Profiling
CPU Profiling
هناك نهجان رئيسيان لتوصيف وحدة المعالجة المركزية (CPU) لشفرة جوليا:
Via @profile
حيث يتم تمكين التوصيف لاستدعاء معين عبر ماكرو @profile
.
julia> using Profile
julia> @profile foo()
julia> Profile.print()
Overhead ╎ [+additional indent] Count File:Line; Function
=========================================================
╎147 @Base/client.jl:506; _start()
╎ 147 @Base/client.jl:318; exec_options(opts::Base.JLOptions)
...
Triggered During Execution
يمكن أيضًا تحليل المهام التي تعمل بالفعل لفترة زمنية محددة في أي وقت يتم فيه تشغيلها بواسطة المستخدم.
لتفعيل التوصيف:
- MacOS و FreeBSD (المنصات المعتمدة على BSD): استخدم
ctrl-t
أو أرسل إشارةSIGINFO
إلى عملية جوليا، أي% kill -INFO $julia_pid
- لينكس: أرسل إشارة
SIGUSR1
إلى عملية جوليا أي% kill -USR1 $julia_pid
- ويندوز: غير مدعوم حاليًا.
أولاً، يتم عرض تتبع مكدس واحد في اللحظة التي تم فيها رمي الإشارة، ثم يتم جمع ملف تعريف لمدة ثانية واحدة، يليه تقرير الملف الشخصي في نقطة العائد التالية، والتي قد تكون عند إكمال المهمة للشفرة بدون نقاط عائد مثل الحلقات الضيقة.
اختياريًا، قم بتعيين متغير البيئة JULIA_PROFILE_PEEK_HEAP_SNAPSHOT
إلى 1
لجمع heap snapshot تلقائيًا أيضًا.
julia> foo()
##== the user sends a trigger while foo is running ==##
load: 2.53 cmd: julia 88903 running 6.16u 0.97s
======================================================================================
Information request received. A stacktrace will print followed by a 1.0 second profile
======================================================================================
signal (29): Information request: 29
__psynch_cvwait at /usr/lib/system/libsystem_kernel.dylib (unknown line)
_pthread_cond_wait at /usr/lib/system/libsystem_pthread.dylib (unknown line)
...
======================================================================
Profile collected. A report will print if the Profile module is loaded
======================================================================
Overhead ╎ [+additional indent] Count File:Line; Function
=========================================================
Thread 1 Task 0x000000011687c010 Total snapshots: 572. Utilization: 100%
╎147 @Base/client.jl:506; _start()
╎ 147 @Base/client.jl:318; exec_options(opts::Base.JLOptions)
...
Thread 2 Task 0x0000000116960010 Total snapshots: 572. Utilization: 0%
╎572 @Base/task.jl:587; task_done_hook(t::Task)
╎ 572 @Base/task.jl:879; wait()
...
Customization
يمكن ضبط مدة التوصيف عبر Profile.set_peek_duration
تقرير الملف الشخصي مقسم حسب الخيط والمهمة. مرر دالة بدون معلمات إلى Profile.peek_report[]
لتجاوز ذلك. أي Profile.peek_report[] = () -> Profile.print()
لإزالة أي تجميع. يمكن أيضًا تجاوز ذلك بواسطة مستهلك بيانات الملف الشخصي الخارجي.
Reference
Profile.@profile
— Macro@profile
@profile <expression>
يقوم بتشغيل التعبير الخاص بك مع أخذ تتبعات دورية. يتم إلحاق هذه التتبعات بذاكرة داخلية لتتبع التتبع.
الطرق في Profile
غير مصدرة وتحتاج إلى أن تُستدعى مثل Profile.print()
.
Profile.clear
— Functionclear()
امسح أي تتبعات موجودة من المخزن الداخلي.
Profile.print
— Functionprint([io::IO = stdout,] [data::Vector = fetch()], [lidict::Union{LineInfoDict, LineInfoFlatDict} = getdict(data)]; kwargs...)
يطبّع نتائج التقييم إلى io
(بشكل افتراضي، stdout
). إذا لم تقم بتزويد متجه data
، سيتم استخدام المخزن الداخلي للتتبع المتراكم.
يمكن أن تكون الوسائط الرئيسية أي مجموعة من:
format
– يحدد ما إذا كان سيتم طباعة تتبعات الأخطاء مع (افتراضي،:tree
) أو بدون (:flat
) تباعد يشير إلى هيكل الشجرة.C
– إذا كانتtrue
، يتم عرض تتبعات الأخطاء من كود C و Fortran (عادةً ما يتم استبعادها).combine
– إذا كانتtrue
(افتراضي)، يتم دمج مؤشرات التعليمات التي تتوافق مع نفس سطر الكود.maxdepth
– يحدد العمق الأعلى منmaxdepth
في تنسيق:tree
.sortedby
– يتحكم في ترتيب تنسيق:flat
.:filefuncline
(افتراضي) يرتب حسب سطر المصدر،:count
يرتب حسب عدد العينات المجمعة، و:overhead
يرتب حسب عدد العينات التي تكبدتها كل دالة بمفردها.groupby
– يتحكم في التجميع عبر المهام والخيوط، أو عدم التجميع. الخيارات هي:none
(افتراضي)،:thread
،:task
،[:thread, :task]
، أو[:task, :thread]
حيث يوفر الاثنان الأخيران تجميعًا متداخلًا.noisefloor
– يحدد الإطارات التي تتجاوز مستوى الضوضاء الاستدلالي للعينة (ينطبق فقط على تنسيق:tree
). قيمة مقترحة لتجربتها هي 2.0 (القيمة الافتراضية هي 0). هذا المعامل يخفي العينات التي يكون فيهاn <= noisefloor * √N
، حيثn
هو عدد العينات في هذا السطر، وN
هو عدد العينات للوظيفة المستدعاة.mincount
– يحدد الطباعة لتشمل فقط تلك الأسطر التي تحتوي على ما لا يقل عنmincount
حدوثات.recur
– يتحكم في معالجة التكرار في تنسيق:tree
.:off
(افتراضي) يطبع الشجرة كالمعتاد.:flat
بدلاً من ذلك يضغط أي تكرار (حسب ip)، مما يظهر التأثير التقريبي لتحويل أي تكرار ذاتي إلى مكرر.:flatc
يفعل نفس الشيء ولكنه يتضمن أيضًا انهيار إطارات C (قد يفعل أشياء غريبة حولjl_apply
).threads::Union{Int,AbstractVector{Int}}
– حدد أي خيوط لتضمين لقطات منها في التقرير. لاحظ أن هذا لا يتحكم في أي خيوط تم جمع العينات عليها (والتي قد تكون قد تم جمعها أيضًا على آلة أخرى).tasks::Union{Int,AbstractVector{Int}}
– حدد أي مهام لتضمين لقطات منها في التقرير. لاحظ أن هذا لا يتحكم في أي مهام تم جمع العينات ضمنها.
تم تقديم الوسائط الرئيسية groupby
و threads
و tasks
في جوليا 1.8.
التقييم على ويندوز محدود إلى الخيط الرئيسي. لم يتم أخذ عينات من الخيوط الأخرى ولن تظهر في التقرير.
print([io::IO = stdout,] data::Vector, lidict::LineInfoDict; kwargs...)
يطبع نتائج التقييم إلى io
. يتم استخدام هذا المتغير لفحص النتائج التي تم تصديرها بواسطة استدعاء سابق لـ retrieve
. قدم المتجه data
من تتبعات العودة وقاموس lidict
من معلومات السطر.
انظر Profile.print([io], data)
للحصول على شرح للوسائط الرئيسية الصالحة.
Profile.init
— Functioninit(; n::Integer, delay::Real)
قم بتكوين delay
بين تتبعات الأخطاء (مقاسة بالثواني)، وعدد n
من مؤشرات التعليمات التي يمكن تخزينها لكل خيط. كل مؤشر تعليمات يتوافق مع سطر واحد من التعليمات البرمجية؛ تتكون تتبعات الأخطاء عمومًا من قائمة طويلة من مؤشرات التعليمات. لاحظ أنه يتم استخدام 6 مسافات لمؤشرات التعليمات لكل تتبع خطأ لتخزين البيانات الوصفية واثنين من علامات نهاية NULL. يمكن الحصول على الإعدادات الحالية عن طريق استدعاء هذه الوظيفة بدون أي وسائط، ويمكن تعيين كل منها بشكل مستقل باستخدام الكلمات الرئيسية أو بالترتيب (n, delay)
.
Profile.fetch
— Functionfetch(;include_meta = true) -> data
إرجاع نسخة من مخزن تتبع الملفات الشخصية. لاحظ أن القيم في data
لها معنى فقط على هذه الآلة في الجلسة الحالية، لأنها تعتمد على عناوين الذاكرة الدقيقة المستخدمة في التجميع JIT. هذه الوظيفة مخصصة بشكل أساسي للاستخدام الداخلي؛ قد تكون retrieve
خيارًا أفضل لمعظم المستخدمين. بشكل افتراضي، يتم تضمين بيانات التعريف مثل threadid و taskid. قم بتعيين include_meta
إلى false
لإزالة بيانات التعريف.
Profile.retrieve
— Functionretrieve(; kwargs...) -> data, lidict
"تصدير" نتائج التحليل في تنسيق محمول، مع إرجاع مجموعة من جميع تتبعات الأخطاء (data
) وقاموس يربط مؤشرات التعليمات (المحددة للجلسة) في data
بقيم LineInfo
التي تخزن اسم الملف، اسم الدالة، ورقم السطر. تتيح لك هذه الدالة حفظ نتائج التحليل لتحليلها في المستقبل.
Profile.callers
— Functioncallers(funcname, [data, lidict], [filename=<filename>], [linerange=<start:stop>]) -> Vector{Tuple{count, lineinfo}}
بناءً على تشغيل سابقة للتقييم، حدد من استدعى دالة معينة. يسمح لك تقديم اسم الملف (وخيارياً، نطاق أرقام الأسطر التي تم تعريف الدالة عليها) بتفريق طريقة مفرطة التحميل. القيمة المعادة هي متجه يحتوي على عدد المكالمات ومعلومات السطر حول المستدعي. يمكن للمرء اختيارياً تقديم بيانات تتبع data
تم الحصول عليها من retrieve
؛ خلاف ذلك، يتم استخدام مخزن التقييم الداخلي الحالي.
Profile.clear_malloc_data
— Functionclear_malloc_data()
يمسح أي بيانات تخص تخصيص الذاكرة المخزنة عند تشغيل جوليا مع --track-allocation
. نفذ الأمر (الأوامر) التي تريد اختبارها (لإجبار JIT-compilation)، ثم استدع clear_malloc_data
. ثم نفذ الأمر (الأوامر) مرة أخرى، اخرج من جوليا، وافحص ملفات *.mem
الناتجة.
Profile.get_peek_duration
— Functionget_peek_duration()
احصل على المدة بالثواني لملف التعريف "peek" الذي يتم تفعيله عبر SIGINFO
أو SIGUSR1
، اعتمادًا على النظام الأساسي.
Profile.set_peek_duration
— Functionset_peek_duration(t::Float64)
قم بتعيين المدة بالثواني لملف التعريف "peek" الذي يتم تفعيله عبر SIGINFO
أو SIGUSR1
، اعتمادًا على النظام الأساسي.
Memory profiling
Profile.Allocs.@profile
— MacroProfile.Allocs.@profile [sample_rate=0.1] expr
قم بتسجيل تخصيصات الذاكرة التي تحدث أثناء expr
، مع إرجاع كل من النتيجة وهيكل AllocResults.
معدل العينة 1.0 سيسجل كل شيء؛ 0.0 لن يسجل أي شيء.
julia> Profile.Allocs.@profile sample_rate=0.01 peakflops()
1.03733270279065e11
julia> results = Profile.Allocs.fetch()
julia> last(sort(results.allocs, by=x->x.size))
Profile.Allocs.Alloc(Vector{Any}, Base.StackTraces.StackFrame[_new_array_ at array.c:127, ...], 5576)
راجع برنامج التعليمات الخاص بالتسجيل في وثائق جوليا لمزيد من المعلومات.
لم تتمكن الإصدارات القديمة من جوليا من التقاط الأنواع في جميع الحالات. في الإصدارات القديمة من جوليا، إذا رأيت تخصيصًا من نوع Profile.Allocs.UnknownType
، فهذا يعني أن أداة التسجيل لا تعرف نوع الكائن الذي تم تخصيصه. حدث هذا بشكل رئيسي عندما كان التخصيص يأتي من كود تم إنشاؤه بواسطة المترجم. راجع issue #43688 لمزيد من المعلومات.
منذ جوليا 1.11، يجب أن تحتوي جميع التخصيصات على نوع مُبلغ عنه.
تمت إضافة أداة تسجيل التخصيصات في جوليا 1.8.
الطرق في Profile.Allocs
غير مصدرة وتحتاج إلى أن تُستدعى مثل Profile.Allocs.fetch()
.
Profile.Allocs.clear
— FunctionProfile.Allocs.clear()
امسح جميع معلومات التخصيص التي تم تحليلها مسبقًا من الذاكرة.
Profile.Allocs.print
— FunctionProfile.Allocs.print([io::IO = stdout,] [data::AllocResults = fetch()]; kwargs...)
يطبّع نتائج التقييم إلى io
(بشكل افتراضي، stdout
). إذا لم تقم بتزويد متجه data
، سيتم استخدام المخزن الداخلي للتتبع المتراكم.
انظر Profile.print
للحصول على شرح للوسائط الرئيسية الصالحة.
Profile.Allocs.fetch
— FunctionProfile.Allocs.fetch()
استرجع التخصيصات المسجلة، وقم بفك تشفيرها إلى كائنات جوليا التي يمكن تحليلها.
Profile.Allocs.start
— FunctionProfile.Allocs.start(sample_rate::Real)
ابدأ بتسجيل التخصيصات بمعدل العينة المعطى. سيقوم معدل العينة 1.0 بتسجيل كل شيء؛ بينما سيقوم 0.0 بتسجيل لا شيء.
Profile.Allocs.stop
— FunctionProfile.Allocs.stop()
توقف عن تسجيل التخصيصات.
Heap Snapshots
Profile.take_heap_snapshot
— FunctionProfile.take_heap_snapshot(filepath::String, all_one::Bool=false, streaming=false)
Profile.take_heap_snapshot(all_one::Bool=false; dir::String, streaming=false)
اكتب لقطة من الذاكرة، بتنسيق JSON المتوقع من عارض لقطة ذاكرة أدوات مطور Chrome (.heapsnapshot extension) إلى ملف ($pid_$timestamp.heapsnapshot
) في الدليل الحالي بشكل افتراضي (أو tempdir إذا كان الدليل الحالي غير قابل للكتابة)، أو في dir
إذا تم تقديمه، أو المسار الكامل للملف المعطى، أو تدفق IO.
إذا كان all_one
صحيحًا، فقم بالإبلاغ عن حجم كل كائن كواحد حتى يمكن عدها بسهولة. خلاف ذلك، قم بالإبلاغ عن الحجم الفعلي.
إذا كان streaming
صحيحًا، فسوف نقوم ببث بيانات اللقطة إلى أربعة ملفات، باستخدام filepath كبادئة، لتجنب الحاجة إلى الاحتفاظ باللقطة الكاملة في الذاكرة. يجب استخدام هذا الخيار في أي إعداد حيث تكون الذاكرة لديك محدودة. يمكن بعد ذلك إعادة تجميع هذه الملفات عن طريق استدعاء Profile.HeapSnapshot.assemble_snapshot()، والذي يمكن القيام به في وضع عدم الاتصال.
ملاحظة: نوصي بشدة بتعيين streaming=true لأسباب تتعلق بالأداء. يتطلب إعادة بناء اللقطة من الأجزاء الاحتفاظ باللقطة الكاملة في الذاكرة، لذا إذا كانت اللقطة كبيرة، يمكنك نفاد الذاكرة أثناء معالجتها. يسمح البث لك بإعادة بناء اللقطة في وضع عدم الاتصال، بعد انتهاء عبء العمل الخاص بك. إذا حاولت جمع لقطة مع streaming=false (الإعداد الافتراضي، للتوافق مع الإصدارات السابقة) وتم قتل عمليتك، لاحظ أن هذا سيحفظ دائمًا الأجزاء في نفس الدليل مثل filepath المقدم، لذا يمكنك إعادة بناء اللقطة بعد ذلك، عبر assemble_snapshot()
.
الطرق في Profile
غير مصدرة وتحتاج إلى أن تُستدعى مثل Profile.take_heap_snapshot()
.
julia> using Profile
julia> Profile.take_heap_snapshot("snapshot.heapsnapshot")
يتتبع ويسجل كائنات جوليا في الذاكرة. هذا يسجل فقط الكائنات المعروفة لجمع القمامة في جوليا. الذاكرة المخصصة من قبل المكتبات الخارجية التي لا يديرها جامع القمامة لن تظهر في اللقطة.
لتجنب نفاد الذاكرة أثناء تسجيل لقطة الذاكرة، أضفنا خيار البث لبث لقطة الذاكرة إلى أربعة ملفات،
julia> using Profile
julia> Profile.take_heap_snapshot("snapshot"; streaming=true)
حيث "snapshot" هو مسار الملف كبادئة للملفات المولدة.
بمجرد إنشاء ملفات اللقطة، يمكن تجميعها في وضع عدم الاتصال باستخدام الأمر التالي:
julia> using Profile
julia> Profile.HeapSnapshot.assemble_snapshot("snapshot", "snapshot.heapsnapshot")
يمكن تحميل ملف لقطة الكومة الناتجة إلى أدوات مطوري Chrome لعرضه. لمزيد من المعلومات، راجع chrome devtools docs. بديل لتحليل لقطات كومة Chromium هو استخدام ملحق VS Code ms-vscode.vscode-js-profile-flame
.
لقطات كومة Firefox هي بتنسيق مختلف، وFirefox حالياً قد لا يُستخدم لعرض لقطات الكومة التي تم إنشاؤها بواسطة Julia.