تقنية
لكتابة مترجم JIT سريع، ستحتاج إلى معرفة كيفية كتابة لغة التجميع

تاريخيًا، كانت الترجمة الفورية السريعة (JIT) فنًا أسود. لكتابة مترجم JIT سريع، ستحتاج إلى معرفة كيفية كتابة لغة التجميع. مثال على ذلك: لا توجد قاعدة بيانات جاهزة للإنتاج اليوم لديها مترجم JIT خاص بها.
جميعها إما تستخدم LLVM أو تولّد كود C/C++. كل من هذين الخيارين يعاني من أوقات ترجمة عالية، مما يحد من قابلية تطبيقهما. الآن، مع استخدام الذكاء الاصطناعي، أصبح من الأسهل من أي وقت مضى كتابة مترجم JIT بأوقات ترجمة سريعة من خلال استهداف لغة التجميع مباشرة.
هذا أيضًا مجال فرصة لقواعد البيانات الجديدة لتحسين القواعد القديمة. عند بناء pgrust، اعتقدت في البداية أنه سيكون من الصعب حقًا تنفيذ مترجم JIT. في النهاية، وجدته أسهل بكثير مما توقعت بفضل مساعدة الذكاء الاصطناعي، وهو جزء من سبب سرعة pgrust.
يترجم مترجم JIT الخاص بـ pgrust الكود في حوالي 5 ميكروثانية، مما يمكننا من ترجمة كل استعلام SQL عبر JIT، وليس فقط مجموعة فرعية منها. في هذا المنشور، سأرشدك خلال كيفية بناء مترجم JIT سريع خاص بك. سنبني محرك تعبيرات منتظمة بسيط يستخدم الترجمة الفورية JIT كمثال.
الترجمة الفورية JIT هي ممارسة توليد كود مُترجم في وقت التشغيل أو "في الوقت المناسب". عند القيام بها بشكل صحيح، يمكن أن تؤدي إلى مكاسب أداء كبيرة، غالبًا في حدود 2-5 مرات وأحيانًا أكثر. حالة الاستخدام الرئيسية للترجمة الفورية JIT هي عندما تكون هناك معلومات تحصل عليها في وقت التشغيل تغير بشكل جذري سلوك برنامجك.
هذا شائع بشكل خاص مع مفسرات لغات البرمجة؛ فهي تتلقى الكود لتنفيذه في وقت التشغيل. مترجمات JIT مفيدة أيضًا في مجالات تتجاوز لغات البرمجة، مثل تحليل البيانات. أحيانًا لا تعرف مخطط البيانات التي تحللها حتى وقت التشغيل، ويمكن أن يساعد JIT في ذلك.
للبدء، دعنا ننفذ محرك تعبيرات منتظمة بسيط. للتبسيط، سندعم ميزتين فقط: السلاسل الحرفية والتكرار (أي التعبير المنتظم *). سنتخطى أيضًا المحلل اللغوي ونمثل التعبير المنتظم كهياكل Rust محللة بالفعل.
هذا يعني أننا سنكون قادرين على دعم سلاسل مثل: ولكن لا تناوب ولا lookbehind ولا أي شيء من هذا القبيل. في الكود، هذا بسيط جدًا. سيكون لدينا 3 أنواع من العقد: عقدة سلسلة حرفية، وعقدة تكرار، وعقدة تسلسل، وهي مزيج من عقدتين. هذا يبدو هكذا: كتابة مفسر لمحرك التعبيرات المنتظمة لدينا هي أيضًا مباشرة: الآن محرك التعبيرات المنتظمة هذا بسيط جدًا. إنه أقل من 20 سطرًا من الكود، لكن دعنا نرى أداءه.
للمقارنة، سنقارن الكود مع كود مكتوب يدويًا خصيصًا للتعبير المنتظم. لمثالنا، سنستخدم التعبير المنتظم b(an)*. الكود المكتوب يدويًا يبدو هكذا: (هناك طرق لتحسين هذا الكود وجعله أسرع بكثير، لكن لأغراضنا، يعد مقارنة جيدة).
عندما أقيس بعض الأمثلة ضد هذين، أحصل على أن النسخة المكتوبة يدويًا أسرع 10-20 مرة من المفسر. من الواضح أن هناك مجالًا كبيرًا للتحسين. الآن دعنا نلقي نظرة على كيفية استخدام الترجمة الفورية JIT للحصول على محرك تعبيرات منتظمة عام يؤدي بنفس جودة النسخة المكتوبة يدويًا. هناك خطوتان لترجمة الكود عبر JIT.
أولاً، توليد لغة التجميع للكود الذي تريد تشغيله. بمجرد حصولك على الكود، تقوم بعد ذلك بتغليف كود التجميع في دالة يمكنك استدعاؤها مثل أي كود آخر في برنامجك. لتوليد لغة التجميع، سنستخدم متغيرًا من نهج يسمى copy-and-patch.
الفكرة هي أن لدينا سلسلة من القوالب في لغة التجميع للعمليات المختلفة التي نريد ترجمتها عبر JIT. تسمى هذه القوالب "استنسلات". عندما نريد ترجمة عملية عبر JIT، نأخذ الاستنسل المرتبط ونقوم بتعديلات صغيرة بناءً على خصوصيات العملية. مشابه جدًا لملء استنسل حقيقي.
المصدر: Hacker News
الأكثر قراءة في هذا التصنيف
جاري تحميل المقال…