تطوير أداة مساعدة على GraalVM

بيان المشكلة


بشكل دوري ، لدي مهمة مشاركة الملفات على شبكة محلية ، على سبيل المثال ، مع زميل مشروع.


يمكن أن يكون هناك العديد من الحلول لهذا - Samba / FTP / scp. يمكنك ببساطة تحميل الملف إلى مكان عام مثل Google Drive أو إرفاقه بمهمة في جيرا أو حتى إرساله عبر البريد الإلكتروني.


لكن كل هذا ، بدرجة أو بأخرى ، غير مرن ، في مكان ما يحتاج إلى تعديل أولي وله حدوده الخاصة (على سبيل المثال ، الحد الأقصى لحجم الاستثمار).


وتريد شيئا أكثر خفيفة الوزن ومرونة.


لقد فوجئت دائمًا بسرور من الفرصة في Linux ، باستخدام الوسائل المتاحة ، لبناء حل عملي بسرعة.


قل ، لقد قمت غالبًا بحل المهمة المذكورة أعلاه باستخدام بيثون النظام مع السطر المفرد التالي


$ python3 -mhttp.server Serving HTTP on 0.0.0.0 port 8000 ... 

يقوم هذا الأمر ببدء تشغيل خادم الويب في المجلد الحالي ويسمح لك بالحصول على قائمة بالملفات وتنزيلها من خلال واجهة الويب. يمكن إلقاء المزيد من هذه الأشياء هنا .


هناك العديد من المضايقات. الآن ، من أجل نقل رابط التنزيل إلى زميل ، تحتاج إلى معرفة عنوان IP الخاص بك على الشبكة.


من المريح استخدام الأمر


 $ ifconfig -a 

ثم من قائمة واجهات الشبكة الناتجة ، حدد الواجهة المناسبة ثم قم بإنشاء رابط للنموذج http: // IP: 8000 ، والذي يمكنك إرساله يدويًا.


الإزعاج الثاني: هذا الخادم مترابط. هذا يعني أنه بينما يقوم أحد زملائك بتنزيل الملف ، لن يتمكن الثاني من تنزيل قائمة الملفات.


ثالثًا ، إنه غير مرن. إذا كنت بحاجة إلى نقل ملف واحد فقط ، فسيؤدي ذلك إلى فتح المجلد بأكمله ، أي سيكون عليك القيام بهذه الإيماءات (ثم تنظيف القمامة):


 $ mkdir tmp1 $ cp file.zip tmp1 $ cd tmp1 $ python3 -mhttp.server 

الإزعاج الرابع - لا توجد طريقة سهلة لتنزيل كامل محتويات المجلد.


لنقل محتويات المجلد ، عادة ما يستخدمون تقنية تسمى أنبوب قطران القطران .


يفعلون شيئا مثل هذا:


 $ ssh user@host 'cd /path/to/source && tar cf - .' | cd /path/to/destination && tar xvf - 

إذا لم يكن الأمر واضحًا فجأة ، فسأشرح كيف يعمل. الجزء الأول من الأمر tar cf - . ينشئ أرشيف محتويات المجلد الحالي ويكتب إلى الإخراج القياسي. علاوة على ذلك ، يتم نقل هذا الإخراج عبر الأنابيب عبر قناة ssh آمنة إلى إدخال أمر tar xvf - مشابه tar xvf - والذي يقوم بالإجراء المعاكس ، أي يقرأ الإدخال القياسي و unzips إلى المجلد الحالي. في الواقع ، يتم نقل أرشيف الملفات ، ولكن دون إنشاء ملف وسيط!


إزعاج هذا النهج واضح أيضا. نحن بحاجة إلى وصول ssh من جهاز لآخر ، وهذا لا يتم على الإطلاق في الحالة العامة.


هل من الممكن تحقيق كل ما سبق ، ولكن بدون هذه المشكلات الموصوفة؟


لذلك ، حان الوقت لإضفاء الطابع الرسمي على ما سنقوم ببنائه:


  1. برنامج سهل التثبيت (ثنائي ثابت)
  2. والتي سوف تسمح لك بنقل كل من ملف ومجلد مع جميع المحتويات
  3. مع ضغط اختياري
  4. الذي يسمح للمضيف بتنزيل الملف (الملفات) باستخدام أدوات * nix القياسية فقط (wget / curl / tar)
  5. سيقوم البرنامج فورًا بإصدار الأوامر الدقيقة للتحميل

قرار


في مؤتمر JEEConf ، الذي حضرته منذ وقت ليس ببعيد ، تم طرح موضوع Graal مرارًا وتكرارًا. هذا الموضوع بعيد عن أن يكون جديدًا ، لكن بالنسبة لي كان من المحتم أن أشعر في النهاية بهذا الوحش بيدي.


بالنسبة لأولئك الذين لم يدخلوا بعد في الموضوع (هل هناك بالفعل شيء من هذا القبيل حتى الآن؟ OO) اسمحوا لي أن أذكركم بأن GraalVM عبارة عن JVM تم ضخه من Oracle مع ميزات إضافية ، أبرزها:


  1. Polyglot JVM - القدرة على تشغيل Java و Javascript و Python و Ruby و R وما إلى ذلك بسلاسة قانون
  2. دعم لتجميع AOT - تجميع جافا مباشرة في ثنائي الأصلي
  3. ميزة أقل وضوحًا ، لكنها رائعة جدًا - تمت إعادة كتابة برنامج التحويل البرمجي C2 من C ++ إلى Java من أجل تطوير أكثر ملاءمة. وقد حقق هذا بالفعل نتائج ملحوظة. يقوم هذا المحول البرمجي بتحسينات أكثر بكثير في مرحلة تحويل كود جافا إلى كود أصلي. على سبيل المثال ، يمكنها إزالة التخصيصات بشكل أكثر فعالية. كان Twitter قادرًا على تقليل استهلاك وحدة المعالجة المركزية بنسبة 11٪ فقط عن طريق تشغيل هذا الإعداد ، مما أدى إلى توفير كبير في الموارد (والمال).

يمكنك تحديث فكرة Graal ، على سبيل المثال ، في مقالة habr هذه .


سنكتب بلغة Java ، لذلك ستكون الميزة الأكثر أهمية بالنسبة لنا هي تجميع AOT.


في الواقع ، يتم تقديم نتيجة التطوير في مستودع جيثب هذا .


مثال للاستخدام لنقل ملف واحد:


 $ serv '/path/to/report.pdf' To download the file please use one of the commands below: curl http://192.168.0.179:17777/dl > 'report.pdf' wget -O- http://192.168.0.179:17777/dl > 'report.pdf' curl http://192.168.0.179:17777/dl?z --compressed > 'report.pdf' wget -O- http://192.168.0.179:17777/dl?z | gunzip > 'report.pdf' 

مثال على استخدام عند نقل محتويات مجلد (جميع الملفات بما في ذلك الملفات المرفقة!):


 $ serv '/path/to/folder' To download the files please use one of the commands below. NB! All files will be placed into current folder! curl http://192.168.0.179:17777/dl | tar -xvf - wget -O- http://192.168.0.179:17777/dl | tar -xvf - curl http://192.168.0.179:17777/dl?z | tar -xzvf - wget -O- http://192.168.0.179:17777/dl?z | tar -xzvf - 

نعم بسيط جدا


يرجى ملاحظة - البرنامج نفسه يحدد عنوان IP الصحيح الذي ستتوفر الملفات عنده للتنزيل.


الملاحظات / الأفكار


من الواضح أن أحد الأهداف في إنشاء البرنامج هو الاكتناز. وها هي النتيجة التي تحققت:


 $ du -hs `which serv` 2.4M /usr/local/bin/serv 

بشكل لا يصدق ، فإن JVM بالكامل ، إلى جانب رمز التطبيق ، يندمجان في عدد قليل من البيجابايت البائسة! بالطبع ، كل شيء خاطئ إلى حد ما ، ولكن المزيد عن ذلك في وقت لاحق.


في الواقع ، ينتج المحول البرمجي Graal ثنائيًا أكبر قليلاً من حجمه 7 ميغابايت. قررت لضغط مزيد من ذلك مع UPX .


اتضح أن هذه فكرة جيدة ، حيث زاد وقت الإطلاق في الوقت الذي كانت فيه ضئيلة للغاية:


خيار غير مضغوط:


 $ time ./build/com.cmlteam.serv.serv -v 0.1 real 0m0.001s user 0m0.001s sys 0m0.000s 

مضغوط:


 $ time ./build/serv -v 0.1 real 0m0.021s user 0m0.021s sys 0m0.000s 

للمقارنة ، وقت الاطلاق في "الطريقة التقليدية":


 $ time java -cp "/home/xonix/proj/serv/target/classes:/home/xonix/.m2/repository/commons-cli/commons-cli/1.4/commons-cli-1.4.jar:/home/xonix/.m2/repository/org/apache/commons/commons-compress/1.18/commons-compress-1.18.jar" com.cmlteam.serv.Serv -v 0.1 real 0m0.040s user 0m0.030s sys 0m0.019s 

كما ترون ، مرتين بطيئة مثل إصدار UPX.


بشكل عام ، يعد وقت البدء القصير أحد نقاط قوة GraalVM. هذا ، بالإضافة إلى انخفاض استهلاك الذاكرة ، يؤدي إلى حماسة كبيرة حول استخدام هذه التكنولوجيا للخدمات الميكروية والخوادم.


حاولت أن أجعل منطق البرنامج أقل ما يمكن وأستخدم أقل عدد ممكن من المكتبات. من حيث المبدأ ، هذا النهج له ما يبرره عمومًا ، وفي هذه الحالة كان لدي مخاوف من أن إضافة تبعيات مخضرمة من جهة خارجية من شأنها أن "تزن" ملف البرنامج الناتج بشكل كبير.


على سبيل المثال ، لهذا السبب لم أستخدم تبعية جهة خارجية لخادم ويب Java (وهناك الكثير لكل ذوق ولون) ، لكنني استخدمت تطبيق JDK لخادم الويب من com.sun.net.httpserver.* الحزمة. في الواقع ، يعتبر استخدام com.sun.* Package بمثابة com.sun.* ، لكني اعتبرت هذا مسموحًا به في هذه الحالة ، لأنني أترجم إلى كود أصلي ، وبالتالي ، لا توجد مسألة توافق بين JVM.


ومع ذلك ، كانت مخاوفي عبثا. في البرنامج ، استخدمت اثنين من التبعيات للراحة


  1. commons-cli - لتحليل وسيطات سطر الأوامر
  2. commons-compress - لإنشاء ملف tarball للمجل وضغط gzip اختياري

في الوقت نفسه ، زاد حجم الملف قليلاً جدًا. سأغامر بالاقتراح بأن برنامج التحويل البرمجي Graal ذكي جدًا في عدم وضع جميع عبوات المكونات الإضافية في الملف القابل للتنفيذ ، ولكن فقط الشفرة الصادرة منها والتي يتم استخدامها فعليًا بواسطة رمز التطبيق.


يتم إجراء التجميع إلى رمز Graal الأصلي بواسطة الأداة المساعدة للصور الأصلية . تجدر الإشارة إلى أن هذه العملية تستهلك الكثير من الموارد. لنفترض أن هذه العملية تستغرق 19 ثانية بناءً على تهيئتي غير البطيئة باستخدام وحدة المعالجة المركزية Intel 7700K. لذلك ، أوصي أنه عند تطوير ، تشغيل البرنامج كالمعتاد (عبر جافا) ، وجمع ثنائي في المرحلة النهائية.


النتائج


التجربة ، كما يبدو لي ، كانت ناجحة للغاية. عند تطوير مجموعة أدوات Graal ، لم أواجه أي مشاكل لا يمكن التغلب عليها أو حتى ذات أهمية. كل شيء يعمل بشكل متوقع وثابت. على الرغم من أنه من شبه المؤكد ، لن يكون كل شيء سلسًا إذا حاولت إنشاء شيء أكثر تعقيدًا بهذه الطريقة ، على سبيل المثال ، تطبيق على Spring Boot . ومع ذلك ، فقد تم بالفعل تقديم عدد من المنصات التي أعلن فيها الدعم المحلي لغراال. من بينها Micronaut ، Microprofile ، Quarkus .


بالنسبة لمزيد من التطوير للمشروع ، فإن قائمة التحسينات المخططة للإصدار 0.2 جاهزة بالفعل. أيضًا ، في الوقت الحالي ، يتم تطبيق تجميع الثنائي النهائي فقط لنظام التشغيل Linux x64. آمل أن يتم إصلاح هذا الإهمال في المستقبل ، خاصة وأن برنامج التحويل البرمجي native-image من Graal يدعم MacOS و Windows. لسوء الحظ ، لا يدعم التجميع المتقاطع ، مما يجعل الأمور أسهل بكثير.


آمل أن تكون الأداة المقدمة مفيدة لشخص واحد على الأقل من مجتمع habr ذو السمعة الطيبة. سأكون سعيدًا بشكل مضاعف إذا كان هناك من يريد المساهمة في المشروع .

Source: https://habr.com/ru/post/ar451574/


All Articles