واجهة برمجة تطبيقات Performance Hint

تاريخ الإصدار:

Android 12 (المستوى 31) - واجهة برمجة تطبيقات تلميح الأداء

Android 13 (المستوى 33) - مدير تلميحات الأداء في NDK API

(معاينة) Android 15 (DP1) - reportActualWorkDuration()

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

سرعة الساعة

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

الأنواع الأساسية

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

من المفترض ألّا تحاول لعبتك ضبط إعدادات التقارب الأساسية لوحدة المعالجة المركزية (CPU) للأسباب التالية:

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

مثال على سلوك أداة جدولة Linux التلقائية

سلوك أداة جدولة Linux
الشكل 1. قد يستغرق الأمر حوالي 200 ملّي ثانية لزيادة أو خفض تردد وحدة المعالجة المركزية (CPU). تعمل أداة ADPF مع نظام الجهد الديناميكي وقياس الترددات (DVFS) لتقديم أفضل أداء لكل واط.

تستبعد واجهة برمجة التطبيقات PerformanceHint API أكثر من وقت الاستجابة في DVFS.

يستخرج ADPF أكثر من وقت استجابة DVFS
الشكل 2. يعرف ADPF كيفية اتخاذ أفضل قرار نيابةً عنك.
  • إذا كانت هناك حاجة إلى تنفيذ المهام على وحدة معالجة مركزية (CPU) معيّنة، يمكن لواجهة PerformanceHint API معرفة كيفية اتخاذ هذا القرار نيابةً عنك.
  • لذلك، لا تحتاج إلى استخدام التقارب.
  • تأتي الأجهزة بطوابق مختلفة؛ خصائص القوة والحرارة متنوعة جدًا بحيث لا يمكن عرضها لمطور التطبيق.
  • ولا يمكنك وضع أي افتراضات حول النظام الأساسي الذي تعمل عليه.

الحل

يوفّر ADPF السمة PerformanceHintManager حتى تتمكن الألعاب من إرسال تلميحات عن الأداء إلى Android بشأن سرعة ساعة وحدة المعالجة المركزية (CPU) النوع الأساسي. يمكن لنظام التشغيل بعد ذلك تحديد أفضل طريقة لاستخدام التلميحات بناءً على تقنية المنظومة على الرقاقة (SoC) الحل الحراري للجهاز. إذا كان تطبيقك يستخدم واجهة برمجة التطبيقات هذه مع الحرارة مراقبة الحالة، فيمكنها تقديم المزيد من التلميحات المستنيرة لنظام التشغيل بدلاً من استخدام والحلقات المشغولة وتقنيات الترميز الأخرى التي يمكن أن تسبب التقييد.

إليك طريقة استخدام اللعبة لتلميحات الأداء:

  1. إنشاء جلسات تلميحات لسلاسل المحادثات الرئيسية التي تعمل بشكل مشابه مثل:
  2. يجب أن تجري اللعبة ذلك في وقت مبكر، أي 2 ملي ثانية على الأقل، ويفضّل أن تكون أكثر من 4 ملي ثانية. قبل أن تحتاج الجلسة إلى موارد نظام إضافية.
  3. في كل جلسة تلميح، يمكنك توقُّع المدة اللازمة لتشغيل كل جلسة. تعادل المدة النموذجية الفاصل الزمني للإطار، ولكن يمكن للتطبيق استخدام فاصل زمني أقصر في حال لم يتفاوت عبء العمل بشكل كبير على مستوى اللقطات.

إليك كيفية وضع النظرية موضع التنفيذ:

إعداد PerformanceHintManager و createHintSession

اطلب من المدير استخدام خدمة النظام وأنشِئ جلسة تلميحية لسلسلة محادثاتك. أو مجموعة سلاسل محادثات تعمل على نفس عبء العمل

C++‎

int32_t tids[1];
tids[0] = gettid();
int64_t target_fps_nanos = getFpsNanos();
APerformanceHintManager* hint_manager = APerformanceHint_getManager();
APerformanceHintSession* hint_session =
  APerformanceHint_createSession(hint_manager, tids, 1, target_fps_nanos);

Java

int[] tids = {
  android.os.Process.myTid()
};
long targetFpsNanos = getFpsNanos();
PerformanceHintManager performanceHintManager =
  (PerformanceHintManager) this.getSystemService(Context.PERFORMANCE_HINT_SERVICE);
PerformanceHintManager.Session hintSession =
  performanceHintManager.createHintSession(tids, targetFpsNanos);

ضبط سلاسل المحادثات إذا لزم الأمر

تاريخ الإصدار:

Android 11 (المستوى 34)

استخدام setThreads دالة PerformanceHintManager.Session عندما يكون لديك سلاسل محادثات أخرى التي يجب إضافتها لاحقًا. على سبيل المثال، إذا أنشأت خيطًا لعلم الفيزياء لاحقًا وتحتاج إلى إضافتها إلى الجلسة، يمكنك استخدام واجهة برمجة تطبيقات setThreads هذه.

C++‎

auto tids = thread_ids.data();
std::size_t size = thread_ids_.size();
APerformanceHint_setThreads(hint_session, tids, size);

Java

int[] tids = new int[3];

// add all your thread IDs. Remember to use android.os.Process.myTid() as that
// is the linux native thread-id.
// Thread.currentThread().getId() will not work because it is jvm's thread-id.
hintSession.setThreads(tids);

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

الإبلاغ عن مدة العمل الفعلية

يمكنك تتبّع المدة الفعلية اللازمة لإنجاز العمل بالنانو ثانية وإعداد تقرير. إلى النظام عند الانتهاء من العمل في كل دورة. على سبيل المثال، إذا هذا لسلاسل العرض، ويجب استدعائها في كل إطار.

لمعرفة الوقت الفعلي بشكل موثوق، استخدِم:

C++‎

clock_gettime(CLOCK_MONOTONIC, &clock); // if you prefer "C" way from <time.h>
// or
std::chrono::high_resolution_clock::now(); // if you prefer "C++" way from <chrono>

Java

System.nanoTime();

مثلاً:

C++‎

// All timings should be from `std::chrono::steady_clock` or `clock_gettime(CLOCK_MONOTONIC, ...)`
auto start_time = std::chrono::high_resolution_clock::now();

// do work

auto end_time = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::nanoseconds>(end_time - start_time).count();
int64_t actual_duration = static_cast<int64_t>(duration);

APerformanceHint_reportActualWorkDuration(hint_session, actual_duration);

Java

long startTime = System.nanoTime();

// do work

long endTime = System.nanoTime();
long duration = endTime - startTime;

hintSession.reportActualWorkDuration(duration);

تعديل "مدة العمل المستهدفة" عند الضرورة

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

C++‎

APerformanceHint_updateTargetWorkDuration(hint_session, target_duration);

Java

hintSession.updateTargetWorkDuration(targetDuration);