
في كثير من الأحيان ، عند حل مشكلات التحليل وإعداد البيانات ، تتم كتابة البرامج النصية لمرة واحدة ، ولا يتم توفير الدعم والتطوير على الإطلاق. هذا النهج له الحق في الوجود ، وخاصة في مجتمع الطلاب. ومع ذلك ، عندما يكون هناك أكثر من شخص يعمل مع الكود ، أو إذا كانت هناك حاجة إلى الحفاظ على الكود لأكثر من يوم عمل واحد ، فإن خيار تنظيم العمل في شكل كومة من الملفات غير مقبول.
لذلك ، سنتحدث اليوم عن موضوع مهم مثل إنشاء مشروع من البداية بلغة جوليا ، وكيفية تعبئته ، والأدوات التكنولوجية الموجودة لدعم التنمية.
مشروع
كما ذكرنا من قبل ، فإن البرامج النصية لمرة واحدة أو Jupyter Notebooks لها الحق في الوجود على سطح المكتب لشخص واحد ، لا سيما عند استخدام لغة البرمجة كآلة حاسبة متقدمة. لكن هذا النهج غير مناسب تمامًا لتطوير المشاريع التي يجب تطويرها وتشغيلها لسنوات. وبالطبع ، لدى Julia ، كمنصة تقنية ، أدوات توفر للمطورين هذه الفرصة.
بالنسبة للمبتدئين ، بضع نقاط عامة. جوليا لديها وحدة Pkg لإدارة الحزمة. أي مكتبة جوليا هي وحدة نمطية. إذا لم يتم تضمين الوحدة في مجموعة جوليا الأساسية ، يتم إصدارها كحزمة منفصلة. لكل حزمة يوجد ملف مشروع Project.toml
، والذي يحتوي على وصف للمشروع واعتماده على الحزم الأخرى. يوجد ملف ثاني - Manifest.toml
، والذي بخلاف Project.toml
، يتم إنشاؤه تلقائيًا ويحتوي على قائمة بجميع التبعيات اللازمة مع أرقام إصدار الحزمة. تنسيق ملف Toml هو لغة توم واضحة ، والحد الأدنى من اللغة .
حزمة تسمية القواعد
وفقًا للوثائق ، قد يتكون اسم الحزمة من أحرف وأرقام لاتينية. ويجب اختيار هذا الاسم بحيث يكون واضحًا لمعظم مستخدمي جوليا ، وليس فقط الخبراء في مجال ضيق.
- وينبغي تجنب المصطلحات والانكماشات المثيرة للجدل المستخدمة بشكل مختلف في مجالات مختلفة.
- لا تستخدم كلمة جوليا في اسم الحزمة.
- يجب تسمية الحزم التي توفر بعض الوظائف إلى جانب الأنواع الجديدة المعلنة فيها بصيغة الجمع.
◦ DataFrames يوفر نوع DataFrame.
◦ يوفر BloomFilters نوع BloomFilter.
the في الوقت نفسه ، لا يوفر JuliaParser نوعًا جديدًا ، والوظيفة الجديدة هي وظيفة JuliaParser.parse (). - يجب تفضيل الشفافية والشفافية باستخدام الاسم الكامل على الاختصار.
RandomMatrices
أقل غموضًا من RndMat
أو RMT
. - قد يتوافق الاسم مع تفاصيل مجال الموضوع. الأمثلة على ذلك:
◦ ليس لدى Julia حزم رسم الرسومات الخاصة بها. بدلاً من ذلك ، توجد حزم Gadfly
و PyPlot
و Winston
وغيرها ، كل منها يطبق منهجيته وطريقة استخدامه.
the في الوقت نفسه ، توفر SortingAlgorithms
واجهة كاملة لاستخدام خوارزميات الفرز. - في الحالات التي تكون فيها الحزم مجمعة على بعض مكتبات الطرف الثالث ، فإنها تحتفظ باسم هذه المكتبة. الأمثلة على ذلك:
CPLEX.jl
عبارة عن غلاف على مكتبة CPLEX
.
◦ MATLAB.jl
يوفر واجهة لتفعيل MATLAB
من جوليا.
في الوقت نفسه ، عادة ما يكون اسم مستودع بوابة git هو اللاحقة ".jl".
حزمة الجيل
أسهل طريقة لإنشاء حزمة هي توليدها باستخدام مولد مدمج في Julia. للقيام بذلك ، في وحدة التحكم ، تحتاج إلى الانتقال إلى الدليل الذي يجب إنشاء الحزمة فيه ، ثم قم بتشغيل julia ووضعه في وضع إدارة الحزمة:
julia> ]
الخطوة الأخيرة هي بدء مولد الحزمة عن طريق تحديد الاسم الذي نريد إعطاء الحزمة.
(v1.2) pkg> generate HelloWorld
نتيجةً لذلك ، يظهر دليل جديد في الدليل الحالي المطابق لاسم الحزمة ، ويمكن رؤية تركيبته باستخدام الأمر tree
(إذا كان مثبتًا):
shell> cd HelloWorld shell> tree . . ├── Project.toml └── src └── HelloWorld.jl 1 directory, 2 files
في هذه الحالة ، نرى مجموعة صغيرة ولكن غير كافية من الملفات لمشروع مصمم جيدًا.لمزيد من التفاصيل ، انظر https://julialang.imtqy.com/Pkg.jl/v1/creating-packages/ .
طريقة بديلة لإنشاء الحزم هي مع مولد PkgTemplates.jl . على عكس المولد المدمج ، فإنه يسمح لك بإنشاء مجموعة كاملة من ملفات الخدمة على الفور لخدمة الحزمة. العيب الوحيد هو أنه يجب تثبيت نفسه كحزمة.
الإجراء لإنشاء حزمة مع مساعدتها على النحو التالي. نحن ربط حزمة:
julia> using PkgTemplates
نقوم بإنشاء قالب يتضمن قائمة بالمؤلفين ، ورخصة ، ومتطلبات Julia ، وقائمة PkgTemplates
الإضافية لأنظمة التكامل المستمر (مثال من وثائق PkgTemplates
):
julia> t = Template(; user="myusername",
نحصل على القالب:
Template: → User: myusername → Host: github.com → License: ISC (Chris de Graaf, Invenia Technical Computing Corporation 2018) → Package directory: ~/code → Minimum Julia version: v0.7 → SSH remote: No → Commit Manifest.toml: No → Plugins: • AppVeyor: → Config file: Default → 0 gitignore entries • Codecov: → Config file: None → 3 gitignore entries: "*.jl.cov", "*.jl.*.cov", "*.jl.mem" • Coveralls: → Config file: None → 3 gitignore entries: "*.jl.cov", "*.jl.*.cov", "*.jl.mem" • GitHubPages: → 0 asset files → 2 gitignore entries: "/docs/build/", "/docs/site/" • TravisCI: → Config file: Default → 0 gitignore entries
الآن ، باستخدام هذا القالب ، يمكننا إنشاء حزم ببساطة عن طريق تحديد اسمهم:
julia> generate(t, "MyPkg1")
في الحد الأدنى من الإصدار ، قد يبدو القالب كما يلي:
julia> t = Template(; user="rssdev10", authors=["rssdev10"]) Template: → User: rssdev10 → Host: github.com → License: MIT (rssdev10 2019) → Package directory: ~/.julia/dev → Minimum Julia version: v1.0 → SSH remote: No → Add packages to main environment: Yes → Commit Manifest.toml: No → Plugins: None
إذا أنشأنا حزمة تسمى MyPkg2 من هذا القالب:
julia> generate(t, "MyPkg2")
ثم يمكننا التحقق من النتيجة مباشرة من جوليا:
julia> run(`git -C $(joinpath(t.dir, "MyPkg2")) ls-files`); .appveyor.yml .gitignore .travis.yml LICENSE Project.toml README.md REQUIRE docs/Manifest.toml docs/Project.toml docs/make.jl docs/src/index.md src/MyPkg2.jl test/runtests.jl
يجب ملاحظة الحقول التالية:
user="myusername"
، هو اسم إدخال التسجيل git.dir
- دليل لوضع رمز الحزمة. إذا لم يتم تحديد ذلك ، فسيتم إنشاؤه في دليل التطوير ~/.julia/dev
. علاوة على ذلك ، وفقًا لقواعد أنظمة ملفات unix ، يتم إخفاء ~/.julia
.
بعد إنشاء المشروع ، سيتم إنشاء مجموعة كافية من الملفات وسيتم إنشاء مستودع بوابة. علاوة على ذلك ، سيتم إضافة جميع الملفات التي تم إنشاؤها إلى هذا المستودع تلقائيًا.
موقع ملف نموذجي في المشروع
سنستعير صورة بترتيب نموذجي للملفات ومحتوياتها من https://en.wikibooks.org/wiki/Introducing_Julia/Modules_and_packages ، لكننا سنوسعها قليلاً:
Calculus.jl/
نضيف أن دليل deps
قد يحتوي على الملفات اللازمة للتجميع الصحيح للحزمة. على سبيل المثال ، deps/build.jl
هو برنامج نصي يتم تشغيله تلقائيًا عند تثبيت الحزمة. يمكن أن يحتوي البرنامج النصي على أي رمز لإعداد البيانات (قم بتنزيل مجموعة بيانات أو إجراء معالجة مسبقة) أو برامج أخرى ضرورية للعمل.
تجدر الإشارة إلى أنه لا يمكن أن يكون هناك سوى وحدة رئيسية واحدة في المشروع. هذا هو ، في المثال أعلاه - Calculus
. ومع ذلك ، في نفس المثال ، هناك وحدة نمطية Derivative
متداخلة تتصل عبر include
. انتبه لهذا. يتضمن الملف الذي يحتوي على نص ، وليس كوحدة نمطية ، والذي يحدث مع using
أو import
. لا تتضمن آخر وظيفتين فقط الوحدة النمطية ، ولكن تجبر جوليا على تجميعها ككيان منفصل. بالإضافة إلى ذلك ، ستحاول جوليا العثور على هذه الوحدة في حزم التبعية وإصدار تحذير بأنها مفقودة في Project.toml
. لذلك ، إذا كانت مهمتنا هي توفير الوصول الهرمي إلى الوظائف ، وتحديدها بمساحات الأسماء ، فسنضمِّن الملفات من خلال include
، وتفعيل الوحدة من خلال نقطة ، مما يشير إلى انتمائها المحلي. هذا هو:
module Calculus include("derivative.jl") import .Derivative ... end
ستكون الوظيفة derivative
التي يتم تصديرها من وحدة Derivative
متاحة لنا من خلال Calculus.Derivative.derivative()
Project.toml ملف المشروع
ملف المشروع هو ملف نصي. يتم الكشف عن أقسامها الرئيسية في وصف https://julialang.imtqy.com/Pkg.jl/v1/toml-files/
بعد إنشاء الملف ، جميع الحقول اللازمة موجودة بالفعل فيه. ومع ذلك ، قد تحتاج إلى تغيير جزء من الوصف وتغيير تكوين الحزم وإصداراتها والتبعيات المحددة لأنظمة التشغيل أو التكوينات المختلفة.
المجالات الرئيسية هي:
name = "Example" uuid = "7876af07-990d-54b4-ab0e-23690620f79a" version = "1.2.5"
name
- اسم الحزمة المختارة وفقًا لقواعد التسمية. uuid
هو معرف موحد يمكن إنشاؤه بواسطة مولد الحزمة أو أي مولد uuid
. version
- رقم إصدار الحزمة بتنسيق ثلاثة أرقام عشرية مفصولة بنقاط. هذا يتوافق مع تنسيق Semantic Versioning 2.0.0 . قبل الإصدار 1.0.0 المعلن ، أي تغييرات في واجهة البرنامج ممكنة. بعد إصدار هذا الإصدار ، يجب أن يمتثل مالك الحزمة لقواعد التوافق. يجب أن تنعكس أي تغييرات متوافقة في الرقم الثانوي (يمين). يجب أن تكون التغييرات غير المتوافقة مصحوبة بتغيير في العدد الكبير. بطبيعة الحال ، لا يوجد تحكم تلقائي في قاعدة الإصدار ، لكن عدم مراعاة القاعدة سيؤدي ببساطة إلى حقيقة أن مستخدمي الحزمة سيبدأون بشكل كبير في التوقف عن استخدام وترحيل الحزمة التي يلتزم مؤلفوها بهذه القاعدة.
يتم تقديم جميع تبعيات الحزمة في قسم [deps]
.
[deps] Example = "7876af07-990d-54b4-ab0e-23690620f79a" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
يحتوي هذا القسم على قائمة بالتبعية المباشرة لحزمتنا. تنعكس تبعيات Cascading في ملف Manifest.toml
، الذي يتم إنشاؤه تلقائيًا في دليل المشروع. يتم تمثيل جميع التبعيات =
أزواج =
. وعادة ، هذا الجزء غير ممتلئ بيديه. لهذا ، يتم توفير وظائف حزمة Pkg
. وغالبًا ما يتم ذلك من REPL
، REPL
إلى وضع إدارة الحزمة - ]
. بعد ذلك - add
العمليات ، rm
، st
، إلخ ، ولكن دائمًا في سياق الحزمة الحالية. إذا لم يكن كذلك ، فأنت بحاجة إلى تنفيذ activate .
.
يمكن حفظ Manifest.toml
في نظام التحكم في إصدار git
. يسمح لك هذا النهج الذي يحتوي على ملفين بإصلاح الحزم بشكل صارم في شجرة التبعية أثناء اختبار منتج البرنامج ، وبعد ذلك يتم ضمان أنه إذا تم نشر الحزمة الخاصة بنا في موقع جديد ، فسيتم تكرار نفس إصدارات حزم الجهات الخارجية في نفس المكان. أو ، على العكس ، في حالة عدم وجود Manifest.toml
ستُتاح Manifest.toml
الفرصة لاستخدام أي إصدارات متوفرة تفي بالشروط الأساسية.
يسمح لك المقطع [compat]
بتحديد إصدارات محددة من الحزم التي نطلبها.
[deps] Example = "7876af07-990d-54b4-ab0e-23690620f79a" [compat] Example = "1.2" julia = "1.1"
يتم تحديد الحزم بالاسم المستخدم مسبقًا في المقطع [compat]
. julia
يشير إلى إصدار جوليا نفسها.
عند تحديد الإصدارات ، تنطبق القواعد الواردة في https://julialang.imtqy.com/Pkg.jl/dev/compatibility/ . ومع ذلك ، يتم تحديد نفس القواعد في الإصدار الدلالي .
هناك العديد من قواعد الإصدار. على سبيل المثال:
[compat] Example = "1.2, 2"
يعني أن أي إصدار في النطاق [1.2.0, 3.0.0)
مناسب ، وليس بما في ذلك 3.0.0
. وهذا متوافق تمامًا مع قاعدة أبسط:
[compat] Example = "1.2"
علاوة على ذلك ، ببساطة تحديد رقم الإصدار هو شكل مختصر من "^1.2"
. مثال على التطبيق الذي يشبه:
[compat] PkgA = "^1.2.3" # [1.2.3, 2.0.0) PkgB = "^1.2" # [1.2.0, 2.0.0) PkgC = "^1" # [1.0.0, 2.0.0) PkgD = "^0.2.3" # [0.2.3, 0.3.0) PkgE = "^0.0.3" # [0.0.3, 0.0.4) PkgF = "^0.0" # [0.0.0, 0.1.0) PkgG = "^0" # [0.0.0, 1.0.0)
إذا كنا بحاجة إلى تحديد قيود أكثر صرامة ، فمن الضروري استخدام نموذج مع التلدة.
[compat] PkgA = "~1.2.3" # [1.2.3, 1.3.0) PkgB = "~1.2" # [1.2.0, 1.3.0) PkgC = "~1" # [1.0.0, 2.0.0) PkgD = "~0.2.3" # [0.2.3, 0.3.0) PkgE = "~0.0.3" # [0.0.3, 0.0.4) PkgF = "~0.0" # [0.0.0, 0.1.0) PkgG = "~0" # [0.0.0, 1.0.0)
حسنًا ، وبالطبع ، هناك إشارة إلى وجود علامات / عدم المساواة على قدم المساواة:
[compat] PkgA = ">= 1.2.3" # [1.2.3, ∞) PkgB = "≥ 1.2.3" # [1.2.3, ∞) PkgC = "= 1.2.3" # [1.2.3, 1.2.3] PkgD = "< 1.2.3" # [0.0.0, 1.2.2]
من الممكن تحديد عدة خيارات للتبعيات في قسم [targets]
. تقليديا ، في جوليا قبل الإصدار 1.2 ، تم استخدامه لتحديد التبعيات لاستخدام الحزمة ولإجراء الاختبارات. للقيام بذلك ، تم تحديد حزم إضافية في المقطع [extras]
، وتم سرد التكوينات الهدف مع أسماء الحزمة في [targets]
.
[extras] Markdown = "d6f4376e-aef5-505a-96c1-9c027394607a" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [targets] test = ["Markdown", "Test"]
بدءًا من جوليا 1.2 ، يوصى ببساطة بإضافة ملف مشروع منفصل test/Project.toml
.
التبعيات الإضافية
يمكن توصيل تبعيات إضافية عبر deps/build.jl
، ومع ذلك ، يتم توفير ملف Artifacts.toml
في هيكل مشروع جوليا. توفر Pkg.Artifacts
إدارة المشروع Pkg.Artifacts
وظائف لأتمتة تحميل التبعيات الإضافية. مثال على هذا الملف:
# Example Artifacts.toml file [socrates] git-tree-sha1 = "43563e7631a7eafae1f9f8d9d332e3de44ad7239" lazy = true [[socrates.download]] url = "https://github.com/staticfloat/small_bin/raw/master/socrates.tar.gz" sha256 = "e65d2f13f2085f2c279830e863292312a72930fee5ba3c792b14c33ce5c5cc58" [[socrates.download]] url = "https://github.com/staticfloat/small_bin/raw/master/socrates.tar.bz2" sha256 = "13fc17b97be41763b02cbb80e9d048302cec3bd3d446c2ed6e8210bddcd3ac76" [[c_simple]] arch = "x86_64" git-tree-sha1 = "4bdf4556050cb55b67b211d4e78009aaec378cbc" libc = "musl" os = "linux" [[c_simple.download]] sha256 = "411d6befd49942826ea1e59041bddf7dbb72fb871bb03165bf4e164b13ab5130" url = "https://github.com/JuliaBinaryWrappers/c_simple_jll.jl/releases/download/c_simple+v1.2.3+0/c_simple.v1.2.3.x86_64-linux-musl.tar.gz" [[c_simple]] arch = "x86_64" git-tree-sha1 = "51264dbc770cd38aeb15f93536c29dc38c727e4c" os = "macos" [[c_simple.download]] sha256 = "6c17d9e1dc95ba86ec7462637824afe7a25b8509cc51453f0eb86eda03ed4dc3" url = "https://github.com/JuliaBinaryWrappers/c_simple_jll.jl/releases/download/c_simple+v1.2.3+0/c_simple.v1.2.3.x86_64-apple-darwin14.tar.gz" [processed_output] git-tree-sha1 = "1c223e66f1a8e0fae1f9fcb9d3f2e3ce48a82200"
لن نتعمق في التفاصيل ، لأن الوصف الإضافي يعتمد على حالة الاستخدام المحددة. وظائف المكتبة artifact_hash
، download
، create_artifact
، bind_artifact
. راجع الوثائق https://julialang.imtqy.com/Pkg.jl/dev/artifacts/ لمزيد من التفاصيل.
تنفيذ التعليمات البرمجية الرئيسية وتصحيح الأخطاء
بالطبع ، نقوم بتحديد دليل التطوير بشكل صريح أو ضمني عند إنشاء الحزمة. ومع ذلك ، إذا لزم الأمر ، يمكننا تغييره. إذا تم إنشاء الحزمة بواسطة PkgTemplates
مع المعلمات الافتراضية ، ابحث عنها في دليل ~/.julia/dev
. على الرغم من أن الدليل مخفي ، فإن الانتقال إليه ممكن من خلال رابط مباشر في متصفح الملفات. بالنسبة إلى MacOS في Finder ، على سبيل المثال ، يتم ذلك عن طريق الضغط على Command + Shift + G. إذا تم إنشاء الحزمة في أي دليل آخر ، فما عليك سوى فتحها في محرر نصي. أفضل محرر للعمل مع جوليا كود هو Atom وكل ما يدعمه البرنامج المساعد uber-juno
. في هذه الحالة ، يمكنك الحصول على محرر نصوص مع التنسيق التلقائي للرمز ووحدة تحكم REPL لتنفيذ التعليمات البرمجية التفاعلية والقدرة على تنفيذ أجزاء التعليمات البرمجية المحددة فقط وعرض النتائج ، بما في ذلك عرض الرسومات. وأيضا ، خطوة خطوة مصحح الأخطاء. على الرغم من أنه يجب علينا أن نعترف أنه في الوقت الحالي بطيء جدًا ، لذلك وضع تصحيح الأخطاء الحالي - أولاً نعتقد أننا نريد التحقق من إخراج التصحيح ووضعه ، ثم نجري الاختبار للاختبار.
يوصى بأن تنظر إلى أنماط التصميم الشائعة للغات البرمجة الديناميكية . أيضا ، كتاب "التدريب العملي على أنماط التصميم مع جوليا 1.0. توم كوونغ" ورمز عينة لذلك . وعند تنفيذ البرامج ، يجب أن تأخذ في الاعتبار التوصيات المتعلقة بنمط برمجة Julia Style Guide .
من تعقيدات تصحيح الأخطاء ، يمكن الإشارة إلى حزمة Revise.jl
. يمكن ضبط تنشيطه في الملف .julia/config/startup.jl
فقط للوضع التفاعلي ، حيث يمكن تشغيل REPL من محرر Atom. يتيح لك Revise تعديل رمز الوظيفة داخل الحزمة الخاصة بنا دون إعادة تشغيل جلسة REPL ، وسيمكن كل تشغيل باستخدام / استيراد في اختباراتنا هذه التحديثات.
من أجل التطوير الفعال ، يوصى بتطوير الرمز الرئيسي والاختبارات التي تختبره بالتوازي. يتيح لك ذلك تنفيذ ما هو مطلوب حقًا فقط ، لأنه بخلاف ذلك ، في الاختبارات سيكون هناك وظائف غير ضرورية. لذلك ، يجب إزالتها. في جوهرها ، جوليا لا تقدم أي شيء محدد في مبادئ التنمية. ومع ذلك ، يتم التركيز على التطوير من خلال اختبار الوحدة هنا لأن Julia تقوم بتجميع التعليمات البرمجية ببطء إلى حد ما ، وفي وضع تصحيح الأخطاء خطوة بخطوة يتم تقليل الأداء إلى حد كبير. أي أن ذلك يعتمد على تطوير الاختبارات ، وتنظيمهم ، ومدى سرعة تصحيح الحزمة التي يتم تطويرها والتحقق منها.
اختبارات
موقع الاختبار النموذجي هو دليل الاختبار. يعد test/runtests.jl
ملف test/runtests.jl
نقطة الانطلاق لجميع الاختبارات.
فيما يتعلق بالمثال المذكور أعلاه ، فإن الشكل النموذجي للملف هو:
using Calculus
يوصى بتطوير ملفات اختبارات محددة على أساس تجميع الوظائف المختبرة. على سبيل المثال ، في وحدة Calculus
المشار إليها ، قد تكون هناك خوارزميات مختلفة لحساب المشتقات والتكاملات ، وما إلى ذلك ، وسيكون من المنطقي اختبارها باختبارات مختلفة موجودة في ملفات مختلفة.
لاختبار الوحدة ، توفر Julia وحدة Test
من مجموعة المكتبة الأساسية. تم @test
الماكرو @test
في هذه الوحدة ، والغرض منه هو التحقق من صحة العبارة المحددة. الأمثلة على ذلك:
julia> @test true Test Passed julia> @test [1, 2] + [2, 1] == [3, 3] Test Passed julia> @test π ≈ 3.14 atol=0.01 Test Passed
انتبه إلى الشكل الكامل لمشغل المقارنة التقريبي ≈
.
العبارة التحقق من اختيار الاستثناء هي @test_throws
. مثال - قم بإنشاء صفيف والوصول إلى الفهرس الذي يتجاوزه:
julia> @test_throws BoundsError [1, 2, 3][4] Test Passed Thrown: BoundsError
بناء مفيد هو @testset
. انها تسمح لك لتجميع البيانات الفردية في اختبار متصل منطقيا. على سبيل المثال:
julia> @testset "trigonometric identities" begin θ = 2/3*π @test sin(-θ) ≈ -sin(θ) @test cos(-θ) ≈ cos(θ) @test sin(2θ) ≈ 2*sin(θ)*cos(θ) @test cos(2θ) ≈ cos(θ)^2 - sin(θ)^2 end; Test Summary: | Pass Total trigonometric identities | 4 4
لكل مجموعة تم الإعلان عنها من خلال @testset
، يتم تشكيل جدول الاختبارات الخاص بها. أجنحة الاختبار يمكن أن تكون متداخلة. في حالة نجاحهم في النجاح ، يتم إصدار جدول ملخص ، في حالة الفشل - لكل مجموعة من الاختبارات سيتم إصدار إحصائياتها الخاصة.
julia> @testset "Foo Tests" begin @testset "Animals" begin @testset "Felines" begin @test foo("cat") == 9 end @testset "Canines" begin @test foo("dog") == 9 end end @testset "Arrays" begin @test foo(zeros(2)) == 4 @test foo(fill(1.0, 4)) == 15 end end Arrays: Test Failed Expression: foo(fill(1.0, 4)) == 15 Evaluated: 16 == 15 [...] Test Summary: | Pass Fail Total Foo Tests | 3 1 4 Animals | 2 2 Arrays | 1 1 2 ERROR: Some tests did not pass: 3 passed, 1 failed, 0 errored, 0 broken.
@test_broken
, @test_skip
.
. julia
:
--code-coverage={none|user|all}, --code-coverage Count executions of source lines (omitting setting is equivalent to "user") --code-coverage=tracefile.info Append coverage information to the LCOV tracefile (filename supports format tokens). --track-allocation={none|user|all}, --track-allocation Count bytes allocated by each source line (omitting setting is equivalent to "user")
code-coverage
— . ( ), . , . .cov
. .
:
- function vectorize(str::String) 96 tokens = str |> tokenizer |> wordpiece 48 text = ["[CLS]"; tokens; "[SEP]"] 48 token_indices = vocab(text) 48 segment_indices = [fill(1, length(tokens) + 2);] 48 sample = (tok = token_indices, segment = segment_indices) 48 bert_embedding = sample |> bert_model.embed 48 collect(sum(bert_embedding, dims=2)[:]) - end
track-allocation
— . , , , , .mem
.
:
- function vectorize(str::String) 0 tokens = str |> tokenizer |> wordpiece 6766790 text = ["[CLS]"; tokens; "[SEP]"] 0 token_indices = vocab(text) 11392 segment_indices = [fill(1, length(tokens) + 2);] 1536 sample = (tok = token_indices, segment = segment_indices) 0 bert_embedding = sample |> bert_model.embed 170496 collect(sum(bert_embedding, dims=2)[:]) - end
, . , , , , . , . .
— :
julia --project=@. --code-coverage --track-allocation test/runtests.jl
— Profile.jl
@profile
. https://julialang.org/blog/2019/09/profilers . @noinline
, . , fib
fib_r
.
julia> @noinline function fib(n) return n > 1 ? fib_r(n - 1) + fib_r(n - 2) : 1 end julia> @noinline fib_r(n) = fib(n) julia> @time fib(40) 0.738735 seconds (3.16 k allocations: 176.626 KiB) 165580141 julia> using Profile julia> @profile fib(40) 165580141 julia> Profile.print(format=:flat, sortedby=:count) Count File Line Function 12 int.jl 52 - 14 int.jl 53 + 212 boot.jl 330 eval 5717 REPL[2] 1 fib_r 6028 REPL[1] 2 fib julia> count(==(0), Profile.fetch()) 585
@profile fib(40)
. Profile.print(format=:flat, sortedby=:count)
. , , , fib_r
fib
, . , :
julia> Profile.print(format=:tree) 260 REPL[1]:2; fib(::Int64) 112 REPL[1]:1; fib_r(::Int64) 212 task.jl:333; REPL.var"##26#27" 212 REPL.jl:118; macro expansion 212 REPL.jl:86; eval_user_input 212 boot.jl:330; eval ╎ 210 REPL[1]:2; fib ╎ 210 REPL[1]:1; fib_r ╎ 210 REPL[1]:2; fib ╎ 210 REPL[1]:1; fib_r ╎ 210 REPL[1]:2; fib ╎ ╎ 210 REPL[1]:1; fib_r ╎ ╎ 210 REPL[1]:2; fib ╎ ╎ 210 REPL[1]:1; fib_r ╎ ╎ 210 REPL[1]:2; fib ╎ ╎ 210 REPL[1]:1; fib_r ╎ ╎ ╎ 210 REPL[1]:2; fib ╎ ╎ ╎ 210 REPL[1]:1; fib_r ╎ ╎ ╎ 210 REPL[1]:2; fib ╎ ╎ ╎ 210 REPL[1]:1; fib_r ╎ ╎ ╎ 210 REPL[1]:2; fib ...
. PProf.jl, .

. https://github.com/vchuravy/PProf.jl .
doc
. https://habr.com/ru/post/439442/
, , Julia .
Project.toml
, . , , - , , .
, , . , — . :
, , . , , git clone, . PackageCompiler.jl
. , , - .
C
- , , ( - , ), deps, deps/build.jl
. . , , , . , , , , . , , build.jl
, :
. julia --project=@.
Julia Project.toml
. , — build.jl
, executable
. , julia --project=@. build.jl
.
Pkg.activate(".")
( Project.toml
).
Pkg.build()
, C-, . deps/build.jl
, .
Pkg.test()
. , -, , . -, , . coverage=true
. , . build.jl
.
, . , PkgTempletes
. — Gitlab CI, Travis CI, GitHub , .
استنتاج
, , Julia. , , . , — , -, , . , .
مراجع