المعالم هي مكتبة ملامح بسيطة لـ OCAML. يوفر بدائيات لتحديد أجزاء من التعليمات البرمجية وقياس أداء الكود المُجهز في وقت التشغيل. يتم الحصول على التدابير المتاحة عن طريق تجميع دورات وحدة المعالجة المركزية (باستخدام عداد الطوابع الزمنية لوحدة المعالجة المركزية) ، والوقت التطبيقي (باستخدام Sys.time
) والبايت المخصص (مع Gc.allocated_bytes
). قد يتم إما أجهزة الكود إما باليد ، تلقائيًا أو شبه تلقائي باستخدام امتداد PPX.
أثناء تنفيذ برنامجك ، يتم تسجيل اجتياز الكود المكون من تدفق التحكم باعتباره "callgraph" الذي يحمل التدابير التي تم جمعها. قد يتم تصفح النتائج إما مباشرة على وحدة التحكم ، أو تصديرها إلى JSON.
تهدف هذه الأداة إلى استخدامها كوسيلة لإيجاد المكان الذي يتم فيه قضاء الوقت في برامجك (وليس القياس لقطع رمز مستقلة مثل Core_bench) مع توفير النتائج التي تتوافق فقط مع الجزء الموجه من رمز OCAML الخاص بك (على عكس الأدوات التي اعمل مباشرة مع الثنائي القابل للتنفيذ مثل GPROF أو perf).
لمزيد من المعلومات ، يمكنك تصفح واجهة برمجة التطبيقات.
يتم تقسيم المكتبة إلى حزمتين: landmarks
لمكتبة وقت التشغيل landmarks-ppx
للمعالج المسبق لتنفيذ الأجهزة التلقائية.
opam install landmarks
أو
opam install landmarks-ppx
سيتم تثبيت مكتبة وقت التشغيل أو كلا من مكتبة وقت التشغيل والمعالج المسبق.
git clone https://github.com/LexiFi/landmarks.git
cd landmarks
dune build @install
ما عليك سوى استخدام landmarks
المكتبة landmarks-ppx
لقياس ماركاتك التنفيذية والمكتبات. على سبيل المثال ، يقوم ملف dune
التالي بإنشاء test
القابل للتنفيذ باستخدام مكتبة landmarks
و PPX. يقوم علامة --auto
بتشغيل الأجهزة التلقائية (انظر أدناه).
(executable
(name test)
(libraries landmarks)
(preprocess (pps landmarks-ppx --auto))
)
من الممكن استخدام الكثبان الرملية لتشغيل أدوات المشروع تلقائيًا. ألق نظرة على lexifi/المعالم ستارتر للحصول على مثال أساسي وشاهد دليل الكثبان الرملية لمزيد من المعلومات.
ocamlfind ocamlopt -c -package landmarks prog.ml
ocamlfind ocamlopt -o prog -package landmarks -linkpkg prog.cmx
يمكنك استبدال "Ocamlopt" بواسطة "OCAMLC" لتجميع البرنامج في Bytecode.
ocamlfind ocamlopt -c -package landmarks -package landmarks-ppx -ppxopt landmarks-ppx,--auto prog.ml
ocamlfind ocamlopt -o prog -package landmarks -linkpkg prog.cmx
لاحظ أن "-PPXOPT Warkmarks-PPX ،-Auto" اختياري ويقوم بتشغيل الأجهزة التلقائية.
هناك ثلاثة بدايات رئيسية:
val register : string -> landmark
val enter : landmark -> unit
val exit : landmark -> unit
تعلن وظيفة register
معالم جديدة ويجب استخدامها في Toplevel. يتم استخدام الوظائف enter
exit
لتحديد جزء التعليمات البرمجية المرفقة بالمعالم. في نهاية التنميط ، نسترجع لكل معلم معلومات الوقت المجمعة التي تم إنفاقها في تنفيذ قطعة التعليمات البرمجية المقابلة. أثناء التنفيذ ، يتم أيضًا تسجيل أثر لكل معلم تمت زيارته من أجل بناء "callgraph".
على سبيل المثال:
open Landmark
let loop = register " loop "
let sleep = register " sleep "
let main = register " main "
let zzz () =
enter sleep;
Unix. sleep 1 ;
exit sleep
let () =
begin
start_profiling () ;
enter main;
enter loop;
for _ = 1 to 9 do
zzz ()
done ;
exit loop;
zzz () ;
exit main;
end
(يمكن تجميع هذا الملف باستخدام ocamlfind ocamlc -o prog -package landmarks -package unix -linkpkg prog.ml
)
callgraph المستحث هو:
- 100.00% : main
| - 90.00% : loop
| | - 100.00% : sleep
| - 10.00% : sleep
التي يمكن إعادة صياغتها على النحو التالي:
clock()
توفر المكتبة ملزمة لعداد الدورات عالية الأداء للبنية X86 32 و 64 بت (لاحظ أنه يمكنك استخدام landmarks-noc.cm(x)a
أرشيف لتوفير التنفيذ الخاص بك). يتم استخدامه لقياس الوقت الذي يقضيه داخل الكود المتواصل.
لتجنب كتابة رمز Boilerplate ، يمكنك استخدام امتداد PPX الموزع باستخدام هذه الحزمة. يسمح للمبرمج بتعبيرات الأدوات باستخدام التعليقات التوضيحية ووظائف المستوى الأعلى تلقائيًا.
يتم توسيع القيمة expr [@landmark "name"]
Landmark. enter __generated_landmark_1;
let r =
try expr with e -> Landmark. exit __generated_landmark_1; raise e
in
Landmark. exit __generated_landmark_1;
r
والإعلان
let __generated_landmark_1 = Landmark. register " name "
يتم إلحاقه في المستوى الأعلى.
تجدر الإشارة إلى أن هذا التحول لا يحافظ على المكالمات المثيرة للاشتعال (ويمنع أيضًا بعض تعميم الأشكال). للتغلب على هذه المشكلات ، يوصى باستخدام التمديد الآخر المقدم let rec ... in
حوله let ... in
let [ @ landmark] f = body
الذي يتم توسيعه في:
let __generated_landmark_2 = Landmark. register " f "
let f = body
let f x1 ... xn =
Landmark. enter __generated_landmark_2;
let r =
try f x1 ... xn with e -> Landmark. exit __generated_landmark_2; raise e
in
Landmark. exit __generated_landmark_2;
r
عندما يتم الحصول على arity n
من f
عن طريق حساب الأحداث الضحلة fun ... ->
function ... ->
في body
. يرجى ملاحظة أنه عند استخدام هذا التعليق التوضيحي باستخدام روابط Let-Rec ، سيتم تسجيل مكالمات نقطة الدخول فقط. على سبيل المثال ، في الجزء التالي من الكود
let () =
let [ @ landmark] rec even n = (n = 0 ) || odd (n - 1 )
and [ @ landmark] odd n = (n = 1 ) || n > 0 && even (n - 1 )
in Printf. printf " 'six is even' is %b n " (even 6 )
سيتم اجتياز المعلم المرتبط بـ "حتى" مرة واحدة (وليس ثلاث مرات!) في حين أن تدفق التحكم لن يمر عبر المعلم المرتبط بـ "Odd".
تعليقات التعليقات التوضيحية للهيكل [@@@landmark "auto"]
و [@@@landmark "auto-off"]
تنشيط أو إلغاء تنشيط الأجهزة التلقائية للوظائف ذات المستوى الأعلى في وحدة نمطية. في الوضع التلقائي ، يتم شرح جميع إعلانات الوظائف ضمنيًا. يمكن تمكين/تعطيل الأجهزة التلقائية لجميع الملفات عبر الخيار auto
في OCAML_LANDMARKS
، على النحو المفصل أدناه.
تتم قراءة متغير البيئة OCAML_LANDMARKS
على مرحلتين مختلفتين: عند تنفيذ إعادة كتابة PPX ، وعندما يتم تحميل وحدة المعالم بواسطة برنامج مصنوع. يتم تحليل هذا المتغير كقائمة مفصولة مفصولة بعناصر option=argument
أو option
، حيث يكون option
:
خلال مرحلة إعادة كتابة PPX (في وقت التجميع):
auto
(بدون وسيط): يقوم تشغيل الأجهزة التلقائية بشكل افتراضي (يتصرف كما لو أن كل وحدة تبدأ بالتعليقات التعليقات التوضيحية [@@@landmark "auto"]
).
threads
(بدون وسيط): يخبر امتداد PPX باستخدام وحدة Landmark_threads
بدلاً من معلم الوحدة Landmark
.
عند تحميل برنامج أداة (في وقت التشغيل):
format
مع الوسائط المحتملة: textual
(الافتراضي) أو json
. يتحكم في تنسيق الإخراج في التنميط الذي يمثل إما تمثيلًا صديقًا للوحدة أو ترميز JSON من callgraph.
threshold
مع رقم بين 0.0 و 100.0 كوسيطة (افتراضي: 1.0). إذا لم تكن العتبة صفرية ، فسيخفي الإخراج النصي العقد في callgraph أدناه هذه العتبة (في المئة من وقت الوالدين). هذا الخيار لا معنى له للتنسيقات الأخرى.
output
مع الوسيطة المحتملة: stderr
(افتراضي) ، stdout
، temporary
، <file>
(حيث <file>
هو مسار الملف). يخبر مكان إخراج نتائج التنميط. مع temporary
، سيتم طباعته في ملف مؤقت (سيتم طباعة اسم هذا الملف على الخطأ القياسي). يمكنك أيضًا استخدام temporary:<directory>
لتحديد الدليل الذي يتم إنشاء الملفات.
debug
بدون حجة. ينشط وضع المطول الذي يخرج آثار على Stderr في كل مرة يتم فيها استدعاء المعالم البدائية.
time
مع عدم وجود حجة. أيضا جمع الطوابع الزمنية Sys.time
أثناء التنميط.
off
دون حجة. تعطيل التنميط.
on
دون حجة. تمكين التنميط (الافتراضي ؛ قد يتم حذفه).
allocation
بدون حجة. أيضا جمع بيانات Gc.allocated_byte
.
يمكنك إما تجميع عارض الويب على جهاز الكمبيوتر الخاص بك أو تصفحه عبر الإنترنت. تحتاج إلى تحميل ملفات JSON باستخدام FilePicker ومن ثم يمكنك النقر حولها لتصفح callgraph.
الوحدة Landmark
ليست آمنة الخيط. إذا كان لديك عدة مؤشرات ترابط ، فيجب عليك التأكد من أن سلسلة رسائل واحدة تنفذ رمز أداة. لذلك يمكنك استخدام وحدة Landmark_threads
(المدرجة في المعالم.
قد يخفف التعليقات المتعلقة بالتعبيرات عن تعدد الأشكال (هذا ليس هو الحال بالنسبة لشرح التوضيح). على سبيل المثال ، ستفشل جزء الكود التالي في التجميع:
let test = ( fun x -> x)[ @ landmark " test " ]
in test " string " , test 1
تم ترخيص حزمة "المعالم هذه" من قبل Lexifi بموجب شروط ترخيص معهد ماساتشوستس للتكنولوجيا.
الاتصال: [email protected]