1. نظرة عامة
في حين أنّ مطوّري تطبيقات العميل والويب الأمامي يستخدمون عادةً أدوات مثل محلّل وحدة المعالجة المركزية (CPU) في استوديو Android أو أدوات تحليل الأداء المضمّنة في Chrome لتحسين أداء الرموز البرمجية، لم تكن التقنيات المشابهة متاحة أو مستخدَمة على نطاق واسع من قِبل العاملين على الخدمات الخلفية. توفّر أداة Cloud Profiler هذه الإمكانات نفسها لمطوّري الخدمات، بغض النظر عمّا إذا كان الرمز البرمجي يعمل على Google Cloud Platform أو في مكان آخر.

تجمع الأداة معلومات عن استخدام وحدة المعالجة المركزية وتخصيص الذاكرة من تطبيقات الإنتاج. وتنسب هذه المعلومات إلى الرمز المصدر للتطبيق، ما يساعدك في تحديد أجزاء التطبيق التي تستهلك أكبر قدر من الموارد، كما توضّح خصائص أداء الرمز. إنّ التكلفة المنخفضة لأساليب الجمع التي تستخدمها الأداة تجعلها مناسبة للاستخدام المستمر في بيئات الإنتاج.
في هذا الدرس التطبيقي حول الترميز، ستتعرّف على كيفية إعداد Cloud Profiler لبرنامج Go، وستتعرّف على نوع الإحصاءات التي يمكن أن تقدّمها الأداة حول أداء التطبيق.
ما ستتعلمه
- كيفية ضبط برنامج Go لتسجيل الأداء باستخدام Cloud Profiler
- كيفية جمع بيانات الأداء وعرضها وتحليلها باستخدام Cloud Profiler
المتطلبات
- مشروع Google Cloud Platform
- متصفّح، مثل Chrome أو Firefox
- معرفة جيدة بمحرّرات النصوص القياسية في Linux، مثل Vim أو EMACs أو Nano
كيف ستستخدم هذا البرنامج التعليمي؟
ما هو تقييمك لتجربة استخدام Google Cloud Platform؟
2. الإعداد والمتطلبات
إعداد البيئة بالسرعة التي تناسبك
- سجِّل الدخول إلى Cloud Console وأنشِئ مشروعًا جديدًا أو أعِد استخدام مشروع حالي. إذا لم يكن لديك حساب على Gmail أو Google Workspace، عليك إنشاء حساب.



تذكَّر رقم تعريف المشروع، وهو اسم فريد في جميع مشاريع Google Cloud (الاسم أعلاه مستخدَم حاليًا ولن يكون متاحًا لك، نأسف لذلك). سيتم الإشارة إليه لاحقًا في هذا الدرس التطبيقي حول الترميز باسم PROJECT_ID.
- بعد ذلك، عليك تفعيل الفوترة في Cloud Console من أجل استخدام موارد Google Cloud.
لن تكلفك تجربة هذا الدرس البرمجي الكثير من المال، إن وُجدت تكلفة على الإطلاق. احرص على اتّباع أي تعليمات في قسم "التنظيف" الذي ينصحك بكيفية إيقاف الموارد حتى لا يتم تحصيل رسوم منك بعد هذا البرنامج التعليمي. يمكن لمستخدمي Google Cloud الجدد الاستفادة من برنامج الفترة التجريبية المجانية بقيمة 300 دولار أمريكي.
Google Cloud Shell
على الرغم من إمكانية تشغيل Google Cloud عن بُعد من الكمبيوتر المحمول، سنستخدم Google Cloud Shell، وهي بيئة سطر أوامر تعمل في السحابة الإلكترونية، لتسهيل عملية الإعداد في هذا الدرس التطبيقي حول الترميز.
تفعيل Cloud Shell
- من Cloud Console، انقر على تفعيل Cloud Shell
.

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

يستغرق توفير Cloud Shell والاتصال به بضع لحظات فقط.

يتم تحميل هذا الجهاز الظاهري بجميع أدوات التطوير التي تحتاج إليها. توفّر هذه الخدمة دليلًا منزليًا دائمًا بسعة 5 غيغابايت وتعمل في Google Cloud، ما يؤدي إلى تحسين أداء الشبكة والمصادقة بشكل كبير. يمكن إنجاز معظم العمل في هذا الدرس البرمجي، إن لم يكن كله، باستخدام متصفّح أو جهاز Chromebook فقط.
بعد الاتصال بـ Cloud Shell، من المفترض أن يظهر لك أنّه تم إثبات هويتك وأنّه تم ضبط المشروع على رقم تعريف مشروعك.
- نفِّذ الأمر التالي في Cloud Shell للتأكّد من إثبات هويتك:
gcloud auth list
ناتج الأمر
Credentialed Accounts
ACTIVE ACCOUNT
* <my_account>@<my_domain.com>
To set the active account, run:
$ gcloud config set account `ACCOUNT`
- نفِّذ الأمر التالي في Cloud Shell للتأكّد من أنّ أمر gcloud يعرف مشروعك:
gcloud config list project
ناتج الأمر
[core] project = <PROJECT_ID>
إذا لم يكن كذلك، يمكنك تعيينه من خلال هذا الأمر:
gcloud config set project <PROJECT_ID>
ناتج الأمر
Updated property [core/project].
3- الانتقال إلى Cloud Profiler
في Cloud Console، انتقِل إلى واجهة مستخدم Profiler من خلال النقر على "Profiler" في شريط التنقّل الأيمن:

بدلاً من ذلك، يمكنك استخدام شريط البحث في Cloud Console للانتقال إلى واجهة مستخدم Profiler: ما عليك سوى كتابة "Cloud Profiler" واختيار العنصر الذي تم العثور عليه. في كلتا الحالتين، من المفترض أن تظهر لك واجهة مستخدم Profiler مع الرسالة "ما مِن بيانات متوفّرة لعرضها" كما هو موضّح أدناه. المشروع جديد، لذا لا يتضمّن أي بيانات تحديد مواصفات تم جمعها حتى الآن.

حان الوقت الآن للحصول على بعض البيانات الشخصية.
4. إنشاء ملف تعريف لمقياس الأداء
سنستخدم تطبيق Go اصطناعيًا بسيطًا متاحًا على Github. في نافذة Cloud Shell الطرفية التي لا تزال مفتوحة (وأثناء استمرار ظهور الرسالة "لا تتوفّر بيانات لعرضها" في واجهة مستخدم Profiler)، شغِّل الأمر التالي:
$ go get -u github.com/GoogleCloudPlatform/golang-samples/profiler/...
بعد ذلك، انتقِل إلى دليل التطبيق:
$ cd ~/gopath/src/github.com/GoogleCloudPlatform/golang-samples/profiler/hotapp
يحتوي الدليل على الملف "main.go"، وهو تطبيق اصطناعي تم تفعيل أداة جمع بيانات الأداء فيه:
main.go
...
import (
...
"cloud.google.com/go/profiler"
)
...
func main() {
err := profiler.Start(profiler.Config{
Service: "hotapp-service",
DebugLogging: true,
MutexProfiling: true,
})
if err != nil {
log.Fatalf("failed to start the profiler: %v", err)
}
...
}
يجمع عامل إنشاء الملفات الشخصية ملفات وحدة المعالجة المركزية (CPU) والذاكرة المؤقتة والعمليات تلقائيًا. يتيح الرمز البرمجي هنا جمع ملفات تعريف mutex (المعروفة أيضًا باسم "التنازع").
الآن، شغِّل البرنامج:
$ go run main.go
أثناء تشغيل البرنامج، سيجمع عامل إنشاء الملفات الشخصية بشكل دوري ملفات شخصية من الأنواع الخمسة التي تم ضبطها. يتم ترتيب المجموعة عشوائيًا بمرور الوقت (بمعدل متوسط يبلغ ملف شخصي واحد في الدقيقة لكل نوع من الأنواع)، لذا قد يستغرق جمع كل نوع من الأنواع مدة تصل إلى ثلاث دقائق. يُعلمك البرنامج عند إنشاء ملف شخصي. يتم تفعيل الرسائل من خلال العلامة DebugLogging في الإعدادات أعلاه، وإلا سيعمل الوكيل بدون إصدار أي صوت:
$ go run main.go 2018/03/28 15:10:24 profiler has started 2018/03/28 15:10:57 successfully created profile THREADS 2018/03/28 15:10:57 start uploading profile 2018/03/28 15:11:19 successfully created profile CONTENTION 2018/03/28 15:11:30 start uploading profile 2018/03/28 15:11:40 successfully created profile CPU 2018/03/28 15:11:51 start uploading profile 2018/03/28 15:11:53 successfully created profile CONTENTION 2018/03/28 15:12:03 start uploading profile 2018/03/28 15:12:04 successfully created profile HEAP 2018/03/28 15:12:04 start uploading profile 2018/03/28 15:12:04 successfully created profile THREADS 2018/03/28 15:12:04 start uploading profile 2018/03/28 15:12:25 successfully created profile HEAP 2018/03/28 15:12:25 start uploading profile 2018/03/28 15:12:37 successfully created profile CPU ...
سيتم تعديل واجهة المستخدم تلقائيًا بعد جمع الملف التجاري الأول. ولن يتم تحديثها تلقائيًا بعد ذلك، لذا لعرض البيانات الجديدة، عليك إعادة تحميل واجهة مستخدم Profiler يدويًا. لإجراء ذلك، انقر على الزر "الآن" في أداة اختيار الفاصل الزمني مرّتين:

بعد إعادة تحميل واجهة المستخدم، سيظهر لك ما يلي:

تعرض أداة اختيار نوع الملف الشخصي أنواع الملفات الشخصية الخمسة المتاحة:

لنراجع الآن كل نوع من أنواع الملفات الشخصية وبعض إمكانات واجهة المستخدم المهمة، ثم نُجري بعض التجارب. في هذه المرحلة، لن تحتاج إلى وحدة Cloud Shell الطرفية، لذا يمكنك الخروج منها بالضغط على CTRL-C وكتابة "exit".
5- تحليل بيانات Profiler
بعد أن جمعنا بعض البيانات، لنلقِ نظرة عليها عن كثب. نستخدم تطبيقًا اصطناعيًا (يتوفّر الرمز المصدر على Github) يحاكي السلوكيات النموذجية لأنواع مختلفة من مشاكل الأداء في مرحلة الإنتاج.
الرموز البرمجية التي تستهلك الكثير من وحدة المعالجة المركزية
اختَر نوع ملف وحدة المعالجة المركزية. بعد تحميل واجهة المستخدم، ستظهر في الرسم البياني الشجري أربع كتل أوراق لوظيفة load، والتي تمثّل بشكل جماعي كل استهلاك وحدة المعالجة المركزية:

تمت كتابة هذه الدالة خصيصًا لاستهلاك الكثير من دورات وحدة المعالجة المركزية من خلال تشغيل حلقة ضيقة:
main.go
func load() {
for i := 0; i < (1 << 20); i++ {
}
}
يتم استدعاء الدالة بشكل غير مباشر من busyloop() عبر أربعة مسارات استدعاء: busyloop → {foo1, foo2} → {bar, baz} → load. يمثّل عرض مربّع الدالة التكلفة النسبية لمسار الاستدعاء المحدّد. في هذه الحالة، تتشابه تكلفة المسارات الأربعة. في برنامج حقيقي، عليك التركيز على تحسين مسارات الاتصال الأكثر أهمية من حيث الأداء. يسهّل الرسم البياني الشعلة، الذي يؤكّد بصريًا على المسارات الأكثر تكلفة باستخدام مربّعات أكبر، تحديد هذه المسارات.
يمكنك استخدام فلتر بيانات الملف الشخصي لتحسين العرض بشكل أكبر. على سبيل المثال، جرِّب إضافة فلتر "عرض حِزم" مع تحديد "baz" كسلسلة الفلتر. من المفترض أن يظهر لك شيء مشابه للقطة الشاشة أدناه، حيث يتم عرض مسارين فقط من مسارات الاتصال الأربعة إلى load(). هذان المساران هما المساران الوحيدان اللذان يمران بدالة تتضمّن السلسلة "baz" في اسمها. تكون عملية الفلترة هذه مفيدة عندما تريد التركيز على جزء فرعي من برنامج أكبر (على سبيل المثال، لأنّك تملك جزءًا منه فقط).

الرموز البرمجية التي تتطلّب ذاكرة كبيرة
الآن، انتقِل إلى نوع الملف الشخصي "Heap". احرص على إزالة أي فلاتر أنشأتها في التجارب السابقة. من المفترض أن يظهر لك الآن رسم بياني على شكل شعلة يظهر فيه allocImpl، الذي تم استدعاؤه من خلال alloc، باعتباره المستهلك الرئيسي للذاكرة في التطبيق:

يشير جدول الملخّص أعلى الرسم البياني الشعلة إلى أنّ إجمالي مقدار الذاكرة المستخدَمة في التطبيق يبلغ في المتوسط 57.4 ميغابايت تقريبًا، ويتم تخصيص معظمها من خلال الدالة allocImpl. وهذا ليس مفاجئًا، بالنظر إلى طريقة تنفيذ هذه الدالة:
main.go
func allocImpl() {
// Allocate 64 MiB in 64 KiB chunks
for i := 0; i < 64*16; i++ {
mem = append(mem, make([]byte, 64*1024))
}
}
يتم تنفيذ الدالة مرة واحدة، مع تخصيص 64 ميغابايت في أجزاء أصغر، ثم يتم تخزين مؤشرات لتلك الأجزاء في متغيّر عام لحمايتها من جمع البيانات غير الضرورية. يُرجى العِلم أنّ مقدار الذاكرة المعروض على أنّه مستخدَم من خلال أداة تحليل الأداء يختلف قليلاً عن 64 ميغابايت: أداة تحليل الأداء في Go هي أداة إحصائية، لذا تكون القياسات منخفضة الحمل ولكنّها ليست دقيقة على مستوى البايت. لا تستغرب عند رؤية فرق بنسبة% 10 تقريبًا على هذا النحو.
الرمز البرمجي الذي يتطلّب عمليات إدخال/إخراج مكثّفة
إذا اخترت "سلاسل المحادثات" في أداة اختيار نوع الملف الشخصي، سيتم التبديل إلى رسم بياني شجري حيث يشغل معظم العرض الدالتان wait وwaitImpl:

في الملخّص أعلى الرسم البياني الشعلة، يمكنك الاطّلاع على 100 إجراء فرعي يزيد من حجم حزمة التنفيذ من الدالة wait. هذا صحيح تمامًا، علمًا بأنّ الرمز الذي يبدأ عمليات الانتظار هذه يبدو على النحو التالي:
main.go
func main() {
...
// Simulate some waiting goroutines.
for i := 0; i < 100; i++ {
go wait()
}
يكون نوع الملف الشخصي هذا مفيدًا لمعرفة ما إذا كان البرنامج يستغرق أي وقت غير متوقّع في عمليات الانتظار (مثل الإدخال/الإخراج). ولا يتم عادةً أخذ عيّنات من حِزم استدعاء الدوال البرمجية هذه بواسطة أداة تحليل استخدام وحدة المعالجة المركزية، لأنّها لا تستهلك أي جزء كبير من وقت وحدة المعالجة المركزية. في كثير من الأحيان، ستحتاج إلى استخدام فلاتر "إخفاء حِزم التعليمات البرمجية" مع ملفات تعريف سلاسل التعليمات، مثلاً لإخفاء جميع حِزم التعليمات البرمجية التي تنتهي بطلب إلى gopark, لأنّها غالبًا ما تكون إجراءات goroutines غير مستخدَمة من قِبل أي برنامج حاليًا وأقل أهمية من تلك التي تنتظر وحدات الإدخال والإخراج.
يمكن أن يساعد نوع ملف تعريف سلاسل التنفيذ أيضًا في تحديد النقاط في البرنامج التي تنتظر فيها سلاسل التنفيذ mutex مملوكًا لجزء آخر من البرنامج لفترة طويلة، ولكن نوع ملف التعريف التالي أكثر فائدة لذلك.
الرمز البرمجي الذي يتطلب الكثير من الموارد
يحدّد نوع ملف تعريف التنازع الأقفال "الأكثر طلبًا" في البرنامج. يتوفّر نوع الملف الشخصي هذا لبرامج Go، ولكن يجب تفعيله بشكل صريح من خلال تحديد "MutexProfiling: true" في رمز إعداد الوكيل. تعمل عملية الجمع من خلال تسجيل (ضمن مقياس "المنافسات") عدد المرات التي كان فيها قفل معيّن، عند إلغاء قفله بواسطة روتين فرعي A، ينتظر روتين فرعي آخر B إلغاء قفل هذا القفل. ويسجّل أيضًا (ضمن مقياس "التأخير") الوقت الذي انتظرت فيه goroutine المحظورة القفل. في هذا المثال، هناك مجموعة واحدة من عمليات الانتظار، وكان إجمالي وقت الانتظار للقفل 10.5 ثانية:

يتألف الرمز البرمجي الذي ينشئ هذا الملف من 4 إجراءات goroutine تتنافس على قفل تبادلي:
main.go
func contention(d time.Duration) {
contentionImpl(d)
}
func contentionImpl(d time.Duration) {
for {
mu.Lock()
time.Sleep(d)
mu.Unlock()
}
}
...
func main() {
...
for i := 0; i < 4; i++ {
go contention(time.Duration(i) * 50 * time.Millisecond)
}
}
6. ملخّص
في هذا الدرس التطبيقي، تعرّفت على كيفية ضبط إعدادات برنامج Go لاستخدامه مع Cloud Profiler. تعرّفت أيضًا على كيفية جمع بيانات الأداء وعرضها وتحليلها باستخدام هذه الأداة. يمكنك الآن تطبيق مهارتك الجديدة على الخدمات الفعلية التي تديرها على Google Cloud Platform.
7. تهانينا!
لقد تعرّفت على كيفية إعداد Cloud Profiler واستخدامه.
مزيد من المعلومات
- Cloud Profiler: https://cloud.google.com/profiler/
- حزمة Go runtime/pprof التي تستخدمها Cloud Profiler: https://golang.org/pkg/runtime/pprof/
الترخيص
يخضع هذا العمل لترخيص Creative Commons Attribution 2.0 Generic License.