تحديد التشويش المرتبط بالارتعاش

الارتعاش هو سلوك النظام العشوائي الذي يمنع تشغيل العمل الملموس. توضح هذه الصفحة كيفية تحديد المشكلات غير المرغوب فيها المتعلقة بعدم الاستقرار ومعالجتها.

تأخير جدولة موضوع التطبيق

يعد تأخير المجدول من أكثر أعراض عدم الاستقرار وضوحًا: تصبح العملية التي يجب تشغيلها قابلة للتشغيل ولكنها لا تعمل لفترة طويلة من الوقت. وتختلف أهمية التأخير باختلاف السياق. على سبيل المثال:

  • من المحتمل أن يتأخر مؤشر ترابط مساعد عشوائي في أحد التطبيقات لعدة أجزاء من الثانية دون حدوث مشكلة.
  • قد يكون مؤشر ترابط واجهة المستخدم الخاص بالتطبيق قادرًا على تحمل 1-2 مللي ثانية من الارتعاش.
  • قد تتسبب برامج التشغيل kthreads التي تعمل كـ SCHED_FIFO في حدوث مشكلات إذا كانت قابلة للتشغيل لـ 500us قبل التشغيل.

يمكن تحديد الأوقات القابلة للتشغيل في systrace من خلال الشريط الأزرق الذي يسبق الجزء الجاري من سلسلة المحادثات. يمكن أيضًا تحديد الوقت القابل للتشغيل من خلال طول الفترة الزمنية بين حدث sched_wakeup لسلسلة رسائل وحدث sched_switch الذي يشير إلى بداية تنفيذ سلسلة المحادثات.

المواضيع التي تعمل لفترة طويلة جدا

يمكن أن تتسبب سلاسل عمليات واجهة مستخدم التطبيق القابلة للتشغيل لفترة طويلة جدًا في حدوث مشكلات. عادةً ما يكون لسلاسل العمليات ذات المستوى الأدنى ذات أوقات التشغيل الطويلة أسباب مختلفة، ولكن محاولة دفع وقت تشغيل سلاسل رسائل واجهة المستخدم نحو الصفر قد يتطلب إصلاح بعض المشكلات نفسها التي تتسبب في جعل سلاسل العمليات ذات المستوى الأدنى أوقاتًا طويلة قابلة للتشغيل. للتخفيف من التأخير:

  1. استخدم وحدات المعالجة المركزية كما هو موضح في الاختناق الحراري .
  2. قم بزيادة قيمة CONFIG_HZ.
    • تاريخيًا، تم تعيين القيمة على 100 على منصات Arm وarm64. ومع ذلك، يعد هذا مجرد حادث تاريخي ولا يمثل قيمة جيدة لاستخدامه في الأجهزة التفاعلية. CONFIG_HZ=100 يعني أن مدة لمح البصر هي 10 مللي ثانية، مما يعني أن موازنة التحميل بين وحدات المعالجة المركزية (CPUs) قد تستغرق 20 مللي ثانية (لحظتان). يمكن أن يساهم هذا بشكل كبير في حدوث مخلفات على نظام محمل.
    • تم شحن الأجهزة الحديثة (Nexus 5X وNexus 6P وPixel وPixel XL) مع CONFIG_HZ=300. يجب أن يكون لهذا تكلفة طاقة ضئيلة مع تحسين أوقات التشغيل بشكل ملحوظ. إذا لاحظت زيادات كبيرة في استهلاك الطاقة أو مشكلات في الأداء بعد تغيير CONFIG_HZ، فمن المحتمل أن أحد برامج التشغيل لديك يستخدم مؤقتًا يعتمد على صور مؤقتة أولية بدلاً من المللي ثانية ويتحول إلى صور مؤقتة. عادةً ما يكون هذا حلاً سهلاً (راجع التصحيح الذي أصلح مشكلات مؤقتkgsl على Nexus 5X و6P عند التحويل إلى CONFIG_HZ=300).
    • أخيرًا، قمنا بتجربة CONFIG_HZ=1000 على Nexus/Pixel ووجدنا أنه يقدم أداءً ملحوظًا ويقلل الطاقة بسبب انخفاض حمل RCU.

مع هذين التغييرين فقط، يجب أن يبدو الجهاز أفضل بكثير بالنسبة للوقت القابل للتشغيل لمؤشر ترابط واجهة المستخدم أثناء التحميل.

باستخدام sys.use_fifo_ui

يمكنك محاولة دفع الوقت القابل للتشغيل لمؤشر ترابط واجهة المستخدم إلى الصفر عن طريق تعيين الخاصية sys.use_fifo_ui على 1.

تحذير : لا تستخدم هذا الخيار في تكوينات وحدة المعالجة المركزية غير المتجانسة إلا إذا كان لديك برنامج جدولة RT مدرك للسعة. وفي هذه اللحظة، لا يوجد برنامج جدولة شحن حاليًا يتعرف على السعة . نحن نعمل على واحد لـ EAS، ولكنه غير متوفر بعد. يعتمد برنامج جدولة RT الافتراضي بشكل كامل على أولويات RT وما إذا كانت وحدة المعالجة المركزية لديها بالفعل مؤشر ترابط RT ذي أولوية مساوية أو أعلى.

نتيجة لذلك، سيقوم برنامج جدولة RT الافتراضي بسعادة بنقل مؤشر ترابط واجهة المستخدم الذي يعمل لفترة طويلة نسبيًا من نواة كبيرة عالية التردد إلى نواة صغيرة عند الحد الأدنى من التردد إذا حدث أن استيقظ مؤشر FIFO k ذو الأولوية الأعلى على نفس النواة الكبيرة. سيؤدي هذا إلى حدوث تراجعات كبيرة في الأداء . نظرًا لأن هذا الخيار لم يتم استخدامه بعد على جهاز Android قيد الشحن، إذا كنت تريد استخدامه، فاتصل بفريق أداء Android لمساعدتك في التحقق من صحته.

عند تمكين sys.use_fifo_ui ، يقوم ActivityManager بتتبع مؤشر ترابط واجهة المستخدم وRenderThread (أكثر سلاسل الرسائل أهمية لواجهة المستخدم) للتطبيق العلوي ويجعل سلاسل الرسائل هذه SCHED_FIFO بدلاً من SCHED_OTHER. يؤدي هذا إلى إزالة الارتعاش بشكل فعال من واجهة المستخدم وRenderThreads؛ تُظهر الآثار التي جمعناها مع تمكين هذا الخيار أوقاتًا قابلة للتشغيل بترتيب ميكروثانية بدلاً من المللي ثانية.

ومع ذلك، نظرًا لأن موازن تحميل RT لم يكن مدركًا للسعة، فقد حدث انخفاض بنسبة 30% في أداء بدء تشغيل التطبيق لأن مؤشر ترابط واجهة المستخدم المسؤول عن بدء تشغيل التطبيق سيتم نقله من نواة Kryo الذهبية بسرعة 2.1 جيجا هرتز إلى نواة Kryo الفضية بسرعة 1.5 جيجا هرتز . باستخدام موازن أحمال RT المدرك للسعة، نرى أداءً مكافئًا في العمليات المجمعة وانخفاضًا بنسبة 10-15% في أوقات الإطارات المئوية 95 و99 في العديد من معايير واجهة المستخدم الخاصة بنا.

مقاطعة حركة المرور

نظرًا لأن منصات ARM توفر المقاطعات لوحدة المعالجة المركزية 0 فقط بشكل افتراضي، فإننا نوصي باستخدام موازن IRQ (irqbalance أو msm_irqbalance على منصات Qualcomm).

أثناء تطوير Pixel، رأينا مخلفات يمكن أن تعزى مباشرة إلى إرهاق وحدة المعالجة المركزية 0 بالمقاطعات. على سبيل المثال، إذا تمت جدولة مؤشر الترابط mdss_fb0 على وحدة المعالجة المركزية 0، فسيكون هناك احتمال أكبر بكثير للتعطيل بسبب المقاطعة التي يتم تشغيلها بواسطة الشاشة على الفور تقريبًا قبل المسح. سيكون mdss_fb0 في منتصف عمله مع موعد نهائي ضيق للغاية، وبعد ذلك سيفقد بعض الوقت لمعالج مقاطعة MDSS. في البداية، حاولنا إصلاح ذلك عن طريق تعيين تقارب وحدة المعالجة المركزية لمؤشر الترابط mdss_fb0 إلى وحدات المعالجة المركزية 1-3 لتجنب التعارض مع المقاطعة، لكننا أدركنا بعد ذلك أننا لم نقم بتمكين msm_irqbalance بعد. مع تمكين msm_irqbalance، تم تحسين البيانات غير المرغوب فيها بشكل ملحوظ حتى عندما كان كل من mdss_fb0 ومقاطعة MDSS على نفس وحدة المعالجة المركزية (CPU) بسبب انخفاض التنافس من المقاطعات الأخرى.

يمكن التعرف على ذلك في systrace من خلال النظر إلى قسم sched بالإضافة إلى قسم irq. يعرض قسم الجدولة ما تمت جدولته، ولكن المنطقة المتداخلة في قسم irq تعني أن المقاطعة قيد التشغيل خلال ذلك الوقت بدلاً من العملية المجدولة عادةً. إذا رأيت أجزاء كبيرة من الوقت المستغرق أثناء المقاطعة، فستتضمن خياراتك ما يلي:

  • جعل معالج المقاطعة أسرع.
  • منع المقاطعة من الحدوث في المقام الأول.
  • قم بتغيير تردد المقاطعة ليكون خارج الطور مع الأعمال العادية الأخرى التي قد تتداخل معها (إذا كانت مقاطعة عادية).
  • قم بتعيين تقارب وحدة المعالجة المركزية للمقاطعة مباشرة ومنعها من التوازن.
  • قم بتعيين تقارب وحدة المعالجة المركزية (CPU) للخيط الذي تتداخل معه المقاطعة لتجنب المقاطعة.
  • اعتمد على موازن المقاطعة لنقل المقاطعة إلى وحدة المعالجة المركزية (CPU) الأقل تحميلًا.

لا يُنصح عمومًا بتعيين تقارب وحدة المعالجة المركزية (CPU)، ولكنه قد يكون مفيدًا لحالات معينة. بشكل عام، من الصعب جدًا التنبؤ بحالة النظام بالنسبة لمعظم المقاطعات الشائعة، ولكن إذا كان لديك مجموعة محددة جدًا من الشروط التي تؤدي إلى مقاطعات معينة حيث يكون النظام مقيدًا أكثر من المعتاد (مثل VR)، فقد يكون هناك تقارب صريح لوحدة المعالجة المركزية (CPU) يكون حلا جيدا.

سوفتيركس طويلة

أثناء تشغيل softirq، فإنه يقوم بتعطيل الشفعة. يمكن أيضًا تشغيل softirqs في العديد من الأماكن داخل kernel ويمكن تشغيله داخل عملية المستخدم. إذا كان هناك ما يكفي من نشاط softirq، فستتوقف عمليات المستخدم عن تشغيل softirqs، وينشط ksoftirqd لتشغيل softirqs وتكون متوازنة التحميل. عادة، هذا جيد. ومع ذلك، يمكن لـ softirq واحد طويل جدًا أن يلحق الضرر بالنظام.


تكون softirqs مرئية داخل قسم irq الخاص بالتتبع، لذا يسهل اكتشافها إذا كان من الممكن تكرار المشكلة أثناء التتبع. نظرًا لأنه يمكن تشغيل softirq ضمن عملية المستخدم، فمن الممكن أيضًا أن يظهر softirq السيئ كوقت تشغيل إضافي داخل عملية المستخدم بدون سبب واضح. إذا رأيت ذلك، فراجع قسم irq لمعرفة ما إذا كان اللوم يقع على softirqs.

برامج التشغيل التي تترك إجراءات الشفعة أو طلبات المقاطعة (IRQs) معطلة لفترة طويلة جدًا

يؤدي تعطيل الإجراءات الاستباقية أو المقاطعات لفترة طويلة جدًا (عشرات المللي ثانية) إلى حدوث أخطاء غير مرغوب فيها. عادةً ما تظهر الملفات غير المرغوب فيها على شكل خيط يصبح قابلاً للتشغيل ولكنه لا يعمل على وحدة المعالجة المركزية (CPU) معينة، حتى لو كان الخيط القابل للتشغيل ذو أولوية أعلى بكثير (أو SCHED_FIFO) من الخيط الآخر.

بعض الإرشادات:

  • إذا كان مؤشر الترابط القابل للتشغيل هو SCHED_FIFO وكان مؤشر الترابط قيد التشغيل هو SCHED_OTHER، فهذا يعني أن مؤشر الترابط قيد التشغيل تم تعطيله أو تعطيل المقاطعات.
  • إذا كان مؤشر الترابط القابل للتشغيل ذو أولوية أعلى بكثير (100) من مؤشر الترابط قيد التشغيل (120)، فمن المحتمل أن يكون لمؤشر الترابط الجاري تشغيله ميزة الاستباقية أو المقاطعات المعطلة إذا لم يتم تشغيل مؤشر الترابط القابل للتشغيل خلال لحظتين.
  • إذا كان الخيط القابل للتشغيل والخيط قيد التشغيل لهما نفس الأولوية، فمن المحتمل أن يكون للخيط قيد التشغيل ميزة الشفعة أو المقاطعات معطلة إذا لم يعمل الخيط القابل للتشغيل خلال 20 مللي ثانية.

ضع في اعتبارك أن تشغيل معالج المقاطعة يمنعك من خدمة المقاطعات الأخرى، مما يؤدي أيضًا إلى تعطيل الإجراء الاستباقي.


هناك خيار آخر لتحديد المناطق المخالفة وهو استخدام أداة التتبع preemptirqsoff (انظر استخدام ftrace الديناميكي ). يمكن أن يوفر هذا التتبع رؤية أكبر بكثير للسبب الجذري للمنطقة غير المنقطعة (مثل أسماء الوظائف)، ولكنه يتطلب المزيد من العمل الجراحي لتمكينه. على الرغم من أنه قد يكون له تأثير أكبر على الأداء، إلا أنه بالتأكيد يستحق المحاولة.

الاستخدام غير الصحيح لطوابير العمل

غالبًا ما تحتاج معالجات المقاطعة إلى القيام بعمل يمكن تشغيله خارج سياق المقاطعة، مما يتيح العمل على سلاسل عمليات مختلفة في النواة. قد يلاحظ مطور برنامج التشغيل أن kernel لديه وظيفة مهمة غير متزامنة على مستوى النظام مريحة جدًا تسمى قوائم انتظار العمل وقد يستخدمها في العمل المتعلق بالمقاطعة.

ومع ذلك، تكون قوائم انتظار العمل دائمًا هي الإجابة الخاطئة لهذه المشكلة لأنها دائمًا SCHED_OTHER. توجد العديد من مقاطعات الأجهزة في المسار الحرج للأداء ويجب تشغيلها على الفور. ليس لدى قوائم انتظار العمل أي ضمانات بشأن موعد تشغيلها. في كل مرة نرى فيها قائمة انتظار عمل في المسار الحرج للأداء، كانت بمثابة مصدر لمخلفات متفرقة، بغض النظر عن الجهاز. على هاتف Pixel، الذي يستخدم معالجًا رئيسيًا، رأينا أنه يمكن تأخير قائمة انتظار عمل واحدة لمدة تصل إلى 7 مللي ثانية إذا كان الجهاز تحت التحميل اعتمادًا على سلوك المجدول والأشياء الأخرى التي تعمل على النظام.

بدلاً من قائمة انتظار العمل، يجب على برامج التشغيل التي تحتاج إلى التعامل مع العمل الشبيه بالمقاطعة داخل سلسلة رسائل منفصلة إنشاء سلسلة SCHED_FIFO k الخاصة بها. للمساعدة في القيام بذلك باستخدام وظائف kthread_work، راجع هذا التصحيح .

تنافس قفل الإطار

يمكن أن يكون التنافس على قفل إطار العمل مصدرًا للرسائل غير المرغوب فيها أو مشكلات أخرى في الأداء. يحدث هذا عادةً بسبب قفل ActivityManagerService ولكن يمكن رؤيته في الأقفال الأخرى أيضًا. على سبيل المثال، يمكن أن يؤثر قفل PowerManagerService على أداء الشاشة. إذا كنت ترى هذا على جهازك، فليس هناك حل جيد لأنه لا يمكن تحسينه إلا من خلال التحسينات المعمارية لإطار العمل. ومع ذلك، إذا كنت تقوم بتعديل التعليمات البرمجية التي يتم تشغيلها داخل system_server، فمن المهم تجنب الاحتفاظ بالأقفال لفترة طويلة، وخاصة قفل ActivityManagerService.

تنافس قفل الموثق

تاريخيًا، كان للموثق قفل عالمي واحد. إذا تم استباق الخيط الذي يقوم بتشغيل معاملة الموثق أثناء الضغط على القفل، فلن يتمكن أي مؤشر ترابط آخر من إجراء معاملة الموثق حتى يقوم الخيط الأصلي بتحرير القفل. هذا سيء؛ يمكن أن يؤدي تنافس الموثق إلى حظر كل شيء في النظام، بما في ذلك إرسال تحديثات واجهة المستخدم إلى الشاشة (تتواصل سلاسل واجهة المستخدم مع SurfaceFlinger عبر الموثق).

يتضمن Android 6.0 عدة تصحيحات لتحسين هذا السلوك عن طريق تعطيل الإجراء الاستباقي أثناء الضغط على قفل الموثق. كان هذا آمنًا فقط لأنه يجب الاحتفاظ بقفل الموثق لبضعة ميكروثانية من وقت التشغيل الفعلي. أدى هذا إلى تحسين الأداء بشكل كبير في المواقف غير المتوقعة ومنع التنافس عن طريق منع معظم مفاتيح الجدولة أثناء الضغط على قفل الموثق. ومع ذلك، لا يمكن تعطيل الشفعة طوال وقت التشغيل الكامل للاحتفاظ بقفل الموثق، مما يعني أنه تم تمكين الشفعة للوظائف التي يمكن أن تكون في وضع السكون (مثل Copy_from_user)، والتي يمكن أن تسبب نفس الشفعة مثل الحالة الأصلية. عندما أرسلنا التصحيحات إلى المنبع، أخبرونا على الفور أن هذه كانت أسوأ فكرة في التاريخ. (لقد اتفقنا معهم، ولكننا لم نتمكن أيضًا من الجدال بشأن فعالية الرقع في منع الأشياء الضارة).

تنافس fd داخل العملية

هذا أمر نادر الحدوث. ربما لا يكون السبب وراء ذلك هو نحافتك.

ومع ذلك، إذا كان لديك عدة سلاسل رسائل ضمن عملية تكتب نفس fd، فمن الممكن أن ترى تعارضًا على هذا fd، ولكن المرة الوحيدة التي رأينا فيها ذلك أثناء إحضار Pixel كانت أثناء اختبار حيث حاولت سلاسل الرسائل ذات الأولوية المنخفضة احتلال وحدة المعالجة المركزية بأكملها الوقت أثناء تشغيل مؤشر ترابط واحد عالي الأولوية ضمن نفس العملية. كانت جميع سلاسل الرسائل تكتب إلى علامة التتبع fd ويمكن أن يتم حظر الخيط ذي الأولوية العالية على علامة التتبع fd إذا كان الخيط ذو الأولوية المنخفضة يحمل قفل fd ثم تم استباقيته. عندما تم تعطيل التتبع من سلاسل العمليات ذات الأولوية المنخفضة، لم تكن هناك مشكلة في الأداء.

لم نتمكن من إعادة إنتاج هذا في أي موقف آخر، ولكن من الجدير الإشارة إليه كسبب محتمل لمشكلات الأداء أثناء التتبع.

التحولات الخمول لوحدة المعالجة المركزية غير الضرورية

عند التعامل مع IPC، وخاصة خطوط الأنابيب متعددة العمليات، فمن الشائع رؤية الاختلافات في سلوك وقت التشغيل التالي:

  1. يعمل الخيط A على وحدة المعالجة المركزية 1.
  2. مؤشر الترابط A ينشط الخيط B.
  3. يبدأ تشغيل مؤشر الترابط B على وحدة المعالجة المركزية 2.
  4. يذهب الخيط "أ" على الفور إلى وضع السكون، ليتم إيقاظه بواسطة الخيط "ب" عندما ينتهي الخيط "ب" من عمله الحالي.

يوجد مصدر شائع للحمل بين الخطوتين 2 و3. إذا كانت وحدة المعالجة المركزية 2 خاملة، فيجب إعادتها إلى حالة نشطة قبل أن يتمكن مؤشر الترابط B من التشغيل. اعتمادًا على SOC ومدى عمق الخمول، قد يستغرق ذلك عشرات الميكروثانية قبل أن يبدأ تشغيل الخيط B. إذا كان وقت التشغيل الفعلي لكل جانب من جوانب IPC قريبًا بدرجة كافية من الحمل الزائد، فيمكن تقليل الأداء الإجمالي لخط الأنابيب هذا بشكل كبير عن طريق التحولات الخاملة لوحدة المعالجة المركزية. المكان الأكثر شيوعًا لـ Android للوصول إلى هذا هو المعاملات الموثقة، والعديد من الخدمات التي تستخدم الموثق ينتهي بها الأمر إلى الظهور كما هو موضح أعلاه.

أولاً، استخدم وظيفة wake_up_interruptible_sync() في برامج تشغيل kernel لديك وادعمها من أي برنامج جدولة مخصص. تعامل مع هذا كشرط، وليس تلميحا. يستخدم Binder هذا اليوم، وهو يساعد كثيرًا في معاملات Binder المتزامنة لتجنب التحولات غير الضرورية لوحدة المعالجة المركزية.

ثانيًا، تأكد من أن أوقات انتقال cpuidle الخاصة بك واقعية وأن مدير cpuidle يأخذها في الاعتبار بشكل صحيح. إذا كانت شركة نفط الجنوب (SOC) الخاصة بك تدخل وتخرج من أعمق حالة خمول لديك، فلن تتمكن من توفير الطاقة بالذهاب إلى أعمق حالة خمول.

تسجيل

التسجيل ليس مجانيًا لدورات وحدة المعالجة المركزية أو الذاكرة، لذا لا تقم بإرسال بريد عشوائي إلى المخزن المؤقت للسجل. دورات تكاليف التسجيل في التطبيق الخاص بك (مباشرة) وفي البرنامج الخفي للسجل. قم بإزالة أي سجلات تصحيح قبل شحن جهازك.

مشاكل الإدخال/الإخراج

تعد عمليات الإدخال/الإخراج من المصادر الشائعة لعدم الاستقرار. إذا وصل مؤشر الترابط إلى ملف معين للذاكرة ولم تكن الصفحة موجودة في ذاكرة التخزين المؤقت للصفحة، فإنه يخطئ ويقرأ الصفحة من القرص. يؤدي هذا إلى حظر الخيط (عادةً لمدة تزيد عن 10 مللي ثانية) وإذا حدث ذلك في المسار الحرج لعرض واجهة المستخدم، فقد يؤدي ذلك إلى حدوث أخطاء غير مرغوب فيها. هناك أسباب كثيرة جدًا لعمليات الإدخال/الإخراج يجب مناقشتها هنا، ولكن تحقق من المواقع التالية عند محاولة تحسين سلوك الإدخال/الإخراج:

  • خدمة بينر . تمت إضافة PinnerService في Android 7.0، وهو يمكّن إطار العمل من قفل بعض الملفات في ذاكرة التخزين المؤقت للصفحة. يؤدي هذا إلى إزالة الذاكرة لاستخدامها من خلال أي عملية أخرى، ولكن إذا كانت هناك بعض الملفات المعروفة مسبقًا بأنها تستخدم بانتظام، فقد يكون من الفعال التحكم في تلك الملفات.

    على أجهزة Pixel وNexus 6P التي تعمل بنظام التشغيل Android 7.0، قمنا بحفظ أربعة ملفات:
    • /system/framework/arm64/boot-framework.oat
    • /system/framework/oat/arm64/services.odex
    • /system/framework/arm64/boot.oat
    • /system/framework/arm64/boot-core-libart.oat
    يتم استخدام هذه الملفات باستمرار بواسطة معظم التطبيقات وخادم النظام، لذا لا ينبغي ترحيلها. وعلى وجه الخصوص، وجدنا أنه إذا تمت ترحيل أي من هذه التطبيقات، فسيتم ترحيلها مرة أخرى وتتسبب في حدوث أخطاء غير مرغوب فيها عند التبديل من تطبيق ثقيل الوزن.
  • التشفير . سبب آخر محتمل لمشاكل الإدخال/الإخراج. نجد أن التشفير المضمن يقدم أفضل أداء عند مقارنته بالتشفير المعتمد على وحدة المعالجة المركزية (CPU) أو باستخدام كتلة الأجهزة التي يمكن الوصول إليها عبر DMA. والأهم من ذلك، أن التشفير المضمن يقلل من الارتعاش المرتبط بالإدخال/الإخراج، خاصة عند مقارنته بالتشفير المعتمد على وحدة المعالجة المركزية (CPU). نظرًا لأن عمليات الجلب إلى ذاكرة التخزين المؤقت للصفحة تكون غالبًا في المسار الحرج لعرض واجهة المستخدم، فإن التشفير المعتمد على وحدة المعالجة المركزية يقدم حملًا إضافيًا لوحدة المعالجة المركزية في المسار الحرج، مما يضيف المزيد من الارتعاش أكثر من مجرد جلب الإدخال/الإخراج.

    تواجه محركات تشفير الأجهزة المستندة إلى DMA مشكلة مماثلة، حيث يتعين على النواة قضاء دورات في إدارة هذا العمل حتى لو كانت هناك أعمال مهمة أخرى متاحة للتشغيل. نوصي بشدة أي بائع SOC ببناء أجهزة جديدة تتضمن دعمًا للتشفير المضمن.

تعبئة المهام الصغيرة العدوانية

تقدم بعض برامج الجدولة الدعم لتعبئة المهام الصغيرة في مراكز وحدة المعالجة المركزية الفردية لمحاولة تقليل استهلاك الطاقة عن طريق إبقاء المزيد من وحدات المعالجة المركزية في وضع الخمول لفترة أطول. على الرغم من أن هذا يعمل بشكل جيد فيما يتعلق بالإنتاجية واستهلاك الطاقة، إلا أنه يمكن أن يكون كارثيًا على زمن الوصول. هناك عدة سلاسل رسائل قصيرة التشغيل في المسار الحرج لعرض واجهة المستخدم والتي يمكن اعتبارها صغيرة؛ إذا تأخرت هذه المواضيع بسبب ترحيلها ببطء إلى وحدات المعالجة المركزية (CPUs) الأخرى، فسوف يتسبب ذلك في حدوث خلل. نوصي باستخدام حزم المهام الصغيرة بشكل متحفظ للغاية.

تحطيم ذاكرة التخزين المؤقت للصفحة

قد يصبح الجهاز الذي لا يحتوي على ذاكرة خالية كافية فجأة بطيئًا للغاية أثناء إجراء عملية طويلة الأمد، مثل فتح تطبيق جديد. قد يكشف تتبع التطبيق أنه محظور باستمرار في الإدخال/الإخراج أثناء تشغيل معين حتى عندما لا يكون محظورًا في الإدخال/الإخراج. عادةً ما يكون هذا علامة على تحطيم ذاكرة التخزين المؤقت للصفحة، خاصة على الأجهزة ذات الذاكرة الأقل.

إحدى الطرق للتعرف على ذلك هي أخذ تتبع النظام باستخدام علامة pagecache والخلاصة التي تتبع البرنامج النصي على system/extras/pagecache/pagecache.py . يقوم pagecache.py بترجمة الطلبات الفردية لتعيين الملفات في ذاكرة التخزين المؤقت للصفحة إلى إحصائيات مجمعة لكل ملف. إذا وجدت أن عدد وحدات البايت من الملف التي تمت قراءتها أكبر من الحجم الإجمالي لذلك الملف الموجود على القرص، فمن المؤكد أنك تقوم بتحطيم ذاكرة التخزين المؤقت للصفحة.

ما يعنيه هذا هو أن مجموعة العمل التي يتطلبها عبء العمل الخاص بك (عادةً تطبيق واحد بالإضافة إلى خادم_النظام) أكبر من مقدار الذاكرة المتوفرة لذاكرة التخزين المؤقت للصفحة على جهازك. ونتيجة لذلك، نظرًا لأن جزءًا واحدًا من حمل العمل يحصل على البيانات التي يحتاجها في ذاكرة التخزين المؤقت للصفحة، فسيتم إزالة جزء آخر سيتم استخدامه في المستقبل القريب وسيتعين جلبه مرة أخرى، مما يتسبب في حدوث المشكلة مرة أخرى حتى يتم التحميل أكملت. هذا هو السبب الأساسي لمشاكل الأداء عند عدم توفر ذاكرة كافية على الجهاز.

لا توجد طريقة مضمونة لإصلاح تحطيم ذاكرة التخزين المؤقت للصفحة، ولكن هناك عدة طرق لمحاولة تحسين ذلك على جهاز معين.

  • استخدام ذاكرة أقل في العمليات المستمرة. كلما قلت الذاكرة المستخدمة من قبل العمليات المستمرة، زادت الذاكرة المتاحة للتطبيقات وذاكرة التخزين المؤقت للصفحة.
  • قم بمراجعة النقوش الموجودة بجهازك للتأكد من أنك لا تقوم بإزالة الذاكرة من نظام التشغيل دون داع. لقد رأينا مواقف تم فيها ترك المنحوتات المستخدمة لتصحيح الأخطاء عن طريق الخطأ في شحن تكوينات kernel، مما يستهلك عشرات الميجابايت من الذاكرة. يمكن أن يحدث هذا فرقًا بين ضرب ذاكرة التخزين المؤقت للصفحة وعدم القيام بذلك، خاصة على الأجهزة ذات الذاكرة الأقل.
  • إذا كنت ترى تعطل ذاكرة التخزين المؤقت للصفحة في system_server على الملفات المهمة، ففكر في تثبيت هذه الملفات. سيؤدي هذا إلى زيادة ضغط الذاكرة في مكان آخر، ولكنه قد يعدل السلوك بدرجة كافية لتجنب الضرب.
  • قم بإعادة ضبط lowmemorykiller لمحاولة الحفاظ على المزيد من الذاكرة خالية. تعتمد حدود lowmemorykiller على كل من الذاكرة الحرة المطلقة وذاكرة التخزين المؤقت للصفحة، لذا فإن زيادة الحد الذي يتم عنده إيقاف العمليات عند مستوى oom_adj معين قد يؤدي إلى سلوك أفضل على حساب زيادة موت تطبيقات الخلفية.
  • حاول استخدام ZRAM. نحن نستخدم ZRAM على Pixel، على الرغم من أن Pixel به 4 غيغابايت، لأنه يمكن أن يساعد في التعامل مع الصفحات المتسخة التي نادرًا ما يتم استخدامها.