مشكلة غامضة
في أواخر عام 2017 ، تلقيت مكالمة لمناقشة مشكلة مع تطبيق Netflix على جهاز فك التشفير الجديد. لقد كان تلفزيون Android جديدًا قادرًا على 4K استنادًا إلى إصدار Android Open Source Project (AOSP) 5.0 ، Lollipop. لقد عملت في Netflix لعدة سنوات وساعدت في إطلاق بعض الأجهزة ، ولكن كان هذا أول تلفزيون يعمل بنظام Android.
كانت الأطراف الأربعة على اتصال: شركة تلفزيونية أوروبية كبيرة أطلقت الجهاز (المشغل) ، ومتكامل للبرامج الثابتة (متكامل) ، ومورد نظام على شريحة (مورد شرائح) ، وأنا (Netflix).
أكملت شركة الدمج و Netflix بالفعل عملية اعتماد Netflix الصارمة ، ولكن أثناء اختبار داخلي مع المشغل ، أبلغ أحد المسؤولين التنفيذيين في الشركة عن مشكلة خطيرة: تأخر تشغيل Netflix ، مما يعني تشغيل الفيديو لوقت قصير جدًا ، ثم توقف مؤقتًا ، ثم توقف مؤقتًا ، ثم توقف مؤقتًا. لم يحدث هذا دائمًا ، لكنه بدأ يتأخر بشكل مطرد بعد أيام قليلة من تشغيل وحدة التحكم. عرضوا الفيديو ، بدا فظيعًا.
وجدت أداة الدمج طريقة لإعادة إظهار المشكلة: قم بتشغيل Netflix عدة مرات ، وابدأ التشغيل ، ثم العودة إلى واجهة المستخدم. قدموا سيناريو لأتمتة العملية. استغرق الأمر أحيانًا ما يصل إلى خمس دقائق ، لكن السيناريو دائمًا ما يعيد إنتاج الخطأ بشكل موثوق.
وفي الوقت نفسه ، قام مهندس في أحد موردي الشرائح بتشخيص السبب الجذري: لم يتمكن تطبيق Netflix Android TV المسمى Ninja من توصيل البيانات الصوتية. تحدث التأخيرات بسبب التخفيضات في خط أنابيب صوت الأجهزة. توقف التشغيل عندما كانت وحدة فك التشفير تنتظر جزءًا من دفق الصوت من Ninja ، ثم استؤنف عند وصول بيانات جديدة. اعتقد كل من عامل التكامل ومورد الرقائق والمشغل أن المشكلة كانت واضحة. وقد نظروا إليّ جميعًا: Netflix ، لديك خطأ في تطبيقك وتحتاج إلى إصلاحه. سمعت التوتر في صوت مندوب الشركة. تم تأخير إصدار الجهاز وزيادة الميزانية ، وتوقعوا مني النتائج.
تحقيق
كنت متشككا. يعمل تطبيق Ninja نفسه على ملايين أجهزة Android TV ، بما في ذلك أجهزة التلفزيون الذكية وأجهزة فك التشفير الأخرى. إذا كان هناك خطأ في Ninja ، فلماذا يحدث فقط على هذا الجهاز؟
لقد بدأت بتكرار المشكلة بنفسي باستخدام برنامج نصي من وحدة الدمج. اتصلت بزميل من الشركة المصنعة للرقاقة وسألته عما إذا كان قد رأى شيئًا كهذا (لم يُر). ثم بدأت في دراسة شفرة مصدر Ninja. كان من الضروري العثور على الشفرة الدقيقة المسؤولة عن تسليم البيانات الصوتية. لقد اكتشفت الكثير ، لكنني بدأت أضيع في الكود المسؤول عن التكاثر ، وكنت بحاجة إلى المساعدة.
صعدت إلى الطابق العلوي ووجدت المهندس الذي كتب خط أنابيب الصوت والفيديو في Ninja ، وعرّفني على الكود. بعد ذلك ، درستها بنفسي لبعض الوقت حتى أفهم أخيرًا الأجزاء الرئيسية وأضف سجلاتي الخاصة. يعد تطبيق Netflix معقدًا ، ولكن بطريقة مبسطة ، يقوم باسترداد البيانات من خادم Netflix ، ويقوم بتخزين بيانات الفيديو والصوت مؤقتًا على الجهاز لبضع ثوان ، ثم يقوم بتسليم إطارات الفيديو والصوت واحدًا تلو الآخر إلى أجهزة فك التشفير.
الشكل: 1. خط أنابيب تشغيل مبسط
دعنا نتحدث عن مسار الصوت / الفيديو في تطبيق Netflix للحظة. قبل "المخزن المؤقت لوحدة فك التشفير" يكون الأمر هو نفسه تمامًا في كل جهاز استقبال وجهاز تلفزيون ، ولكن نقل بيانات A / V إلى المخزن المؤقت لوحدة فك التشفير للجهاز هو إجراء خاص بالجهاز. إنه يعمل على الخيط الخاص به. الغرض من هذا الإجراء هو الحفاظ على امتلاء المخزن المؤقت لوحدة فك الترميز من خلال استدعاء الإطار التالي لبيانات الصوت أو الفيديو من خلال Netflix API. في Ninja ، يتم هذا العمل عن طريق الخيطذكري المظهر. هناك آلة حالة بسيطة وبعض المنطق للتعامل مع حالات التشغيل المختلفة ، ولكن في التشغيل العادي ، ينسخ الدفق إطارًا واحدًا من البيانات إلى واجهة برمجة تطبيقات تشغيل Android ، ثم يخبر جدولة مؤشر الترابط بالانتظار 15 مللي ثانية قبل استدعاء المعالج التالي. عند إنشاء مؤشر ترابط Android ، يمكنك طلب إعادة تشغيل سلسلة الرسائل مثل الحلقة ، ولكن برنامج جدولة مؤشر ترابط Android هو الذي يستدعي المعالج ، وليس التطبيق الخاص بك.
عند 60 إطارًا في الثانية كحد أقصى ، يجب أن يعرض الجهاز إطارًا جديدًا كل 16.66 مللي ثانية ، لذا فإن التحقق بعد 15 مللي ثانية يكفي على أي حال. نظرًا لأن شركة الدمج حددت أن المشكلة كانت في دفق الصوت ، فقد ركزت على المعالج المحدد الذي كان يسلم عينات الصوت إلى خدمة الصوت في Android.
كان من الضروري أن نفهم من أين أتت التأخيرات ، أي التأخير. افترضت أن بعض الوظائف التي دعاها المعالج هي المسؤولة ، لذلك قمت بتشتيت رسائل السجل في جميع أنحاء المعالج وكنت سأعثر بسهولة على الكود الذي تسبب في التأخيرات. سرعان ما أصبح واضحًا أنه لا يوجد شيء خاطئ في المعالج ، وتم تشغيله لبضعة أجزاء من الألف من الثانية حتى عندما كان التشغيل متأخرًا.
نعم ، البصيرة
في النهاية ، ركزت على ثلاثة أرقام: معدل البث بالباود ووقت استدعاء المعالج ووقت نقل التحكم من المعالج إلى Android. لقد كتبت نصًا لتحليل إخراج السجل وقمت بإنشاء الرسم البياني أدناه لعرض الاستجابة. الشكل: 2. تصور عرض النطاق الترددي لدفق الصوت وتوقيتات المعالج الخط البرتقالي هو المعدل الذي يتم به نقل البيانات من المخزن المؤقت للتدفق إلى نظام الصوت Android (بايت لكل مللي ثانية). هناك ثلاثة سيناريوهات مختلفة في هذا الرسم البياني:
- منطقتان بهما قمم عالية ، حيث تصل معدلات البيانات إلى 500 بايت لكل مللي ثانية. يتم تخزين هذه المرحلة مؤقتًا قبل بدء التشغيل. المعالج ينسخ البيانات بأسرع ما يمكن.
- — . 45 .
- , 10 . .
الاستنتاج الحتمي: الخط البرتقالي يؤكد استنتاجات المهندس من شركة الرقائق. في الواقع ، Ninja ليست سريعة بما يكفي لتوصيل البيانات الصوتية.
لفهم السبب ، دعنا نلقي نظرة فاحصة على الخطوط الصفراء والرمادية.
يُظهر الخط الأصفر الوقت المنقضي في إجراء المعالج نفسه ، محسوبًا من الطوابع الزمنية المسجلة في بداية الإجراء ونهايته. في كل من المناطق العادية والمتأخرة ، يكون الوقت في المعالج هو نفسه: حوالي 2 مللي ثانية. تُظهر الصور المتتالية الحالات التي تكون فيها الأوقات أبطأ بسبب المهام الأخرى التي يتم تنفيذها على الجهاز.
السبب الجذري الحقيقي
الخط الرمادي - الوقت بين المكالمات إلى المعالج - يروي قصة مختلفة. في التشغيل العادي ، يتم استدعاء المعالج كل 15 مللي ثانية تقريبًا. في حالة التأخر على اليمين ، يتم استدعاء المعالج كل 55 مللي ثانية تقريبًا ، وهناك 40 مللي ثانية إضافية بين المكالمات ، وفي مثل هذه الحالة لا يمكنه مواكبة التشغيل. لكن لماذا؟
لقد أبلغت عن اكتشافي للمتكامل ومورد الشرائح (انظر ، جدولة البث في Android هي السبب!) ، لكنهم ظلوا يصرون على أن Netflix يجب أن يحل المشكلة. لماذا لا تنسخ المزيد من البيانات في كل مرة يتم استدعاء المعالج؟ كان نقدًا عادلًا ، لكن تنفيذ مثل هذا السلوك يستلزم تغييرات عميقة لم أرغب في الذهاب إليها ، لذلك واصلت البحث عن السبب الجذري. لقد تعمقت في كود مصدر Android واكتشفت أن سلاسل عمليات Android عبارة عن بنية مساحة مستخدم وأن برنامج جدولة مؤشر الترابط يستخدم مكالمة نظام للمزامنة
epoll()
. كنت أعلم أن الأداء
epoll()
ليس مضمونًا ، لذلك اشتبهت في أن شيئًا ما يؤثر عليه بشكل منهجي.
في هذه المرحلة ، تم إنقاذي بواسطة مهندس آخر من مورد الرقائق الذي اكتشف خطأ تم إصلاحه بالفعل في الإصدار التالي من Android (Marshmallow). اتضح أن برنامج جدولة مؤشر ترابط Android يغير سلوك سلاسل الرسائل اعتمادًا على ما إذا كان التطبيق يعمل في المقدمة أو في الخلفية. يتم تعيين زمن انتقال إضافي 40 مللي ثانية (40000000 نانوثانية) مؤشرات الترابط الخلفية.
يعني وجود خلل عميق في جوهر Android أن قيمة المؤقت الإضافية هذه استمرت عند ظهور الخيط في المقدمة. عادة ، تم إنشاء مؤشر ترابط المعالج الصوتي عندما كان التطبيق في المقدمة ، ولكن في بعض الأحيان في وقت أبكر قليلاً عندما كان Ninja لا يزال في الخلفية. إذا حدث هذا ، سيبدأ التشغيل في التأخر.
الدروس المستفادة
لم يكن هذا هو الخطأ الأخير الذي قمنا بإصلاحه على نظام Android الأساسي ، ولكن كان من الصعب تعقبه. كان خارج تطبيق Netflix وحتى خارج خط أنابيب التشغيل ، وأشارت جميع البيانات الأولية إلى وجود خطأ في تطبيق Netflix نفسه.
توضح القصة جانبًا أحبه من وظيفتي: من المستحيل توقع جميع المشكلات التي سيلقيها شركاؤنا علي. وأعلم أن حلها يتطلب فهم الكثير من الأنظمة ، والعمل مع زملاء رائعين ، ودفع نفسك باستمرار لتعلم أشياء جديدة. ما أفعله له تأثير مباشر على الأشخاص الحقيقيين وتمتعهم بمنتج رائع. عندما يستمتع الناس بمشاهدة Netflix في غرفة معيشتهم ، أعلم أنني جزء من الفريق الذي جعل ذلك ممكنًا.