تحليل أداء التعليمات البرمجية باستخدام Rprof وprofvis
حدّد الدوال التي تستهلك أكبر قدر من الوقت في نصوصك البرمجية
تحليل أداء التعليمات البرمجية باستخدام Rprof وprofvis درس مجاني في R Academy على CoddyKit. هذا هو الدرس 2 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في R Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة R Academy 4 دروس في المجموع.
ما هو تحليل الأداء؟
يخبرك التوقيت بالمدة التي تستغرقها الشيفرة. أما تحليل الأداء فيخبرك بموضع استهلاك الوقت داخل تلك الشيفرة. يأخذ محلل الأداء في R عينات من مكدس الاستدعاءات على فواصل منتظمة لبناء صورة إحصائية عن الدوال المكلفة.
الأداتان الرئيسيتان هما Rprof() المدمجة وحزمة profvis التفاعلية.
بدء وإيقاف Rprof()
يبدأ Rprof('output.prof', interval = 0.01) محلل الأداء. ويكتب عينات مكدس الاستدعاءات في ملف كل 10 مللي ثانية. شغّل الشيفرة البطيئة، ثم استدعِ Rprof(NULL) لإيقاف التسجيل.
تتحكم الوسيطة interval في تكرار أخذ العينات بالثواني — إذ تمنح القيم الأصغر دقة أعلى، لكنها تنتج ملفات أكبر.
# Pattern — do not run Rprof inside knitr/Quarto
# Rprof('my_profile.prof', interval = 0.01)
#
# slow_function <- function(n) {
# x <- numeric(n)
# for (i in seq_len(n)) x[i] <- sqrt(i)
# sum(x)
# }
# slow_function(500000)
#
# Rprof(NULL) # stop profilingقراءة النتائج باستخدام summaryRprof()
تحلل summaryRprof('output.prof') ملف تحليل الأداء وتعيد قائمة تحتوي على إطاري بيانات:
- by.self — الوقت الذي استغرقته كل دالة نفسها، باستثناء الدوال التي تستدعيها
- by.total — الوقت الإجمالي، بما في ذلك جميع الدوال التي استدعتها تلك الدالة
رتّب حسب self.pct للعثور على مواضع الاختناق.
# After Rprof() run:
# prof <- summaryRprof('my_profile.prof')
# head(prof$by.self)
#
# Example output columns:
# self.time self.pct total.time total.pct
# slow_fn 1.22 61.0 1.98 99.0
# sqrt 0.76 38.0 0.76 38.0
# sum 0.02 1.0 0.02 1.0الوقت الذاتي مقابل الوقت الإجمالي
يُعد فهم الوقت الذاتي مقابل الوقت الإجمالي أمرًا أساسيًا في تحليل الأداء:
- الوقت الذاتي — الوقت الذي استغرقته الدالة في تنفيذ أسطرها الخاصة، من دون انتظار الدوال التي تستدعيها
- الوقت الإجمالي — الوقت الذاتي مضافًا إليه كل الوقت الذي استغرقته الدوال التي استدعتها
الدالة ذات الوقت الإجمالي المرتفع والوقت الذاتي المنخفض بطيئة بسبب ما تستدعيه، لا بسبب منطقها الخاص. حسّن الدالة المستدعاة، لا الدالة المستدعية.
# Conceptual example:
# wrapper() -> process_data() -> slow_sort()
#
# total.pct: wrapper=100, process_data=90, slow_sort=85
# self.pct: wrapper=5, process_data=5, slow_sort=85
#
# => slow_sort is the real bottleneck to fix.
cat('High total + low self => the culprit is a callee function
')مقدمة إلى profvis
تغلّف profvis الدالة Rprof() وتوفر مخطط لهب HTML تفاعليًا في RStudio أو المتصفح. وتكون قراءته أسهل بكثير من مخرجات summaryRprof() الخام.
ثبّتها مرة واحدة باستخدام install.packages('profvis')، ثم غلّف شيفرتك باستخدام profvis({...}).
# library(profvis)
#
# profvis({
# n <- 200000
# x <- numeric(n)
# for (i in seq_len(n)) x[i] <- log(i)
# total <- sum(x)
# sorted <- sort(x)
# })قراءة مخطط اللهب في profvis
تحتوي مخرجات profvis على لوحتين:
- مخطط اللهب — أشرطة أفقية يساوي عرضها الوقت؛ وتمثل الأشرطة المتداخلة عمق مكدس الاستدعاءات
- جدول البيانات — عرض قابل للفرز للوقت الذاتي والإجمالي لكل دالة وسطر مصدر
تمثل الأشرطة العريضة في أسفل مخطط اللهب الدوال المستدعية الأعلى تكلفة. وتشير المكدسات الطويلة إلى سلاسل استدعاءات عميقة.
# Reading the flame graph:
# - Each horizontal bar = one function on the call stack
# - Width proportional to time spent
# - Bottom = outermost caller, top = deepest callee
# - Click a bar to zoom in
# - 'Memory' tab shows allocation by line
cat('profvis shows self time per source line — invaluable for tight loops
')تحديد مواضع الاختناق
بعد عرض مخرجات profvis، حدّد مواضع الاختناق بالبحث عن الدوال العريضة في مخطط اللهب وذات الوقت الذاتي المرتفع. ومن الأسباب الشائعة في R:
- الحلقات غير المتجهة التي تنفذ العمل عنصرًا بعد عنصر
- تكرار
rbind()أوc()مع زيادة حجم الكائنات داخل حلقة - تكرار تحليل التعبيرات النمطية أو السلاسل النصية داخل الحلقات الضيقة
# Before fix — growing vector in loop (common hot spot)
# profvis reveals repeated reallocations:
# result <- c()
# for (i in 1:50000) result <- c(result, i^2)
#
# After fix — pre-allocated:
# result <- numeric(50000)
# for (i in 1:50000) result[i] <- i^2
cat('Pre-allocation eliminates the most common loop hot spot
')تحليل تخصيصات الذاكرة
يمكن لـ Rprof أيضًا تتبع تخصيصات الذاكرة باستخدام memory.profiling = TRUE. وتعرض profvis لوحة للذاكرة إلى جانب التوقيت، ما يتيح لك اكتشاف الدوال التي تخصص كائنات مؤقتة كبيرة — وهي مصدر رئيسي لتوقفات تجميع البيانات المهملة.
# Memory profiling with Rprof:
# Rprof('mem.prof', interval = 0.01, memory.profiling = TRUE)
# ... slow code ...
# Rprof(NULL)
# prof <- summaryRprof('mem.prof', memory = 'both')
# head(prof$by.self)
#
# profvis also shows mem delta per line automatically
cat('Memory profiling pinpoints allocation hot spots causing GC pauses
')تحليل أداء سير معالجة حقيقي
طبّق تحليل الأداء منهجيًا على سير معالجة البيانات: غلّف سير المعالجة بأكمله داخل profvis({})، وحدد المرحلة الأبطأ، وحسّنها، ثم أعد التحليل للتأكد من التحسن. لا تحسّن الشيفرة أبدًا بصورة عمياء.
# Workflow:
# 1. profvis({ full_pipeline() }) => identify Stage 3 is 80% of time
# 2. Rewrite Stage 3 (vectorize / use data.table)
# 3. profvis({ full_pipeline() }) => confirm Stage 3 now < 10%
# 4. system.time({ full_pipeline() }) => confirm overall speedup
cat('Profile -> identify -> fix -> re-profile is the correct cycle
')قيود أخذ عينات Rprof
يستخدم Rprof أخذ عينات إحصائيًا، ولذلك قد لا تظهر الدوال السريعة جدًا، أي الأسرع من الفاصل الزمني لأخذ العينات. ولإجراء اختبارات أداء دقيقة للتعبيرات الصغيرة، استخدم حزمة microbenchmark بدلًا من ذلك.
كذلك، لا يحلل Rprof شيفرة C/C++ الموجودة أسفل واجهة R — إذ لا تظهر سوى مكدسات الاستدعاءات على مستوى R.
# Rprof interval = 0.01s => functions faster than 10ms may not appear
# For sub-millisecond work use microbenchmark:
# microbenchmark(expr1, expr2, times = 1000L)
#
# For C-level profiling use external tools:
# - Instruments (macOS)
# - perf (Linux)
cat('Rprof is for R-level profiling; use microbenchmark for micro-timing
')أفضل الممارسات لتحليل أداء R
اتبع هذه الممارسات للحصول على نتائج موثوقة لتحليل الأداء:
- حلّل الأداء باستخدام أحجام بيانات واقعية — فالمدخلات الصغيرة تخفي عنق الزجاجة الفعلي
- شغّل تكرارات تمهيدية قبل تحليل الأداء لاستبعاد تكاليف الإعداد التي تحدث مرة واحدة
- أجرِ التحليل في جلسة R نظيفة لتجنب التداخل من الحزم المحملة
- استخدم
profvisللاستكشاف، وsummaryRprofللتقارير الآلية أو تقارير CI
# Clean session profiling checklist:
# 1. Restart R (Ctrl+Shift+F10 in RStudio)
# 2. Load only required packages
# 3. Run once to warm up
# 4. profvis({ ... }) on second run
# 5. Compare before/after with system.time()
cat('Always profile with realistic data in a clean R session
')تحقق سريع: الوقت الذاتي مقابل الإجمالي في Rprof
تعرض دالة ما total.pct = 95%، لكن self.pct = 3% في مخرجات summaryRprof(). ماذا يخبرك ذلك؟
مراجعة أدوات تحليل الأداء
يوفر لك R مجموعة أدوات لتحليل الأداء على مستويين:
Rprof('file.prof', interval=0.01)+Rprof(NULL)+summaryRprof()— مدمجة وقابلة للبرمجة النصية وملائمة لـ CIprofvis({...})— مخطط لهب تفاعلي مع تعليقات على أسطر المصدر وتتبع الذاكرة
سير العمل الصحيح هو دائمًا: قِس أولًا، وحدد الموضع الأعلى تكلفة، وحسّن ذلك الموضع فقط، ثم أعد القياس للتأكد من تحقيق التحسن.
الأسئلة الشائعة
هل درس «تحليل أداء التعليمات البرمجية باستخدام Rprof وprofvis» مجاني؟
نعم — نص درس «تحليل أداء التعليمات البرمجية باستخدام Rprof وprofvis» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة R Academy، انتقل إلى CoddyKit PRO. تتضمن دورة R Academy 4 دروس في المجموع.
ماذا ستتعلم في «تحليل أداء التعليمات البرمجية باستخدام Rprof وprofvis»؟
حدّد الدوال التي تستهلك أكبر قدر من الوقت في نصوصك البرمجية تتمرن على R Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ R Academy؟
لا تُشترط خبرة سابقة. R Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 2 من أصل 4.
كم من الوقت يستغرق درس «تحليل أداء التعليمات البرمجية باستخدام Rprof وprofvis»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس R Academy هذا؟
نعم. كل درس في R Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- system.time() وproc.time()
- تحليل أداء التعليمات البرمجية باستخدام Rprof وprofvis
- التوجيهية لتحسين السرعة
- قياس الأداء باستخدام microbenchmark