SDV में सेवा की क्वालिटी को शेड्यूल करना

एसडीवी की सेवा की क्वालिटी (QoS) का शेड्यूलिंग फ़्रेमवर्क, लाइफ़साइकल मैनेजर (एलएम) से मैनेज किए जाने वाले सर्विस बंडल के लिए, सीपीयू संसाधन का तय आवंटन करता है. यह प्लैटफ़ॉर्म, Linux के शेड्यूलिंग एट्रिब्यूट (नीति, प्राथमिकता, नाइस) को लॉजिकल प्रीसेट में बदलकर, सेवा के विकास और पूरे वाहन के सिस्टम ट्यूनिंग के बीच अंतर करने की सुविधा देता है. इससे सुरक्षा के लिहाज़ से ज़रूरी और समय के हिसाब से संवेदनशील वर्कलोड के लिए, ज़रूरी कंप्यूट बैंडविड्थ उपलब्ध कराने में मदद मिलती है. साथ ही, सिस्टम बैकग्राउंड टास्क को सीमित करता है, ताकि सिस्टम में कोई गड़बड़ी न हो.

भूमिकाएं और ज़िम्मेदारियां

एसडीवी के शेड्यूलिंग मॉडल में, ज़िम्मेदारी सौंपने के पैटर्न का इस्तेमाल किया जाता है. इससे यह पक्का करने में मदद मिलती है कि सेवाएं पोर्टेबल बनी रहें. साथ ही, ओईएम को सिस्टम को ट्यून करने की अनुमति मिलती है.

भूमिका ज़िम्मेदारी मुख्य डिलीवरेबल
SDV प्लैटफ़ॉर्म (Google) यह sdv_service_bundles_scheduling.proto स्कीमा तय करता है, एलएम लागू करने का लॉजिक लागू करता है, और sdv_service_bundles_scheduling क्लाइंट लाइब्रेरी उपलब्ध कराता है. प्रोटोबफ़ की परिभाषाएं और प्लैटफ़ॉर्म लाइब्रेरी
ओईएम (सिस्टम इंटिग्रेटर) यह हर प्रीसेट के लिए कॉन्क्रीट वैल्यू तय करता है. जैसे, किसी खास हार्डवेयर पर ELEVATED का क्या मतलब है. साथ ही, यह सिस्टम-वाइड कॉन्फ़िगरेशन को कंट्रोल करता है. /product/etc/lifecycle_config.textproto
सेवा डेवलपर यह सही लॉजिकल प्रीसेट का नाम चुनता है और scheduling_config.textproto पाथ को सेवा बंडल मेनिफ़ेस्ट में रजिस्टर करता है. scheduling_config.textproto और sdv_service_bundles_manifest.textproto

तकनीकी वर्कफ़्लो

  1. प्लैटफ़ॉर्म इंटिग्रेशन: OEM, वाहन के हिसाब से lifecycle_config.textproto तय करता है. यह फ़ाइल, सिस्टम-वाइड शेड्यूलिंग प्रोफ़ाइल (प्रीसेट) सेट करती है. साथ ही, टारगेट हार्डवेयर के आधार पर, उन्हें Linux शेड्यूलिंग एट्रिब्यूट के साथ मैप करती है.
  2. सर्विस बंडल डेवलपमेंट: डेवलपर, अपने APEX पैकेज में scheduling_config.textproto को बंडल करता है. साथ ही, लॉजिकल प्रीसेट (उदाहरण के लिए, ELEVATED) का सुझाव देता है और इंटरनल थ्रेड के नाम तय करता है.
  3. सेवा बंडल का इंटिग्रेशन: वाहन के इंटिग्रेशन के दौरान, OEM डेवलपर के सुझाए गए प्रीसेट की समीक्षा करता है. OEM के पास, सुझाई गई प्रोफ़ाइल को बनाए रखने या उसे बदलने का विकल्प होता है. जैसे, APEX पर हस्ताक्षर करने से पहले, सिस्टम की स्थिरता को बेहतर बनाने के लिए, ELEVATED सेवा को NORMAL पर डाउनग्रेड करना.
  4. रनटाइम एट्रिब्यूट रिज़ॉल्यूशन: जब कोई सेवा शुरू की जाती है, तो एलएम, सेवा के मेनिफ़ेस्ट से अनुमति वाला प्रीसेट ढूंढता है. इसके बाद, ओईएम के सिस्टम कॉन्फ़िगरेशन से उससे जुड़े Linux एट्रिब्यूट वापस पाता है.
  5. स्टार्टअप सिंक्रनाइज़ेशन और लागू करना: एलएम, सिग्नल-एंड-कंटिन्यू प्रोटोकॉल का इस्तेमाल करके, सेवा प्रोसेस को एक्ज़ीक्यूट करने का सिग्नल देने से पहले, हल किए गए एट्रिब्यूट लागू करता है.

सबसे ज़रूरी सिद्धांत

एसडीवी के शेड्यूल करने के फ़्रेमवर्क के लिए, ये कॉन्सेप्ट ज़रूरी हैं.

प्रीसेट शेड्यूल करना

एसडीवी में क्यूओएस को मैनेज करने के लिए, शेड्यूल करने से जुड़े प्रीसेट मुख्य तरीके हैं. डेवलपर, रॉ Linux शेड्यूलिंग पैरामीटर तय करने के बजाय, पहले से तय किए गए प्रीसेट को नाम से रेफ़रंस करते हैं. रन टाइम के दौरान, एलएम इन लॉजिकल नामों को Linux के शेड्यूलिंग एट्रिब्यूट से मैप करता है.

lifecycle_config.textproto में उदाहरण के तौर पर कॉन्फ़िगर किए गए ये प्रीसेट:

प्रीसेट का नाम शेड्यूल करने की नीति औसत नाइस वैल्यू इस्तेमाल का सामान्य उदाहरण
NORMAL SCHED_OTHER 0 स्टैंडर्ड सेवाएं (एचवीएसी, मीडिया, सेटिंग)
ELEVATED SCHED_OTHER -10 सिस्टम के मुख्य कॉम्पोनेंट और इन्फ़्रास्ट्रक्चर
IDLE SCHED_IDLE 19 बैकग्राउंड में आंकड़ों को इकट्ठा करना और गैर-ज़रूरी लॉगिंग
CUSTOM उपयोगकर्ता की ओर से तय किया गया -20 (शुरुआती) ऐसी सेवाएं जिनके लिए रीयल-टाइम नीतियां या अफ़िनिटी ज़रूरी होती है

प्रीसेट लागू करते समय, एलएम setpriority सिस्टम कॉल का इस्तेमाल करके, पूरी प्रोसेस के लिए nice वैल्यू सेट करता है. इससे, डिफ़ॉल्ट Linux Completely Fair Scheduler (CFS) के तहत, सीपीयू के उस हिस्से पर असर पड़ता है जो प्रोसेस को मिलता है.

खास अधिकार और सुरक्षा

बिना अनुमति के प्राथमिकता बढ़ाने से रोकने के लिए, SDV प्लैटफ़ॉर्म, SELinux डोमेन और Linux की क्षमताओं पर आधारित सुरक्षा मॉडल का इस्तेमाल करता है.

सुरक्षा डोमेन

  • untrusted_service_bundle: यह स्टैंडर्ड प्रीसेट (NORMAL, ELEVATED, IDLE) के लिए डिफ़ॉल्ट डोमेन है. कर्नल इस डोमेन में प्रोसेस को सीमित करता है, ताकि वे अपने शेड्यूलिंग पैरामीटर में बदलाव न कर सकें.
  • priority_service_bundle: यह किसी भी सेवा बंडल को दिया जाता है. इसके लिए, प्रीसेट का इस्तेमाल किया जाता है. इसमें is_privileged: true को पूरे सिस्टम के लिए lifecycle_config.textproto में सेट किया जाता है. इस डोमेन पर ट्रांज़िशन करने से, प्रोसेस को CAP_SYS_NICE की सुविधा मिलती है. इससे प्रोसेस, अपने संसाधन के बंटवारे को मैनेज कर पाती है.

CAP_SYS_NICE क्षमता

यह प्लैटफ़ॉर्म, priority_service_bundle डोमेन में मौजूद प्रोसेस को CAP_SYS_NICE की सुविधा देता है. इस अनुमति से, कोई प्रोसेस ये काम कर सकती है:

  • इसकी nice वैल्यू को शुरुआती असाइनमेंट से ज़्यादा बढ़ाना.
  • क्लास शेड्यूल करने की नीति को रीयल-टाइम क्लास के लिए बनी नीति में बदलें. जैसे, SCHED_FIFO या SCHED_RR.
  • sched_setaffinity का इस्तेमाल करके, सीपीयू अफ़िनिटी सेट करें.
  • SCHED_DEADLINE के लिए, खास समयसीमा वाले पैरामीटर कॉन्फ़िगर करें.

इस सुविधा को किसी खास डोमेन तक सीमित रखने से, पूरे सिस्टम के लिए शेड्यूल किए गए टास्क का बैलेंस बना रहता है. ऐसा इसलिए होता है, क्योंकि इससे साफ़ तौर पर अनुमति वाली सेवाओं में रुकावटें कम होती हैं.

कॉन्फ़िगरेशन गाइड

इस सेक्शन में, ओईएम और सेवा डेवलपर, दोनों के लिए कॉन्फ़िगरेशन से जुड़े दिशा-निर्देश दिए गए हैं.

OEM गाइड: पूरे सिस्टम के लिए प्रीसेट

OEM, /product/etc/lifecycle_config.textproto में शेड्यूलिंग प्रोफ़ाइलें तय करता है. प्लैटफ़ॉर्म, lifecycle_management/config/lifecycle_config.textproto पर एक उदाहरण देता है. OEM को इसे वाहन के हार्डवेयर के हिसाब से अडजस्ट करना होता है.

उदाहरण: रीयल-टाइम प्रीसेट तय करना

ओईएम, सुरक्षा से जुड़ी सेवाओं के लिए CRITICAL प्रीसेट तय कर सकता है. इन सेवाओं को कभी भी स्टैंडर्ड ऐप्लिकेशन से नहीं रोका जाना चाहिए:

# lifecycle_config.textproto
scheduling_presets {
  name: "CRITICAL"
  is_privileged: true
  thread_scheduling_configuration {
    policy: 1      # SCHED_FIFO
    priority: 80   # High real-time priority
  }
}

डेवलपर गाइड: सेवा बंडल का कॉन्फ़िगरेशन

सेवा डेवलपर, प्रीसेट का सुझाव देते हैं. साथ ही, वे चाहें, तो scheduling_config.textproto फ़ाइल में लॉजिकल थ्रेड के नाम तय कर सकते हैं. इस फ़ाइल का पाथ, प्लैटफ़ॉर्म पर दिखने के लिए sdv_service_bundles_manifest.textproto में रजिस्टर होना चाहिए.

उदाहरण: मेनिफ़ेस्ट रजिस्ट्रेशन

# sdv_service_bundles_manifest.textproto
service_bundle_entries {
  name: "SensorService"
  scheduling_config_path: "configs/scheduling_config.textproto"
}

उदाहरण: स्टैंडर्ड प्रीसेट का इस्तेमाल करना

ज़्यादातर सेवाओं के लिए, scheduling_config.textproto में प्रीसेट किए गए नाम का रेफ़रंस देना काफ़ी होता है:

# configs/scheduling_config.textproto
scheduling_preset_name: "ELEVATED"

उदाहरण: सेवा से जुड़ी वर्कर थ्रेड के लिए शेड्यूल करना

सेवा डेवलपर, अपने कोड में अतिरिक्त वर्कर थ्रेड बना सकता है. ऐसा खास टास्क को हैंडल करने के लिए किया जाता है. जैसे, कम समय में सेंसर डेटा लूप करना. डेवलपर, कॉन्फ़िगरेशन फ़ाइल में इन इंटरनल थ्रेड के लिए, नाम वाले शेड्यूल एट्रिब्यूट तय कर सकता है.

मैन्युअल तरीके से लागू करने की सुविधा का इस्तेमाल सिर्फ़ उन सेवाओं में करें जिनके पास यह सुविधा है. ये सेवाएं, इस मेटाडेटा का इस्तेमाल करके, अपने इंटरनल वर्कर थ्रेड के लिए प्रॉपर्टी सेट करती हैं:

# configs/scheduling_config.textproto
scheduling_preset_name: "CUSTOM"

# Map of logical thread names to their attributes (propagated as metadata)
thread_scheduling_configuration {
  key: "sensor-processing-thread"
  value {
    policy: 1        # SCHED_FIFO
    priority: 50
    cpu_affinity_ids: [2, 3]  # Pin to specific cores
  }
}

सिस्टम का व्यवहार और नीति उल्लंघन ठीक करने का तरीका

एसडीवी प्लैटफ़ॉर्म, सेवा से जुड़े किसी कोड को चलाने से पहले, शेड्यूल करने की सेटिंग को चालू करने के लिए, सख्त नियम लागू करता है.

स्टार्टअप के दौरान सिंक करना

किसी सेवा को गलत प्राथमिकता पर चलने से रोकने के लिए, एलएम और सर्विस बंडल रनर (एसबीआर), सिग्नल-एंड-कंटिन्यू सिंक्रनाइज़ेशन प्रोटोकॉल का इस्तेमाल करते हैं. ऐसा सेवा के शुरू होने के दौरान भी किया जाता है:

  1. प्रोसेस बनाना: एलएम, एसबीआर प्रोसेस को फ़ोर्क करता है. इस समय, एसबीआर की चाइल्ड प्रोसेस चल रही होती है, लेकिन तुरंत ब्लॉक हो जाती है. ऐसा इसलिए होता है, क्योंकि यह stdin पर सिग्नल का इंतज़ार कर रही होती है.
  2. एट्रिब्यूट लागू करना: जब चाइल्ड प्रोसेस ब्लॉक हो जाती है, तब एलएम, अनुरोध की गई nice वैल्यू को लागू करने के लिए setpriority सिस्टम कॉल का इस्तेमाल करता है. साथ ही, शेड्यूलिंग की नीति (उदाहरण के लिए, SCHED_IDLE) को कॉन्फ़िगर करता है.
  3. सुरक्षा से जुड़ी ट्रांज़िशन: एलएम, SELinux डोमेन ट्रांज़िशन करता है. इससे चाइल्ड प्रोसेस को untrusted_service_bundle या priority_service_bundle डोमेन में ले जाया जाता है.
  4. सिग्नल: सभी पैरामीटर लागू होने के बाद ही, एलएम बच्चे के stdin को एक बाइट का सिग्नल भेजता है.
  5. एक्ज़ीक्यूशन: एसबीआर को सिग्नल मिलता है. इसके बाद, वह सेवा की लाइब्रेरी लोड करना शुरू कर देता है और लाइफ़साइकल के तरीकों को कॉल करता है.

मुख्य थ्रेड और लाइफ़साइकल पर असर

सेवा की लाइब्रेरी लोड करने से पहले सिंक्रनाइज़ करने पर, प्लैटफ़ॉर्म सभी लाइफ़साइकल कॉलबैक के लिए, मुख्य एक्ज़ीक्यूशन थ्रेड के लिए अनुरोध की गई प्राथमिकता को बनाए रखता है:

  • onCreate: सभी डिपेंडेंसी इंजेक्शन और शुरुआती संसाधन आवंटन, सही प्राथमिकता पर होता है.
  • onStart: प्रीसेट, चालू स्थिति और शुरुआती वर्क लूप में ट्रांज़िशन को कंट्रोल करता है.
  • onStop और onDestroy: प्लैटफ़ॉर्म, शटडाउन के दौरान सिस्टम की ज़रूरी गतिविधियों को बंद होने से रोकने के लिए, एक ही प्राथमिकता पर क्लीनअप ऑपरेशन करता है.

Binder थ्रेड पूल और प्राथमिकता इनहेरिटेंस

प्लैटफ़ॉर्म-मैनेज किए गए बाइंडर थ्रेड पूल में मौजूद थ्रेड, पूल बनाने वाली थ्रेड की प्राथमिकता के साथ काम नहीं करती हैं. इसके बजाय, सिंक्रोनस लेन-देन के लिए, सर्वर थ्रेड को कॉलर की प्राथमिकता मिलती है. बाइंडर कर्नल ड्राइवर, प्राथमिकता इनहेरिटेंस के इस तरीके को कंट्रोल करता है.

थ्रेड-लेवल पर फ़ाइन-ट्यूनिंग

जिन सेवा बंडलों के लिए ज़्यादा कंट्रोल की ज़रूरत होती है (उदाहरण के लिए, रीयल-टाइम प्रोसेसिंग लूप), उन्हें अपनी वर्कर थ्रेड पर मैन्युअल तरीके से कॉन्फ़िगरेशन लागू करने होंगे. थ्रेड-लेवल के कॉन्फ़िगरेशन लागू करने के लिए, यह तरीका अपनाएं:

  1. ऐसे खास प्रीसेट का अनुरोध करें जिसमें is_privileged: true सेट हो.
  2. thread_scheduling_configuration को पढ़ने के लिए, sdv_service_bundles_scheduling लाइब्रेरी से get_scheduling_configuration फ़ंक्शन का इस्तेमाल करें.
  3. sched_setattr का इस्तेमाल करके, वर्कर थ्रेड पर एट्रिब्यूट लागू करें.

SELinux और क्षमताओं को लागू करना

यह प्लैटफ़ॉर्म, SELinux और CAP_SYS_NICE Linux की सुविधा का इस्तेमाल करके, शेड्यूल करने के प्रीसेट लागू करता है:

  • NORMAL या IDLE जैसे प्रीसेट का इस्तेमाल करने वाली सेवाओं के लिए, स्टार्टअप के दौरान एलएम शेड्यूल को कॉन्फ़िगर करता है. इन सेवाओं में CAP_SYS_NICE की सुविधा नहीं है. साथ ही, ये अपनी प्राथमिकता या नीति में बदलाव नहीं कर सकतीं.
  • प्रीसेट (is_privileged: true) का इस्तेमाल करने वाली सेवाओं को CAP_SYS_NICE की सुविधा मिलती है. इससे वे अपनी इंटरनल थ्रेड के लिए, ज़रूरत के मुताबिक मैन्युअल तरीके से शेड्यूलिंग को कंट्रोल कर सकती हैं. यह रीयल-टाइम टास्क के लिए ज़रूरी है.

पुष्टि और सैंपल

शेड्यूलिंग के व्यवहार की पुष्टि करने के लिए, लॉग विश्लेषण और सिस्टम-लेवल की परफ़ॉर्मेंस मेज़रमेंट, दोनों का इस्तेमाल करना ज़रूरी है. एसडीवी प्लैटफ़ॉर्म, इन तकनीकों को दिखाने के लिए एक खास सैंपल उपलब्ध कराता है.

QoS शेड्यूलिंग का सैंपल

samples/qos_scheduling में मौजूद इस सैंपल में, परफ़ॉर्मेंस की जांच करने वाली कई सेवाएं शामिल हैं. इन्हें एक साथ चलाने और इनकी प्रोग्रेस की रिपोर्ट देने के लिए डिज़ाइन किया गया है.

  • PerformanceTesterNormal: NORMAL प्रीसेट के साथ काम करता है.
  • PerformanceTesterElevated: ELEVATED प्रीसेट के साथ काम करता है.
  • PerformanceTesterRealtime: यह CUSTOM प्रीसेट का इस्तेमाल करके, अपने इंटरनल वर्कर थ्रेड पर SCHED_FIFO लागू करता है.
  • PolicyOffender: यह एक डाइग्नोस्टिक सेवा है. यह NORMAL प्रीसेट का इस्तेमाल करते समय, रीयल-टाइम प्राथमिकता सेट करने की कोशिश करती है. इस कुकी का इस्तेमाल यह पुष्टि करने के लिए किया जाता है कि प्लैटफ़ॉर्म, बिना अनुमति के एस्केलेशन को ब्लॉक करता है.

पुष्टि करने वाला सुइट चलाना

  1. QoS के हिसाब से ऑर्केस्ट्रेशन कॉन्फ़िगरेशन चालू करें:

    adb shell setprop persist.sdv.orchestrator_config_path /etc/orch/vm_qos_scheduling_orch_config.textproto

  2. डिवाइस को रीबूट करें, ताकि सेवाएं अपने-अपने शेड्यूल किए गए डोमेन में शुरू हो सकें:

    adb reboot

  3. तुलनात्मक परफ़ॉर्मेंस के नतीजे देखने के लिए, लॉग फ़िल्टर करें:

    adb logcat | grep sdv_sample_qos_common

    PerformanceTesterElevated सेवा ने PerformanceTesterNormal की तुलना में, बहुत ज़्यादा वर्क यूनिट पूरी की हैं. PolicyOffender सेवा के लॉग में, EPERM या SELinux से जुड़ी गड़बड़ियों को शामिल किया गया है.

पिछले वर्शन के गेम खेलने की सुविधा

  • पिछली सेवाओं के साथ काम करने के लिए, अगर कोई लेगसी सेवा बंडल अपने मेनिफ़ेस्ट में scheduling_config_path की जानकारी देता है, लेकिन कॉन्फ़िगरेशन फ़ाइल में scheduling_preset_name की जानकारी नहीं देता है, तो उसे अपने-आप विशेषाधिकार वाली सेवा के तौर पर माना जाता है. इससे उन पुरानी सेवाओं के लिए ज़रूरी सुविधाएं (उदाहरण के लिए, CAP_SYS_NICE) बनी रहती हैं जो थ्रेड को मैन्युअल तरीके से ट्यून करने पर निर्भर करती हैं.
  • रूट कॉन्फ़िगरेशन मैसेज DeadlineSchedulingConfiguration का नाम, आने वाली रिलीज़ में बदला जाएगा. मौजूदा नाम पुराना है और अब यह सही तरीके से नहीं दिखाता कि मैसेज, सभी तरह की शेड्यूलिंग को मैनेज करता है. इसमें सिर्फ़ समयसीमा के हिसाब से शेड्यूलिंग शामिल नहीं है.