Design: الاقتراح: أضف روابط نوع بين اللغات

تم إنشاؤها على ١ مايو ٢٠١٩  ·  61تعليقات  ·  مصدر: WebAssembly/design

يعد WebAssembly حاليًا جيدًا جدًا في تنفيذ التعليمات البرمجية المكتوبة بلغات عشوائية من مترجم معين (عادةً JS) ، ولكنه يفتقر إلى العديد من الميزات الأساسية عندما يتعلق الأمر بدمج لغات عشوائية متعددة معًا .

إحدى هذه الميزات هي نظام الكتابة الحيادي اللغة. أود أن أقترح إضافة نظام (أنظمة) واحد أو أكثر إلى WebAssembly.

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

لماذا نهتم بإمكانية التشغيل البيني اللغوي؟

تشمل فوائد الحواجز الأقل من اللغة إلى اللغة ما يلي:

  • المزيد من المكتبات لمستخدمي wasm : هذا

  • اعتماد أسهل للغات الصغيرة: في السوق الحالية ، غالبًا ما يكون من الصعب على اللغات التي ليس لديها دعم من الشركة أن تحصل على قوة جذب. يجب أن تتنافس اللغات الجديدة (وحتى اللغات مثل D مع سنوات من الصقل) مع اللغات ذات النظم البيئية الكبيرة ، وتعاني من افتقارها للمكتبات. ستسمح لهم إمكانية التشغيل البيني اللغوي باستخدام الأنظمة البيئية الحالية مثل Python أو Java.

  • سلاسل أدوات حيادية لغوية أفضل : في الوقت الحالي ، تمتلك معظم اللغات مخطط تحميل مكتبة خاص بها ومدير حزم (أو ، في حالة C / C ++ ، العديد من البرامج غير الرسمية). تعد كتابة منشئ مشروع حيادي اللغة أمرًا صعبًا ، لأن هذه اللغات غالبًا ما تحتوي على تبعيات دقيقة ، وحالات عدم توافق ABI ، والتي تتطلب حلًا موحدًا على مستوى المشروع لحلها. من شأن نظام الروبوت بين اللغات أن يجعل من السهل تقسيم المشاريع إلى وحدات أصغر ، والتي يمكن معالجتها بواسطة حل يشبه npm.

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

متطلبات

مع أخذ ذلك في الاعتبار ، أريد أن أوجز المتطلبات التي يحتاجها نظام الكتابة بين اللغات لتمريرها.

أنا أكتب في ظل افتراضات مفادها أن نظام الكتابة سيتم استخدامه بشكل صارم للتعليق على الوظائف التي يتم تمريرها بين الوحدات ، ولن أتحقق من كيفية استخدام اللغات لذاكرتها الخطية أو المدارة بأي شكل من الأشكال.

لكي تكون مفيدة حقًا في إعداد wasm ، سيحتاج نظام الكتابة هذا إلى:

1 - السلامة

  • النوع الآمن: يجب أن يكون للمستدعي حق الوصول إلى البيانات التي يحددها المتصل فقط ، نمط قدرات الكائن.

    • يجب "نسيان" الذاكرة في نهاية المكالمة. يجب ألا يتمكن المستدعي من الوصول إلى بيانات المتصل والعودة ثم الوصول إلى تلك البيانات مرة أخرى بأي شكل.

2 - النفقات العامة

  • يجب أن يكون المطورون مرتاحين لإجراء مكالمات بين الوحدات بانتظام ، على سبيل المثال ، في حلقة تصيير.

    • نسخة صفرية: يجب أن يكون نظام الكتابة معبرًا بما يكفي للسماح للمترجمين الفوريين بتنفيذ استراتيجيات النسخ الصفري إذا أرادوا ذلك ، ومعبّرًا بدرجة كافية لهؤلاء المنفذين لمعرفة متى تكون النسخة الصفرية هي الأمثل.

3 - الرسوم البيانية الهيكلية

  • يجب أن يشتمل نظام الكتابة على هياكل ومؤشرات اختيارية ومصفوفات متغيرة الطول وشرائح وما إلى ذلك.

    • من الناحية المثالية ، يجب أن يكون المتصل قادرًا على إرسال رسم بياني كائن مبعثر في الذاكرة مع احترام المتطلبات 1 و 2.

4 - أنواع المراجع

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

5 - جسر بين تخطيطات الذاكرة

  • هذه نقطة مهمة جدا. فئات اللغات المختلفة لها متطلبات مختلفة. قد ترغب اللغات التي تعتمد على الذاكرة الخطية في تمرير شرائح من الذاكرة ، بينما قد ترغب اللغات التي تعتمد على GC في تمرير مراجع GC.

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

    • قد تسمح الارتباطات الإضافية أيضًا بالتخزين المؤقت واستراتيجيات التحسين الأخرى.

    • يجب أن يكون عمل التحويل عند تمرير البيانات بين وحدتين شفافًا للمطور ، طالما أن الأنواع الدلالية متوافقة.

6 - معالجة أخطاء وقت الترجمة

  • يجب أن يكون أي خطأ يتعلق بوسائط استدعاء الوظيفة غير الصالحة قابلاً للاكتشاف والتعبير في وقت الترجمة ، على عكس ، على سبيل المثال ، JS ، حيث يتم طرح TypeErrors في وقت التشغيل عند محاولة تقييم الوسيطة.
  • من الناحية المثالية ، ينبغي لمجمعي اللغة أنفسهم اكتشاف أخطاء الكتابة عند استيراد وحدات الصيغ ، وإخراج الأخطاء التعبيرية والاصطلاحية للمستخدم. الشكل الذي يجب أن يتخذه هذا التحقق من الأخطاء يجب أن يتم تفصيله في مستودع اصطلاحات الأدوات .
  • هذا يعني أن IDL مع المحولات الحالية للغات أخرى سيكون ميزة إضافية.

7 - توفير نقطة شيلينغ للتفاعل بين اللغات

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

التنفيذ المقترح

ما أقترحه هو إضافة الارتباطات بـ Cap'n'Proto IDL بواسطة kentonv إلى Webassembly.

سيعملون بطريقة مماثلة لارتباطات WebIDL: تقوم وحدات ISM بتصدير الوظائف ، وتستخدم تعليمات خاصة لربطها بالتوقيعات المطبوعة ؛ وحدات أخرى تقوم باستيراد هذه التواقيع ، وربطها بوظائفها.

يُقصد بالصيغة الزائفة التالية إعطاء فكرة عما ستبدو عليه هذه الارتباطات ؛ إنه تقريبي ومستوحى بشكل كبير من اقتراح WebIDL ، ويركز بشكل أكبر على التحديات التقنية بدلاً من توفير قوائم شاملة من التعليمات.

سيتم تخزين تعليمات ربط Capnproto في قسم

أنواع Cap'n'proto

سيحتاج المعيار إلى تمثيل داخلي للغة مخطط capnproto . كمثال ، نوع Capnproto التالي:

`` Cap'n Proto
شخص منظم {
name @ 0 : نص ؛
تاريخ الميلاد @ 3 : التاريخ ؛

البريد الإلكتروني @ 1 : نص ؛
الهواتف @ 2 : قائمة (رقم الهاتف) ؛

رقم PhoneNumber {
رقم @ 0 : نص ؛
اكتب @ 1 : النوع ؛

enum Type {
  mobile @0;
  home @1;
  work @2;
}

}
}

تاريخ البناء {
السنة @ 0 : Int16 ؛
الشهر @ 1 : UInt8 ؛
اليوم @ 2 : UInt8 ؛
}

might be represented as

```wasm
(<strong i="32">@capnproto</strong> type $Date (struct
    (field "year" Int16)
    (field "month" UInt8)
    (field "day" UInt8)
))
(<strong i="33">@capnproto</strong> type $Person_PhoneNumber_Type (enum 0 1 2))
(<strong i="34">@capnproto</strong> type $Person_PhoneNumber (struct
    (field "number" Text)
    (field "type" $Person_PhoneNumber_Type)
))
(<strong i="35">@capnproto</strong> type $Person (struct
    (field "name" Text)
    (field "email" Text)
    (field "phones" (generic List $Person_PhoneNumber))
    (field "birthdate" $Data)
))

التسلسل من الذاكرة الخطية

تمرر رسائل Capnproto نوعين من البيانات: المقاطع (بايت خام) ، والإمكانيات.

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

(يمكن وضع نهج أفضل للقدرات ، لتجنب عمليات التحقق من نوع وقت التشغيل.)

لاحظ أن حسابات التسلسل الفعلية ستحدث في كود الغراء ، إن وجدت (انظر إنشاء رمز الغراء ).

عوامل الربط

| عامل | الوساطة | الأطفال | الوصف |
| : --- | : --- | : --- | : --- |
| الجزء | قبالة ‑ معرف
لين ‑ idx | | يأخذ القيمتين الصادرتين off-idx 'th و len-idx ' th من المجموعة المصدر ، والتي يجب أن تكون كلاهما i32 s ، كإزاحة وطول شريحة من الذاكرة الخطية في أي قطعة مخزنة. |
| مأسور | قبالة ‑ معرف
لين ‑ idx | | يأخذ القيمتين الصادرتين off-idx 'th و len-idx ' th من المجموعة المصدر ، والتي يجب أن تكون كلاهما i32 s ، كإزاحة وطول شريحة الجدول التي يتم تخزين جدول القدرة. |
| رسالة | نوع capnproto
قدرة الجدول | شرائح | لإنشاء رسالة capnproto بالتنسيق capnproto-type ، باستخدام جدول الإمكانيات المتوفرة والمقاطع. |

التسلسل من الذاكرة المدارة

من الصعب تحديد سلوك معين قبل هبوط اقتراح GC. لكن التنفيذ العام هو أن روابط capnproto ستستخدم عامل تحويل واحدًا للحصول على أنواع capnproto من أنواع GC.

ستكون قواعد التحويل للأنواع منخفضة المستوى واضحة إلى حد ما: تحويل i8 إلى Int8 و UInt8 و bool ، و i16 يتحول إلى Int16 ، وما إلى ذلك. ستتحول الأنواع عالية المستوى إلى معادلاتها capnproto: تحويل مراجع البنية والمصفوفات إلى مؤشرات ومراجع غير شفافة تحويل إلى قدرات.

سيحتاج أي اقتراح أكثر اكتمالاً إلى تحديد استراتيجية للتعداد والنقابات.

عوامل الربط

| عامل | الوساطة | الأطفال | الوصف |
| : --- | : --- | : --- | : --- |
| كـ | نوع capnproto
idx | | تأخذ القيمة الصرفية idx 'th من tuple المصدر ، والتي يجب أن تكون مرجعًا ، وتنتج قيمة capnproto بقيمة capnproto-type . |

إلغاء التسلسل إلى الذاكرة الخطية

يشبه إلغاء التسلسل إلى الذاكرة الخطية في الغالب التسلسل منه ، مع تحذير إضافي واحد: غالبًا لا يعرف كود wasm مسبقًا مقدار الذاكرة التي سيستغرقها نوع capnproto ، ويحتاج إلى تزويد المضيف بنوع من طريقة إدارة الذاكرة الديناميكية .

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

قد يكون الحل الآخر هو السماح لخرائط الربط الواردة بالارتباط بتعبيرات ربط واردة (وبالتالي وظيفتان): أحدهما يخصص الذاكرة لبيانات capnproto ، والآخر يأخذ البيانات بالفعل.

إلغاء التسلسل إلى الذاكرة المدارة

إلغاء التسلسل إلى الذاكرة المدارة سيستخدم نفس نوع مشغل التحويل مثل الاتجاه المعاكس.

توليد كود الغراء

عند ربط وحدتي wasm معًا (سواء بشكل ثابت أو ديناميكي) ، يجب على أداة التضمين سرد جميع أنواع capnproto الشائعة لكل من الوحدات النمطية ، والارتباطات بين أنواع الوظائف وأنواع capnproto ، وإنشاء رمز لاصق بين كل زوج مختلف من أنواع الوظائف.

يعتمد رمز اللصق على أنواع البيانات المرتبطة. قد يتلخص كود الغراء بين روابط الذاكرة الخطية في مكالمات memcpy. قد يتلخص رمز الغراء بين روابط الذاكرة المدارة في المراجع العابرة. من ناحية أخرى ، قد يتضمن رمز الغراء بين الذاكرة الخطية والمدارة عمليات تحويل متداخلة أكثر تعقيدًا.

على سبيل المثال ، يمكن لوحدة Java النمطية تصدير وظيفة ، مع أخذ الوسائط كأنواع GC ، وربط هذه الوظيفة بتوقيع مكتوب ؛ يجب أن يسمح المترجم لوحدة Python و C ++ باستيراد هذا النوع من التوقيع ؛ سيمرر ربط C ++ البيانات من الذاكرة الخطية ، في حين أن ربط Python سيمرر البيانات من ذاكرة GC. ستكون التحويلات الضرورية

حلول بديلة

في هذا القسم ، سأفحص طرقًا بديلة لتبادل البيانات ، وكيف يتم تقييمها على المقاييس المحددة في قسم المتطلبات .

تبادل رسائل JSON

إنه حل القوة الغاشمة. لن أقضي الكثير من الوقت في ذلك ، لأن عيوبه واضحة إلى حد ما. فشل في تلبية المتطلبات 2 و 4 و 6.

إرسال البايت الخام المشفرة بتنسيق تسلسل

إنه حل جزئي. حدد طريقة لوحدات wasm لتمرير شرائح من الذاكرة الخطية والجداول إلى وحدات أخرى ، ويمكن لكتاب الوحدة بعد ذلك استخدام تنسيق تسلسل (capnproto أو protobuff أو غيره) لتشفير رسم بياني منظم في سلسلة من البايتات ، وتمرير البايت ، واستخدم نفس التنسيق لفك تشفيره.

يمر 1 و 3 ، ويمكن أن يمر 2 و 4 مع بعض التغيير والتبديل (على سبيل المثال ، تمرير المراجع كمؤشرات إلى جدول). يمكن أن يمر 6 إذا تأكد المستخدم من تصدير نوع التسلسل إلى تعريف نوع في لغة المتصل.

ومع ذلك ، فإنه يفشل في المتطلبات 5 و 7. وهو غير عملي عند الربط بين تطبيقين من GC ؛ على سبيل المثال ، ستحتاج وحدة Python التي تستدعي مكتبة Java باستخدام Protobuf إلى إجراء تسلسل لقاموس كذاكرة خطية ، وتمرير شريحة الذاكرة هذه ، ثم إلغاء تسلسلها ككائن Java ، بدلاً من إجراء بعض عمليات البحث القابلة للتجزئة التي يمكن تحسينها بعيدًا في أ تنفيذ JIT.

ويشجع كل كاتب مكتبة على استخدام تنسيق التسلسل الخاص به (JSON ، و Protobuf ، و FlatBuffer ، و Cap'n Proto ، و SBE) ، وهو ليس مثاليًا للتشغيل البيني ؛ على الرغم من أنه يمكن التخفيف من ذلك من خلال تحديد تنسيق تسلسل أساسي في اصطلاحات الأدوات .

ومع ذلك ، فإن إضافة إمكانية تمرير شرائح عشوائية من الذاكرة الخطية ستكون خطوة أولى جيدة.

إرسال كائنات GC

سيكون من الممكن الاعتماد على الوحدات النمطية التي ترسل كائنات GC الأخرى.

الحل له بعض المزايا: اقتراح GC قيد التنفيذ بالفعل ؛ يمر 1 و 3 و 4 و 7. البيانات المجمعة من GC باهظة التكلفة عند تخصيصها ، ولكنها رخيصة الثمن.

ومع ذلك ، فإن هذا الحل ليس مثاليًا للغات تشبه لغة سي. على سبيل المثال ، ستحتاج وحدة D التي تمرر البيانات إلى وحدة Rust إلى تسلسل بياناتها في رسم بياني GC ، وتمرير الرسم البياني إلى وظيفة Rust ، والتي من شأنها إلغاء تسلسلها في ذاكرتها الخطية. تخصص هذه العملية عقد GC التي يتم تجاهلها على الفور ، لكثير من النفقات العامة غير الضرورية.

وبغض النظر عن ذلك ، لا يحتوي اقتراح مجلس التعاون الخليجي الحالي على دعم داخلي للتعداد والنقابات ؛ وستكون معالجة الأخطاء إما في وقت الارتباط أو وقت التشغيل بدلاً من وقت الترجمة ، ما لم يتمكن المترجم من قراءة وفهم أنواع wasm GC.

استخدم ترميزات أخرى

أي مكتبة تسلسل تحدد نظام الكتابة يمكن أن تعمل مع wasm.

يبدو Capnproto هو الأنسب ، بسبب تركيزه على النسخة الصفرية ، وقدراته المضمنة في الكائنات التي تحدد بدقة أنواع المراجع.

العمل المتبقي

يجب توضيح المفاهيم التالية لتحويل هذا الاقتراح الأساسي إلى مستند يمكن تقديمه إلى مجموعة المجتمع.

  • عوامل الربط
  • معادلات نوع GC
  • قدرات الكائن
  • صفائف منطقية
  • المصفوفات
  • الثوابت
  • علم الوراثة
  • اكتب التطور
  • أضف نوع ربط ثالث من "الحاصلون والضوابط".
  • استراتيجيات التخزين المؤقت الممكنة
  • دعم للجداول المتعددة والذكريات الخطية

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

التعليق الأكثر فائدة

يمكننا إضافة عدد قليل من الارتباطات لكل نوع IR لتغطية الغالبية العظمى من اللغات.

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

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

حالة هاسكل أكثر تعقيدًا بكثير مما تصفه ، لأن القوائم في هاسكل كسولة ، مما يعني أنه بالنسبة لكل حرف في سلسلة ، قد تحتاج إلى استدعاء ثانك.

تستخدم اللغات الأخرى تمثيلات مضحكة لطول السلسلة ، أو لا تخزنها بشكل صريح ولكن تتطلب حسابها.

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

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

ثم هناك جانب الاستقبال ، حيث يجب أن تكون قادرًا على إنشاء كل هياكل البيانات هذه!

لذا أعتقد أنه من غير الواقعي تمامًا أن نقترب ولو من بعيد من دعم "الغالبية العظمى من اللغات". بدلاً من ذلك ، سنبدأ في منح امتياز لعدد قليل ، بينما ننمي بالفعل حديقة حيوانات كبيرة من الأشياء التعسفية. هذا يبدو قاتلا على مستويات متعددة.

ال 61 كومينتر

هذا مثير للاهتمام حقًا! لقد قرأت سريعًا فقط ، ولدي بعض الأفكار الأولية فقط ، ولكن سؤالي الأول والأهم سيكون السؤال عن سبب عدم كفاية آلية FFI الحالية التي توفرها / تستخدمها معظم اللغات بالفعل لـ WebAssembly. تقريبًا كل لغة أعرفها لديها شكل من أشكال C FFI ، وبالتالي فهي قادرة بالفعل على التشغيل البيني اليوم. العديد من هذه اللغات قادرة على إجراء فحص ثابت للنوع بناءً على تلك الارتباطات أيضًا. علاوة على ذلك ، يوجد بالفعل قدر كبير من الأدوات حول هذه الواجهات (على سبيل المثال ، الصندوق bindgen لـ Rust ، erl_nif لـ Erlang / BEAM ، إلخ). تتناول FFI C بالفعل أهم المتطلبات ، وتتمتع بفائدة رئيسية تتمثل في كونها أثبتت بالفعل واستخدامها في الممارسة على نطاق واسع.

5 - جسر بين تخطيطات الذاكرة

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

يجب أن يكون عمل التحويل عند تمرير البيانات بين وحدتين شفافًا للمطور ، طالما أن الأنواع الدلالية متوافقة.

تبدو الترجمة الشفافة لتخطيط إلى آخر عند تمرير البيانات عبر حاجز FFI حقًا وظيفة لخلفيات المترجم أو أوقات تشغيل اللغة بالنسبة لي ، ومن المحتمل أنها غير مرغوبة على الإطلاق في اللغات الحساسة للأداء مثل C / C ++ / Rust / إلخ. على وجه الخصوص ، بالنسبة للأشياء التي تخطط لنقلها ذهابًا وإيابًا عبر FFI ، يبدو لي أنه من الأفضل دائمًا استخدام ABI مشترك ، بدلاً من القيام بأي نوع من الترجمة ، حيث من المحتمل أن تكون الترجمة باهظة التكلفة. من غير المحتمل أن تكون فائدة اختيار تخطيط بخلاف ABI المشترك للنظام الأساسي تستحق ذلك ، لكنني أعترف بسهولة أنني قد أسيء فهم ما تقصده بالتخطيطات البديلة.

بالإضافة إلى ذلك ، فإن وضع عبء أدوات FFI الصلبة على المجمعين / أوقات التشغيل له فائدة إضافية ، حيث أن أي تحسينات يتم إجراؤها قابلة للتطبيق على منصات أخرى ، والعكس صحيح ، حيث إن التحسينات على FFI لمنصات غير Wasm تفيد Wasm. أعتقد أن الحجة يجب أن تكون مقنعة حقًا للبدء بشكل أساسي من المربع الأول وبناء آلية جديدة للمؤسسات المالية الأجنبية.

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

يوجد Apache Arrow لهذا أيضًا ، ولكنه يركز بشكل أكبر على التطبيقات عالية الأداء.

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

شاغلي الرئيسي (وسبب إهمال إدخال الأسئلة الشائعة) هو النطاق: يبدو أن المشكلة العامة لربط لغات N من المرجح أن تولد الكثير من المناقشات المفتوحة (وربما غير المنتهية) ، خاصة بالنظر إلى أن لا أحد يقوم بذلك بالفعل ( وهي بالطبع مشكلة دجاجة وبيضة). على النقيض من ذلك ، فإن المشكلات التي تعالجها روابط Web IDL ملموسة إلى حد ما ويتم توضيحها بسهولة باستخدام Rust / C ++ اليوم ، مما يسمح لنا بتحفيز الجهد (غير التافه) لتوحيد / تنفيذ وأيضًا وضع النموذج الأولي / التحقق من صحة الحل المقترح.

ولكن آمل أن يسمح لنا Web IDL Bindings بكسر مشكلة الدجاجة والبيضة هذه والبدء في اكتساب بعض الخبرة في الربط بين اللغات التي يمكن أن تحفز الموجة التالية من الامتداد أو شيء جديد وليس خاصًا بـ Web IDL . (لاحظ أنه ، كما هو مقترح حاليًا ، إذا كانت هناك وحدتان من الوحدات النمطية تستخدمان Web IDL Bindings المتوافقة تستدعي بعضهما البعض ، يمكن أن تقوم أداة التحسين بالتحسينات التي ذكرتها هنا ؛ فقط بدون التعبير الكامل لـ Cap'n Proto.)

يجب أن أصرح مقدمًا أنه لم يكن لدي الوقت حتى الآن للتغلب على الاقتراح بشكل كامل.
والسبب في ذلك هو أنني أعتقد أن المهمة مستحيلة. هناك سببان أساسيان لذلك:
أ. اللغات المختلفة لها دلالات مختلفة لا يتم التقاطها بالضرورة في نوع التعليق التوضيحي. مثال على ذلك ، يختلف تقييم Prolog اختلافًا جذريًا عن تقييم C ++: لدرجة أن اللغات غير قابلة للتشغيل البيني بشكل أساسي. (بالنسبة إلى Prolog ، يمكنك استبدال عدد من اللغات الأخرى)

ب. بحكم التعريف ، فإن أي شاشة LCD من أنظمة الكتابة ليست مضمونة لالتقاط جميع أنواع لغة لغة معينة. هذا يترك المنفذ اللغوي مع خيار غير مريح للغاية: دعم لغته الخاصة أو التخلي عن مزايا نظام الكتابة اللغوي. مثال على ذلك: هاسكل لديها "فئات النوع". إن أي تطبيق لـ Haskell يتضمن عدم دعم فئات النوع من شأنه أن يؤدي إلى تثبيطها بشكل فعال وجعلها غير قابلة للاستخدام.
مثال آخر: يتطلب دعم لغة ++ C للأدوية إزالة النوع العام في وقت الترجمة ؛ من ناحية أخرى ، يستخدم ML و Java (ومجموعة من اللغات الأخرى) شكلاً من أشكال التمثيل العالمي - لا يتوافق مع النهج الذي تتبعه C ++.

من ناحية أخرى ، يبدو أن وجود تعبيرين لنوع مستورد / مستورد يثير مشكلات خاصة به: هل يفترض أن يتحقق نظام اللغة من أن التعبيرين متسقان إلى حد ما؟ على من تقع مسؤولية القيام بهذا العمل؟

lukewagner شكرا على الروابط! بالتأكيد سعيد لأنني حصلت على فرصة لقراءة هذا المستند!

يبدو لي أن هناك شيئين ممزوجين معًا في هذه المناقشة بالذات - بعض ما هو مكتوب أدناه حتى أتمكن من التحقق من فهمي مرتين ، لذلك لا تتردد في الإشارة إلى أي شيء ربما أساء فهمه أو فاتني:

  1. روابط المضيف الفعالة

    • بشكل أساسي ، تهدف مشكلة WebIDL إلى حلها ، على الأقل بالنسبة لبيئات المستعرض - وصف الواجهة الذي يرسم من الوحدة النمطية> المضيف والمضيف> الوحدة النمطية ، ويفوض بشكل أساسي عمل الترجمة من واحد إلى الآخر إلى المحرك المضيف. هذه الترجمة ليست مضمونة بالضرورة لتكون مثالية ، أو حتى محسّنة على الإطلاق ، ولكن تحسين المحركات يمكن أن يستفيد منها للقيام بذلك. ومع ذلك ، حتى الترجمة المحسّنة ، لا تزال تتم إلى حد ما ، لكن هذا مقبول لأن البديل لا يزال ترجمة ، فقط أبطأ.

  2. روابط فعالة غير متجانسة من وحدة إلى وحدة.

    • بعبارة أخرى ، بالنظر إلى وحدتين ، واحدة مكتوبة بـ source والأخرى بـ dest ، تشارك الأنواع بينهما ، الاتصال من source-> dest و / أو dest-> source

    • في حالة عدم توفر FFI مشترك ، ونظرًا لشيء مثل WebIDL ، أي الحصول على دعم على 1 ، فسيكون المسار غير الأمثل هو الترجمة من خلال بعض أنواع القاسم المشترك التي توفرها البيئة المضيفة عند الاتصال عبر حواجز اللغة ، على سبيل المثال source type -> common type -> dest type .



      • يمكن لمحرك التحسين نظريًا أن يجعل هذه الترجمة مباشرة من source إلى dest بدون وسيط ، لكنه لا يزال يفرض تكاليف الترجمة.



    • في حالة توفر مؤسسة مالية أجنبية مشتركة ، على سبيل المثال source و dest مشاركة ABI (على سبيل المثال C ABI) ، عندئذٍ يمكن لـ source و dest الاتصال ببعضهم البعض مباشرةً باستخدام لا توجد نفقات عامة على الإطلاق ، عبر FFI. ربما يكون هذا هو السيناريو الأكثر احتمالا في الممارسة.

لذا فإن وجهة نظري هي أن هناك بالتأكيد فوائد للاستفادة من WebIDL ، أو شيء من هذا القبيل (أي مجموعة شاملة تدعم مجموعة أوسع من واجهات برمجة التطبيقات / البيئات المضيفة) ، ولكنها في الحقيقة مجرد حل للمشكلة الموضحة في 1 ، والمجموعة الفرعية من 2 التي تتعامل مع الارتباطات بين اللغات حيث لا تتوفر مؤسسة مالية أجنبية. من الواضح أن المجموعة الفرعية من 2 حيث FFI _is_ متاحة ، مفضلة بشكل واضح على البدائل ، لأنها لا تتحمل أي نفقات عامة في حد ذاتها.

هل هناك أسباب وجيهة لاستخدام IDL حتى عندما يكون FFI خيارًا؟ لكي أكون واضحًا ، أنا أتفق بالتأكيد مع استخدام IDL لحالات الاستخدام الأخرى المذكورة ، لكنني أسأل على وجه التحديد في سياق قابلية التشغيل البيني للغة ، وليس روابط المضيف.

لدي سؤالان إضافيان ، إذا تم استخدام / تقديم كل من C FFI (على سبيل المثال ، نظرًا لأنه الأكثر شيوعًا) و IDL في نفس الوقت:

  • إذا قدمت كلتا اللغتين source و dest تعريفات أنواع مختلفة لنوع مشترك مع نفس التمثيل في الذاكرة الأساسي وفقًا لـ ABI المشترك (على سبيل المثال ، تمثيل شائع لمصفوفة متغيرة الطول ) - هل سيحاول المحرك المضيف إجراء ترجمة بين هذه الأنواع لمجرد وجود توجيهات IDL ، على الرغم من أنه يمكنهم الاتصال ببعضهم البعض بأمان باستخدام FFI القياسي الخاص بهم؟

    • إذا لم يكن الأمر كذلك ، وكان الاشتراك ، يبدو أن هذا هو السيناريو المثالي ، حيث يمكنك إضافة IDL لدعم التوافق مع اللغات بدون FFI ، مع دعم اللغات باستخدام FFI في نفس الوقت. لست متأكدًا من كيفية عمل محرك مضيف على ذلك. لم أفكر في الأمر تمامًا ، لذلك ربما أفتقد شيئًا ما

    • إذا كان الأمر كذلك ، كيف يقوم محرك المضيف بتوحيد الأنواع ؟:



      • إذا كان المحرك يهتم فقط بالتخطيط ، فكيف يمكن للتحليل الثابت أن يكتشف عندما يقدم المتصل أنواع وسيطة غير صحيحة إلى المستدعي؟ إذا لم يكن هذا النوع من التحليل هدفًا ، فسيبدو أن IDL مناسب حقًا بشكل مثالي فقط لربط المضيف ، وأقل من ذلك عبر اللغات.


      • إذا كان المحرك يهتم بأكثر من التصميم ، بمعنى آخر ، يتطلب نظام الكتابة توافقًا اسميًا وتركيبيًا:





        • من الذي يحدد النوع المعتمد لبعض الوظائف؟ كيف يمكنني حتى الإشارة إلى النوع الموثوق من بعض اللغات؟ على سبيل المثال ، لنفترض أنني اتصل بمكتبة مشتركة مكتوبة بلغة أخرى تحدد دالة add/2 ، و add/2 تتوقع وسيطتين من نوع ما size_t . لا تعرف لغتي بالضرورة عن size_t اسميًا ، فلديها تمثيلها الخاص المتوافق مع ABI للأعداد الصحيحة غير الموقعة لعرض الآلة ، usize ، لذا فإن ارتباطات FFI لهذه الوظيفة في لغتي تستخدم أنواع اللغات. بالنظر إلى ذلك ، كيف يمكن للمجمع الخاص بي معرفة إنشاء IDL الذي يقوم بتعيين usize إلى size_t .






  • هل توجد أمثلة لواجهات IDL المستخدمة للاتصال بين الوحدات النمطية في برنامج ، حيث يتوفر FFI ولكن تم تركه صراحةً غير مستخدم لصالح الواجهة الموصوفة لـ IDL؟ على وجه التحديد شيء ليس WebAssembly ، يهتم في الغالب بدراسة الفوائد في تلك الحالات.

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

تضمين التغريدة

هذا مثير للاهتمام حقًا!

سعيد لأنك أحببته!

ولكن سؤالي الأول والأهم سيكون أن أسأل لماذا آلية FFI الحالية التي توفرها / تستخدمها معظم اللغات بالفعل ليست كافية لـ WebAssembly.

يحتوي نظام النوع C على بعض المشكلات مثل IDL بين اللغات:

  • تعمل في ظل افتراض مساحة عنوان مشتركة ، وهي مساحة غير آمنة ولا يتم الاحتفاظ بها بشكل متعمد في WebAssembly. (تشير تجربتي الخاصة مع مؤسسة مالية أجنبية من JS-to-C إلى أن عمليات التنفيذ تميل فقط إلى مقايضة السلامة مقابل السرعة)

  • لا يحتوي على دعم أصلي لمصفوفات الطول الديناميكي ، والنقابات ذات العلامات ، والقيم الافتراضية ، والأدوية ، وما إلى ذلك.

  • لا يوجد مكافئ مباشر لأنواع المراجع.

يحل C ++ بعض هذه المشكلات (ليست المشكلة الأكبر ، مساحة العنوان المشتركة) ، ولكنه يضيف مجموعة من المفاهيم التي ليست مفيدة حقًا في IPC. بالطبع ، يمكنك دائمًا استخدام مجموعة شاملة من C أو مجموعة فرعية من C ++ مثل IDL الخاص بك ثم وضع قواعد ملزمة حولها ، ولكن في هذه المرحلة لن تحصل على أي فوائد تقريبًا من الكود الحالي ، لذلك يمكنك أيضًا استخدام أحد الرموز الموجودة IDL.

على وجه الخصوص ، للأشياء التي تخطط لتمريرها ذهابًا وإيابًا عبر مؤسسة مالية أجنبية

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

من غير المحتمل أن تكون فائدة اختيار تخطيط بخلاف ABI المشترك للنظام الأساسي تستحق ذلك ، لكنني أعترف بسهولة أنني قد أسيء فهم ما تقصده بالتخطيطات البديلة.

الشيء ، في الوقت الحالي ، ABI المشترك هو شريحة من البايت مخزنة في الذاكرة الخطية. ولكن في المستقبل ، عندما يتم تنفيذ اقتراح GC ، فإن بعض اللغات (Java ، C # ، Python) سوف تخزن القليل جدًا أو لا شيء في الذاكرة الخطية. بدلاً من ذلك ، سيقومون بتخزين جميع بياناتهم في هياكل GC. إذا حاولت اثنتان من هذه اللغات الاتصال ، فإن تسلسل هذه الهياكل إلى دفق من البايتات فقط لإلغاء تسلسلها على الفور لن يكون ضروريًا.


KronicDeth شكرًا ،

على الرغم من أنه من خلال مسح المستند ، يبدو أن هذا هو مجموعة شاملة من Flatbuffers ، تهدف تحديدًا إلى تحسين الأداء؟ في كلتا الحالتين ، ما هي صفاته التي يمكن أن تساعد بشكل فريد في إمكانية التشغيل التفاعلي لوحدة WebAssembly ، مقارنةً بـ Flatbuffers أو Capnproto؟


تضمين التغريدة

ولكن آمل أن يسمح لنا Web IDL Bindings بكسر مشكلة الدجاجة والبيضة هذه والبدء في اكتساب بعض الخبرة في الربط بين اللغات التي يمكن أن تحفز الموجة التالية من الامتداد أو شيء جديد وليس خاصًا بـ Web IDL.

متفق. كان افتراضي عند كتابة هذا الاقتراح هو أن أي تنفيذ لربط capnproto سيعتمد على التعليقات من تنفيذ اقتراح WebIDL.

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

أعتقد أن مناقشة تطبيق capnproto لها قيمة ، رغم ذلك ، حتى في وقت مبكر.

على وجه الخصوص ، حاولت تحديد المتطلبات التي يجب / يمكن أن يحاول التنفيذ الوفاء بها. أعتقد أنه سيكون من المفيد أيضًا سرد حالات الاستخدام الشائعة التي قد يحاول نظام الكتابة متعدد اللغات معالجتها.

فيما يتعلق بمشكلة N-to-N ، أركز على هذه الحلول:

  • تقلق فقط بشأن نقل البيانات على غرار RPC. لا تحاول تمرير البيانات أو الفئات أو فترات عمر المؤشر المشتركة أو أي نوع آخر من المعلومات الأكثر تعقيدًا من "المتجه له ثلاثة حقول: 'x' و 'y' و 'z' ، وكلها عوامات".

  • حاول تجميع اللغات واستخدام الحالات في "مجموعات" من استراتيجيات معالجة البيانات. وضع استراتيجيات في مركز هذه المجموعات ؛ يرتبط المترجمون اللغويون بإستراتيجية معينة ، ويقوم المترجم الفوري بباقي عمل NxN.


تضمين التغريدة

والسبب في ذلك هو أنني أعتقد أن المهمة مستحيلة. هناك سببان أساسيان لذلك:
أ. اللغات المختلفة لها دلالات مختلفة لا يتم التقاطها بالضرورة في نوع التعليق التوضيحي. مثال على ذلك ، يختلف تقييم Prolog اختلافًا جذريًا عن تقييم C ++: لدرجة أن اللغات غير قابلة للتشغيل البيني بشكل أساسي. (بالنسبة إلى Prolog ، يمكنك استبدال عدد من اللغات الأخرى)

إن أي تطبيق لـ Haskell يتضمن عدم دعم فئات النوع من شأنه أن يؤدي إلى تثبيطها بشكل فعال وجعلها غير قابلة للاستخدام.

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

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

أعتقد أنه من الممكن الاستفادة من أوجه التشابه هذه لتقليل الاحتكاك بين الوحدات بشكل كبير. (انظر أيضًا إجابتي على lukewagner)

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

نعم. أعتقد أن القاعدة الأساسية هنا هي "إذا كانت حدود مكتبة مشتركة ، اجعلها من نوع capnproto ، وإلا فاستخدم الأنواع الأصلية الخاصة بك".

من ناحية أخرى ، يبدو أن وجود تعبيرين لنوع مستورد / مستورد يثير مشكلات خاصة به: هل يفترض أن يتحقق نظام اللغة من أن التعبيرين متسقان إلى حد ما؟ على من تقع مسؤولية القيام بهذا العمل؟

نعم ، أردت في البداية تضمين قسم حول التحقق الثابت ، وقسم آخر حول توافق النوع ، لكنني فقدت الشجاعة.

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

نظام النوع C لديه بعض المشاكل مثل IDL بين اللغات

فقط لأكون واضحًا ، أنا لا أقترحه باعتباره IDL. بدلاً من ذلك ، أقترح أن الواجهة الثنائية (C ABI) موجودة بالفعل ، ومحددة جيدًا ، ولديها دعم لغوي واسع النطاق بالفعل. المعنى الضمني إذن هو أن WebAssembly لا يحتاج إلى توفير حل آخر ما لم تتجاوز المشكلة التي يتم حلها التشغيل المتداخل عبر اللغات.

تعمل في ظل افتراض مساحة عنوان مشتركة ، وهي مساحة غير آمنة ولا يتم الاحتفاظ بها بشكل متعمد في WebAssembly.

لذلك أعتقد أنني أرى جزءًا من سوء الفهم هنا. هناك فئتان من FFI نتحدث عنهما هنا ، أحدهما يتضمن مشاركة الذاكرة الخطية (الذاكرة المشتركة التقليدية FFI) ، والآخر لا (IPC / RPC التقليدي). لقد كنت أتحدث عن الأول ، وأعتقد أنك تركز أكثر على الأخير.

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

يبدو التشغيل المتداخل متعدد الوحدات الذي لا يستخدم الذاكرة المشتركة FFI ، أي IPC / RPC ، بالتأكيد مطابقًا جيدًا لـ WebIDL أو capnproto أو أحد الاقتراحات الأخرى في هذا السياق ، نظرًا لأن هذا هو الخبز والزبدة.

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

لا يحتوي على دعم أصلي لمصفوفات الطول الديناميكي ، والنقابات ذات العلامات ، والقيم الافتراضية ، والأدوية ، وما إلى ذلك.

أعتقد أن هذا ربما لا يكون ذا صلة الآن بعد أن أدركت أننا كنا نتحدث عن شيئين مختلفين ، ولكن للأجيال القادمة فقط: من المؤكد أن ABI لديها _تقديم_ لمصفوفات متغيرة الطول والنقابات ذات العلامات ، لكنك على حق في أن C لديها نظام الكتابة الضعيفة ، ولكن هذا ليس هو الهدف حقًا ، فاللغات لا تستهدف C FFI لنظام النوع C. السبب وراء فائدة C ABI هو أنه يوفر قاسمًا مشتركًا يمكن للغات استخدامه للتواصل مع الآخرين الذين قد لا يكون لديهم مفهوم لنظام الكتابة الذي يتفاعلون معه. إن الافتقار إلى ميزات النظام من النوع الأعلى ليس مثاليًا ، ويحد من نوع الأشياء التي يمكنك التعبير عنها عبر FFI ، ولكن القيود هي أيضًا جزء من سبب نجاحها في ما تفعله ، إلى حد كبير يمكن لأي لغة أن تجد طريقة لتمثيل الأشياء التي تتعرض لها عبر تلك الواجهة ، والعكس صحيح.

يحل C ++ بعض هذه المشكلات (ليست المشكلة الأكبر ، مساحة العنوان المشتركة) ، ولكنه يضيف مجموعة من المفاهيم التي ليست مفيدة حقًا في IPC. بالطبع ، يمكنك دائمًا استخدام مجموعة شاملة من C أو مجموعة فرعية من C ++ مثل IDL الخاص بك ثم وضع قواعد ملزمة حولها ، ولكن في هذه المرحلة لن تحصل على أي فوائد تقريبًا من الكود الحالي ، لذلك يمكنك أيضًا استخدام أحد الرموز الموجودة IDL.

متفق عليه ، بالنسبة لـ IPC / RPC ، تعد C لغة رهيبة لتعريف الواجهات.

الشيء ، في الوقت الحالي ، ABI المشترك هو شريحة من البايت مخزنة في الذاكرة الخطية.

هذا بالتأكيد هو الأساس الذي نعمل معه ، لكن C ABI تحدد الكثير علاوة على ذلك.

ولكن في المستقبل ، عندما يتم تنفيذ اقتراح GC ، فإن بعض اللغات (Java ، C # ، Python) سوف تخزن القليل جدًا أو لا شيء في الذاكرة الخطية. بدلاً من ذلك ، سيقومون بتخزين جميع بياناتهم في هياكل GC. إذا حاولت اثنتان من هذه اللغات الاتصال ، فإن تسلسل هذه الهياكل إلى دفق من البايتات فقط لإلغاء تسلسلها على الفور لن يكون ضروريًا.

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

TL ؛ DR: أعتقد أننا نتفق فيما يتعلق بوحدة التشغيل المتداخل حيث لا يتم تشغيل الذاكرة الخطية المشتركة. لكنني أعتقد أن الذاكرة المشتركة _من المهم دعمها ، و C ABI هو الخيار الأفضل لحالة الاستخدام هذه بسبب دعم اللغة الحالي. آمل أن يدعم هذا الاقتراح مع تطوره كليهما.

ما نحتاجه هو ببساطة طريقة فعالة إلى أقصى حد لتبادل المخازن المؤقتة للبايت ، وطريقة للغات للاتفاق على التنسيق. ليست هناك حاجة لإصلاح هذا في نظام تسلسل معين. إذا كان Cap'n Proto هو الأنسب لهذا الغرض ، فيمكن أن ينشأ بشكل افتراضي عام ، بدلاً من أن يكون مفوضًا من قبل wasm.

أنا بالطبع متحيز ، لأنني صنعت FlatBuffers ، والتي تشبه Cap'n Proto من حيث الكفاءة ، ولكنها أكثر مرونة وأكثر دعمًا. ومع ذلك ، فإنني لا أوصي بهذا الشكل ليتم تفويضه من قبل شركة wasm أيضًا.

هناك العديد من التنسيقات الأخرى التي يمكن أن تكون أفضل من هاتين الحالتين نظرًا لحالات استخدام معينة.

لاحظ أن كلا من Cap'n Proto و FlatBuffers هما عبارة عن نسخة معدومة ، والوصول العشوائي ، وكفاءة في التنسيقات المتداخلة (مما يعني أن التنسيق المغلف في تنسيق آخر ليس أقل كفاءة من عدم التفافه) ، وهي الخصائص الحقيقية التي يجب مراعاتها بين اللغات الاتصالات. يمكنك تخيل IDL الذي يسمح لك بتحديد تخطيطات بايت دقيقة جدًا لمخزن مؤقت ، بما في ذلك "وحدات البايت التالية هي Cap'n Proto schema X".

بينما أقوم بالترويج الذاتي بمهارة ، قد أوجه الأشخاص إلى

تضمين التغريدة

ما نحتاجه هو ببساطة طريقة فعالة إلى أقصى حد لتبادل المخازن المؤقتة للبايت ، وطريقة للغات للاتفاق على التنسيق. ليست هناك حاجة لإصلاح هذا في نظام تسلسل معين. إذا كان Cap'n Proto هو الأنسب لهذا الغرض ، فيمكن أن ينشأ بشكل افتراضي عام ، بدلاً من أن يكون مفوضًا من قبل wasm.

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

بعد قولي هذا ، عندما يتم قول وفعل كل شيء ، يحتاج المطاط إلى تلبية الطريق في مرحلة ما. إذا أراد wasm تسهيل الاتصال بين اللغات (وهو ، من المسلم به ، ليس افتراضًا يشاركه الجميع) ، فإنه يحتاج إلى تنسيق قياسي يمكنه التعبير عن أكثر من "هذه البايتات تشكل الأرقام". يمكن أن يكون هذا التنسيق عبارة عن capnproto أو C أو flatbuffers أو حتى شيئًا خاصًا بـ wasm ، لكن لا يمكن أن يكون مجموعة فرعية من كل هذه العناصر في نفس الوقت ، للأسباب الموضحة fgmccabe .

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

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

assert(myObj.foo);
assert(isJsonObject(myObj.foo));
assert(myObj.foo.bar);
assert(isString(myObj.foo.bar));
loadUrl(myObj.foo.bar);

مع وجود ثغرات أمنية محتملة إذا لم تفعل ذلك.

راجع أيضًا 6 - معالجة أخطاء وقت الترجمة أعلاه.


تضمين التغريدة

حسنًا ، لم أفكر حقًا في إمكانية مشاركة الذاكرة الخطية. سأحتاج إلى شخص أكثر دراية بتصميم webassembly مني ( lukewagner ؟) لمناقشة مدى

على سبيل المثال ، غالبًا ما تعتمد المؤسسات المالية الأجنبية على حقيقة أن لغتها المضيفة تستخدم مكتبة C ، وتمنح المكتبات المحلية إمكانية الوصول إلى وظيفة malloc مباشرةً. إلى أي مدى يمكن ترجمة هذه الاستراتيجية إلى نظام ، في سياق وحدتين مشبوهتين بشكل متبادل؟

أعتقد أنني يجب أن أقول شيئًا ما في هذا الموضوع ، بصفتي مبتكر Cap'n Proto ، لكن الغريب بما فيه الكفاية ، لم أجد أن لدي الكثير من الرأي. اسمحوا لي أن أعبر عن بعض الأفكار المتجاورة التي قد تكون مثيرة للاهتمام وقد لا تكون كذلك.

أنا أيضًا الرائد التقني في Cloudflare Workers ، وهي بيئة "بدون خادم" تقوم بتشغيل JavaScript و WASM.

لقد فكرنا في دعم Cap'n Proto RPC كبروتوكول للعمال للتحدث مع بعضهم البعض. في الوقت الحالي ، يقتصر استخدامهما على HTTP ، لذلك تم تعيين الشريط على مستوى منخفض جدًا. :)

في حالة العمال ، عندما يتصل عامل بآخر ، فمن الشائع جدًا أن كلاهما يعمل على نفس الجهاز ، حتى في نفس العملية. لهذا السبب ، من الواضح أن تسلسل نسخة صفرية مثل Cap'n Proto له معنى كبير ، خاصة بالنسبة لعمال WASM نظرًا لأنهم يعملون على ذاكرة خطية يمكن ، من الناحية النظرية ، مشاركتها فعليًا بينهم.

السبب الثاني الأقل شهرة في اعتقادنا أن هذا مناسب بشكل جيد هو نظام RPC. يتميز Cap'n Proto ببروتوكول RPC ذي القدرة الكاملة على الكائن مع خطوط الأنابيب الواعدة ، على غرار CapTP. هذا يجعل من السهل التعبير عن تفاعلات غنية وموجهة نحو الكائنات بطريقة آمنة وفعالة. Cap'n Proto RPC ليس مجرد بروتوكول من نقطة إلى نقطة ، بل هو نموذج للتفاعلات بين أي عدد من الأطراف المتصلة بالشبكة ، والتي نعتقد أنها ستكون صفقة كبيرة جدًا.

وفي الوقت نفسه في أرض WASM ، تقدم WASI واجهة برمجة تطبيقات تعتمد على القدرات. يبدو أنه قد يكون هناك بعض "التآزر" المثير للاهتمام هنا.

مع كل ما قيل ، قد لا تكون العديد من أهداف التصميم لـ Cap'n Proto منطقية لحالة الاستخدام المحددة لـ FFI:

  • تم تصميم رسائل Cap'n Proto لتكون مستقلة عن الموضع ومتجاورة بحيث يمكن إرسالها ومشاركتها بين مساحات العنوان. المؤشرات نسبية ، ويجب تخصيص جميع الكائنات في الرسالة في ذاكرة متجاورة ، أو على الأقل عدد صغير من المقاطع. هذا يعقد بشكل كبير نموذج الاستخدام مقارنة بالكائنات الأصلية. عند استخدام FFI في نفس مساحة الذاكرة الخطية ، يتم إهدار هذا الحمل الزائد ، حيث يمكنك تمرير مؤشرات أصلية لفقدان كومة الكائنات بشكل جيد.
  • تم تصميم رسائل Cap'n Proto لتكون متوافقة مع الإصدارات السابقة والعكسية بين إصدارات المخطط ، بما في ذلك القدرة على نسخ الكائنات والأشجار الفرعية دون فقدان البيانات دون معرفة المخطط. يتطلب هذا تخزين بعض معلومات نوع الضوء مباشرة في المحتوى ، والتي يقوم Cap'n Proto بترميزها كبيانات وصفية على كل مؤشر. إذا تم تجميع وحدتين تتواصلان عبر FFI في نفس الوقت ، فلن تكون هناك حاجة إلى هذه البيانات الوصفية.
  • تعد ضمانات Cap'n Proto RPC لتوصيل الأنابيب ، وتقصير المسار ، وضمانات الطلب منطقية عندما يكون هناك زمن انتقال غير مهم بين المتصل والمستدعي. FFI على وحدة معالجة مركزية واحدة ليس له مثل هذا الكمون ، وفي هذه الحالة من المحتمل أن تكون آلات خطوط الأنابيب الواعدة مجرد إهدار للدورات.

باختصار ، أعتقد أنه عندما يكون لديك وحدات منتشرة بشكل مستقل في صناديق رمل منفصلة تتحدث مع بعضها البعض ، فإن Cap'n Proto تكون منطقية للغاية. ولكن بالنسبة للوحدات النمطية التي يتم نشرها في وقت واحد في صندوق رمل واحد ، فمن المحتمل أن يكون الأمر مبالغة.

شكرا على ملاحظاتك!

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

لا أعرف مدى جدوى نهج الذاكرة الخطية المشتركة بالنسبة إلى wasm (انظر أعلاه).

ومع ذلك ، في كلتا الحالتين ، لا أعتقد أن النفقات العامة من المؤشرات النسبية ستكون بهذا السوء. يستخدم WebAssembly بالفعل الإزاحات المتعلقة ببداية الذاكرة الخطية ، والتطبيقات لديها حيل لتحسين التعليمات ADD بعيدًا في معظم الحالات (على ما أظن) ، لذلك من المحتمل أن يتم تحسين النفقات العامة لاستخدام المؤشرات النسبية بعيدًا أيضًا.

تم تصميم رسائل Cap'n Proto لتكون متوافقة مع الإصدارات السابقة والعكسية بين إصدارات المخطط ، بما في ذلك القدرة على نسخ الكائنات والأشجار الفرعية دون فقدان البيانات دون معرفة المخطط. [...] إذا تم تجميع وحدتين تتواصلان عبر مؤسسة مالية أجنبية في نفس الوقت ، فلا داعي لوجود هذه البيانات الوصفية.

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

قد يكون المصدر الأكبر للنفقات الزائدة غير المجدية هو طريقة capnproto xor s متغيراته مقابل قيمها الافتراضية ، وهو أمر مفيد عندما يتم ضغط صفر بايت بعيدًا ، ولكن يؤدي إلى نتائج عكسية في مهام سير العمل ذات النسخ الصفرية.

لا أعرف مدى جدوى نهج الذاكرة الخطية المشتركة بالنسبة إلى wasm (انظر أعلاه).

آه ، TBH لا أعتقد أن لدي سياق كاف لمتابعة هذا الجزء من المناقشة. إذا لم يكن لديك مساحة عنوان مشتركة ، فحينئذٍ ، نعم ، يبدأ Cap'n Proto بإضفاء المزيد من المعنى.

يسعدني تقديم المشورة حول كيفية تصميم تنسيقات كهذه. FWIW هناك بعض الأشياء الصغيرة التي كنت سأغيرها في Cap'n Proto إذا لم أكن أهتم بالتوافق مع التطبيقات الموجودة بالفعل اليوم ... إنها في الغالب ، مثل تفاصيل ترميز المؤشر ذات المستوى المنخفض ، على الرغم من ذلك.

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

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

lukewagner هل من أفكار حول جزء "مشاركة الذاكرة الخطية"؟

أعتقد أن هناك حالات استخدام لكل من مشاركة الذاكرة الخطية وعدم مشاركتها ، وفي النهاية تحتاج الأدوات إلى دعم كلاً من:

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

يعد عدم مشاركة الذاكرة أمرًا منطقيًا بالنسبة لمجموعة من الوحدات النمطية غير المترابطة بشكل أكبر ، حيث يضع التصميم الكلاسيكي على غرار Unix الكود في عمليات منفصلة متصلة بواسطة الأنابيب. أنا شخصياً أعتقد أن هذا هو الاتجاه الأكثر إثارة / مستقبليًا لنظام بيئي أكثر تكوينًا للبرامج ، ولذا فقد دعت إلى أن يكون هذا هو الخيار الافتراضي لأي سلسلة أدوات تهدف إلى المشاركة في النظام البيئي ESM / npm عبر تكامل ESM (وبالفعل ذلك هذا هو الحال اليوم مع Rust's wasm-pack / wasm-bindgen). إن استخدام آلية في المنطقة المجاورة العامة لـ Web IDL Bindings أو الامتداد الذي اقترحته أمر منطقي للغاية بالنسبة لي كشكل من أشكال RPC الفعالة والمريحة والمكتوبة (المزامنة أو غير المتزامنة).

بعد أن قرأت هذا بالكامل أخيرًا ، يبدو كثيرًا مثل تفكيري في هذا المجال (أي مربع التعليق هذا قصير جدًا بحيث لا يمكن احتوائه؟).

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

من منظور WASI / ESM + npm ، فإن حل هذا النموذج هو الأكثر منطقية بالنسبة لي. إنه تجريد فوق ABIs ، دون الاعتماد على ABI مشترك. يسمح بشكل أساسي للمرء أن يصف واجهة بواجهة برمجة تطبيقات مخطط لانغ ، والاتصال عبر حدود اللغة هذه مع ABI تبدو أصلية على كلا الطرفين ، مما يسمح للمضيف بمعالجة الترجمة.

على وجه الخصوص ، هذا لا يشمل حالة الاستخدام للحصول على مزيد من التنسيق مع وحدة أخرى: إذا كنت تعرف بالتأكيد أنه يمكنك مشاركة ABI ، فيمكنك في الواقع استخدام ABI ، أي ABI ، سواء كان ذلك C أو Haskell. إذا كنت تتحكم في كل الكلمات المنطوقة وتجمعها ، فهذه مشكلة أسهل بكثير لحلها. فقط عندما تدخل في حالة npm حيث تقوم بتحميل كود تعسفي غير معروف ولا تعرف لغة المصدر الخاصة به ، يصبح شيئًا مثل وجود توافق على مستوى المخطط بين الوحدات أمرًا جذابًا بشكل لا يصدق. لأنه يمكننا إما استخدام شاشة LCD الخاصة بـ wasm نفسها - والتي أتوقع أنها ستتبع قوسًا مشابهًا للمكتبات الأصلية ، واستخدام C ABI - أو يمكننا استخدام شاشة LCD للغات ، المشفرة بلغة المخطط. ويمكن أن يكون المخطط أكثر مرونة من خلال جعل المتطلب 2) مطلبًا ناعمًا ، على سبيل المثال ، يجب أن يكون من الممكن التحويل من C إلى Rust إلى Nim بكفاءة ، لكن وجود C إلى Haskell لا يمثل زيادة في النفقات العامة بمثابة كسر للصفقات.

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

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

يجب أن يكون من الممكن التحويل من C إلى Rust إلى Nim بكفاءة ، و C إلى Haskell مع وجود المزيد من النفقات العامة ليس بمثابة كسر للصفقة.

ربما لا ، لكن يجب أن تكون على دراية بالآثار المترتبة على ذلك. إن امتياز اللغات الشبيهة بلغة C يعني أن هاسكل لن تستخدم هذا التجريد لوحدات هاسكل ، بسبب النفقات الزائدة التي يسببها. وهذا بدوره يعني أنه لن يشارك في نفس النظام البيئي "npm" لمكتباته الخاصة.

و "Haskell" هنا هو مجرد بديل لكل لغة عالية المستوى تقريبًا. الغالبية العظمى من اللغات ليست مثل لغة سي.

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

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

و "Haskell" هنا هو مجرد بديل لكل لغة عالية المستوى تقريبًا. الغالبية العظمى من اللغات ليست مثل لغة سي.

يمكن أن تعطي بعض حالات الاستخدام المحددة؟ من الناحية المثالية ، المكتبات الموجودة في هاسكل أو بعض اللغات الأخرى التي سيكون من الصعب ترجمتها إلى مخطط تسلسل؟

أظن أن الأمر سينزل في الغالب إلى مكتبات المرافق مقابل مكتبات الأعمال. على سبيل المثال ، الحاويات وخوارزميات الفرز والأدوات المساعدة الأخرى التي تعتمد على الأدوية العامة للغة لن تُترجم جيدًا إلى wasm ، ولكن المحللون ، وأدوات واجهة المستخدم الرسومية ، وأدوات نظام الملفات سوف يفعلون ذلك.

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

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

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

يقوم المضيف بتنفيذ المخطط. لا يصف المخطط البايت على الإطلاق ، ويتيح أن يكون ذلك أحد تفاصيل التنفيذ. هذا استعارة من تصميم اقتراح WebIDL Bindings ، حيث يكون الجزء المثير للاهتمام في التحويلات من هياكل C إلى أنواع WebIDL. يستخدم هذا النوع من التصميم أنواع واجهة Wasm Abstract (أقترح الاختصار: WAIT) بدلاً من أنواع WebIDL. في اقتراح WebIDL ، لسنا بحاجة أو نريد تفويض تمثيل ثنائي للبيانات عندما يتم "ترجمتها إلى WebIDL" ، لأننا نريد أن نكون قادرين على الانتقال مباشرة من واجهات برمجة التطبيقات (APIs) إلى المتصفح دون توقف بينهما.

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

أوه ، موافق 100٪. كان يجب أن أنهي المثال لتوضيح ذلك بشكل أكبر: في غضون ذلك ، يمكن أن تكون Haskell إلى Elm إلى C # فعالة بالمثل (على افتراض أنها تستخدم أنواع wasm gc) ، ولكن C # to Rust قد يكون لها عبء. لا أعتقد أن هناك طريقة لتجنب النفقات الزائدة عند القفز عبر نماذج اللغة.

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

أعتقد أنه من خلال تجريد الأنواع وعدم تحديد تنسيق سلكي ، يمكننا إعطاء مساحة أكبر بكثير للمضيفين للتحسين. أعتقد أن الهدف غير المقصود هو أن تقول "السلاسل ذات النمط C فعالة" ، ولكن من الهدف أن نقول "اللغات التي [تريد] تفكيرًا حول سلاسل النمط C يمكنها أن تفعل ذلك بكفاءة". أو ، لا ينبغي تبارك تنسيق واحد ، ولكن يجب أن تكون بعض سلاسل المكالمات المتوافقة فعالة ، ويجب أن تكون جميع سلاسل المكالمات ممكنة.

أعني بسلاسل الاتصال:

  1. ج -> الصدأ -> التعرج -> فورتران ، بكفاءة
  2. هاسكل -> C # -> هاسكل ، فعال
  3. ج -> هاسكل -> الصدأ -> المخطط ، غير فعال
  4. جافا -> الصدأ ، غير فعال

و "Haskell" هنا هو مجرد بديل لكل لغة عالية المستوى تقريبًا. الغالبية العظمى من اللغات ليست مثل لغة سي.

نعم ، كان هذا هدفي من استخدام هاسكل كلغة ملموسة. (على الرغم من أن Nim كان على الأرجح مثالًا سيئًا للغة شبيهة بلغة C لأنها تستخدم بشكل كبير GC أيضًا)

-

طريقة أخرى كنت أفكر بها في الأنواع المجردة هي استخدام IR. بالطريقة نفسها التي يصف بها LLVM علاقة أطراف بأطراف (العديد من اللغات -> واحد IR -> العديد من الأهداف) ، يمكن لأنواع ملخصات wasm التوسط في تعيين متعدد إلى متعدد ، للغات + المضيفين -> اللغات + المضيفين. يأخذ شيء ما في مساحة التصميم هذه مشكلة تعيين N ^ 2 ويحولها إلى N + N.

يقوم المضيف بتنفيذ المخطط.

حسنًا ، لا يمكن أن يكون هذا كافيًا ، يجب على كل وحدة تنفيذ شيء ما حتى يتمكن المضيف من العثور على البيانات. إذا كان المضيف يتوقع تخطيط C ، فيجب عليك تحديد تخطيط C هذا ، ويجب على كل عميل تنظيم / إلغاء التنظيم من / إلى ذلك داخليًا. هذا ليس مختلفًا تمامًا عن تنسيق التسلسل.

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

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

لا ينبغي أن يتوقع المضيف أي شيء ، ولكنه يحتاج إلى دعم كل شيء. بشكل أكثر تحديدًا ، باستخدام اقتراح روابط webidl كمثال توضيحي ، لدينا utf8-cstr و utf8-str ، والتي تأخذ i32 (ptr) و i32 (ptr), i32 (len) على التوالي. ليست هناك حاجة إلى التفويض في المواصفات "يمثل المضيف داخليًا هذه السلاسل C" لتتمكن من رسم خريطة ملموسة بينها.
لذلك ، تنفذ كل وحدة نمطية شيئًا ما ، نعم ، لكن تمثيل البيانات لا يحتاج إلى التعبير عنه في طبقة البيانات / المخطط المجردة ، وهذا ما يمنحنا خاصية التجريد فوق تخطيط البيانات هذا.
بالإضافة إلى ذلك ، هذا قابل للتوسيع في طبقة الروابط التي تحدد بين أنواع الخرسانة والأنواع الوسيطة المجردة. لإضافة دعم Haskell (الذي يصمم السلاسل كقوائم سلبية من الأحرف ومصفوفات الأحرف) ، يمكننا إضافة روابط utf8-cons-str و utf8-array-str ، والتي تتوقع (وتحقق من صحة) أنواع الوسم (باستخدام الحالي بناء جملة اقتراح gc) (type $haskellString (struct (field i8) (field (ref $haskellString)))) و (type $haskellText (array i8)) .

أي أن كل وحدة تقرر كيف تنشأ البيانات. تسمح الأنواع المجردة + الارتباطات بالتحويلات بين كيفية عرض الوحدات النمطية لنفس البيانات ، دون مباركة تمثيل واحد على أنه قانوني بطريقة ما.

سيكون تنسيق التسلسل (مجموعة فرعية من) أنواع الملخصات مفيدًا ، ولكن يمكن تنفيذه كمستهلك لتنسيق المخطط ، وأعتقد أنه مصدر قلق متعامد. أعتقد أن FIDL يحتوي على تنسيق تسلسل لمجموعة فرعية من الأنواع التي يمكن نقلها عبر الشبكة ، ولا يسمح بتجسيد المقابض غير الشفافة ، مع السماح للمقابض غير الشفافة بالنقل داخل النظام (IPC نعم ، RPC لا).

ما تصفه قريب جدًا مما كان يدور في ذهني ، مع تحذير كبير واحد: يجب أن يحتوي المخطط على عدد صغير وثابت من التمثيلات الممكنة. يعتبر التجسير بين التمثيلات المختلفة مشكلة N * N ، مما يعني أن عدد التمثيلات يجب أن يظل صغيرًا لتجنب إثقال كتبة VM.

لذا فإن إضافة دعم هاسكل يتطلب استخدام الروابط الحالية ، وليس إضافة روابط مخصصة.

بعض التمثيلات الممكنة:

  • بنيات ومؤشرات على غرار C.
  • بايتات capnproto الفعلية.
  • فئات GC.
  • عمليات الإغلاق بمثابة حاصل وضبط.
  • قواميس بأسلوب بايثون.

الفكرة هي أنه في حين أن كل لغة مختلفة ، وهناك بعض القيم المتطرفة المتطرفة ، يمكنك وضع عدد كبير نسبيًا من اللغات في عدد صغير نسبيًا من الفئات.

لذا فإن إضافة دعم هاسكل يتطلب استخدام الروابط الحالية ، وليس إضافة روابط مخصصة.

يعتمد على مستوى دقة الروابط الحالية التي تفكر فيها. N <-> لغات N التي ترميز كل ربط ممكن هي 2 * N * N ، ولكن N <-> IR هي 2 * N ، وكذلك إذا قلت N <-> [أنماط الربط الشائعة] <-> IR ، حيث الرقم من التنسيقات الشائعة k ، أنت تتحدث 2 * k ، حيث k <N.

على وجه الخصوص ، مع المخطط الذي أصفه ، تحصل على Scheme مجانًا (سيعيد استخدام utf8-cons-str ). إذا طرز Java سلاسل كمصفوفات char أيضًا ، فهذا ربط utf8-array-str . إذا كان Nim يستخدم string_views تحت الغطاء ، utf8-str . إذا كان Zig يتوافق مع C ABI ، فسيكون utf8-cstr . (لا أعرف ABIs لـ Java / Nim / Zig ، لذلك لم أذكرها كأمثلة ملموسة سابقًا)

لذا ، نعم ، لا نريد إضافة ارتباط لكل لغة ممكنة ، ولكن يمكننا إضافة بعض الارتباطات لكل نوع IR لتغطية الغالبية العظمى من اللغات. أعتقد أن مساحة الاختلاف هنا هي ، كم عدد الارتباطات "قليلة" ، ما هي النقطة الحلوة ، وما مدى صرامة المعايير فيما يتعلق بما إذا كنا ندعم ABI للغة؟
ليس لدي إجابات محددة على هذه الأسئلة. أحاول أن أعطي الكثير من الأمثلة الملموسة لتوضيح مساحة التصميم بشكل أفضل.

كما أود أن أؤكد أننا نريد تمامًا تحديد روابط متعددة لكل نوع مجردة ، لتجنب امتياز أي نمط واحد من البيانات. إذا كان الارتباط الوحيد الذي نعرضه للسلاسل النصية هو utf8-cstr ، فيجب على جميع اللغات التي لا تتبع C-ABI التعامل مع هذا عدم التطابق. أنا بخير مع زيادة تعقيد كتابة VM بعض العوامل غير الصغيرة.
إجمالي العمل في النظام البيئي هو O (جهد VM + جهد تنفيذ اللغة) ، وكلا هذين المصطلحين يتوسعان بطريقة ما مع N = عدد اللغات. لنفترض أن M = عدد عمليات التضمين ، و k = عدد الارتباطات ، و = متوسط ​​عدد الارتباطات التي تحتاج لغة معينة إلى تنفيذها ، مع <= k. كحد أدنى ، لدينا تطبيقات M + N منفصلة.
نهج ساذج ، مع كل لغة N تنفذ بشكل مستقل ABI FFI مع كل لغة N أخرى ، هو O (M + N * N). هذا ما لدينا في الأنظمة الأصلية ، وهو إشارة قوية إلى أن أي O (N * N) سيؤدي إلى نتائج لا تختلف عن الأنظمة الأصلية.
النهج الساذج الثاني ، حيث يحتاج كل جهاز افتراضي إلى تنفيذ جميع ارتباطات N * N: O (M * N * N + N) ، والتي من الواضح أنها أسوأ.
ما نحاول اقتراحه هو أن لدينا روابط k التي ترسم خريطة بين لغة مجردة ، والتي تعود إلى جميع اللغات. هذا يعني عمل k لكل VM. لكل لغة ، نحتاج فقط إلى تنفيذ مجموعة فرعية من الارتباطات. إجمالي العمل M * k + N * a ، وهو O (M * k + N * k). لاحظ أنه في حالة أن k = N يكون الجانب VM "فقط" M * N ، لذلك بالنسبة لأي جهاز افتراضي معين ، يكون "فقط" خطيًا في عدد اللغات. من الواضح أننا نريد k << N ، لأنه بخلاف ذلك لا يزال هذا O (N * N) ، ليس أفضل من الحل الأول.
ومع ذلك ، فإن O (M * k + N * k) أكثر قبولا. إذا كانت k هي O (1) ، فهذا يجعل النظام البيئي بأكمله خطيًا في عدد عمليات التنفيذ ، وهو الحد الأدنى لمقدار الجهد المبذول. من المرجح أن يكون k هو O (log (N)) ، والذي ما زلت راضيًا عنه.

وهي طريقة طويلة للقول ، أنا على ما يرام تمامًا مع زيادة تعقيد VM لهذه الميزة من خلال بعض العوامل الثابتة.

يمكننا إضافة عدد قليل من الارتباطات لكل نوع IR لتغطية الغالبية العظمى من اللغات.

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

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

حالة هاسكل أكثر تعقيدًا بكثير مما تصفه ، لأن القوائم في هاسكل كسولة ، مما يعني أنه بالنسبة لكل حرف في سلسلة ، قد تحتاج إلى استدعاء ثانك.

تستخدم اللغات الأخرى تمثيلات مضحكة لطول السلسلة ، أو لا تخزنها بشكل صريح ولكن تتطلب حسابها.

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

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

ثم هناك جانب الاستقبال ، حيث يجب أن تكون قادرًا على إنشاء كل هياكل البيانات هذه!

لذا أعتقد أنه من غير الواقعي تمامًا أن نقترب ولو من بعيد من دعم "الغالبية العظمى من اللغات". بدلاً من ذلك ، سنبدأ في منح امتياز لعدد قليل ، بينما ننمي بالفعل حديقة حيوانات كبيرة من الأشياء التعسفية. هذا يبدو قاتلا على مستويات متعددة.

تجربتي هي أن هناك (على الأقل!) العديد من خيارات التمثيل كما هو الحال في تطبيقات اللغة. ويمكن أن تكون معقدة بشكل تعسفي.

أنا أتفق تماما. أعتقد أن محاولة تصميم الأنواع التي ستغطي بطريقة أو بأخرى التمثيلات الداخلية للبيانات في اللغة هي ببساطة غير قابلة للتتبع ، وستجعل النظام البيئي معقدًا بشكل مفرط.

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

في الواقع ، يمكنك الوصول بعيدًا جدًا باستخدام نوع بيانات واحد فقط: المؤشر + زوج لين. ثم تحتاج فقط إلى "مخطط" يوضح ما هو موجود في تلك البايتات. هل يعد بالتوافق مع UTF-8؟ هل البايت الأخير مضمون دائمًا 0؟ هل أول 4/8 بايت هي حقول الطول / السعة؟ هل كل هذه البايتات هي عوامات endian صغيرة يمكن إرسالها مباشرة إلى WebGL؟ هل هذه البايتات ربما مخطط X لتنسيق تسلسل موجود؟ إلخ؟

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

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

أوافق على أن هذا هو الافتراض الأساسي الأساسي. لا أوافق على أن هذا ليس صحيحًا ، على الرغم من أنني أعتقد أنه بسبب فارق بسيط في الدلالة لا أعتقد أنني أوضحته.

لا يُقصد من الارتباطات تعيين جميع تمثيلات اللغة بشكل مثالي ، فهي تحتاج فقط إلى تعيين جميع اللغات بشكل جيد بما فيه الكفاية .

هذا افتراض أساسي أساسي يجعل ذلك قابلاً للتتبع على الإطلاق ، بغض النظر عن الترميز. aardappel الصورة اقتراح تسير في الاتجاه الآخر وفعلا reifying بايت في المخزن مؤقت بنيت أيضا على افتراض أنه هو ترميز الضياع من دلالات أي برنامج معين، وبعض أكثر من غيرها الضياع ديكودابلي.

حالة هاسكل أكثر تعقيدًا بكثير مما تصفه ، لأن القوائم في هاسكل كسولة ، مما يعني أنه بالنسبة لكل حرف في سلسلة ، قد تحتاج إلى استدعاء ثانك.

لقد نسيت ذلك بالفعل ، لكنني لا أعتقد أنه مهم. الهدف ليس تمثيل Haskell Strings مع الحفاظ على جميع الفروق الدلالية الخاصة بهم عبر حدود الوحدة. الهدف هو تحويل سلسلة Haskell إلى سلسلة IR ، من حيث القيمة. هذا ينطوي بالضرورة على حساب السلسلة بأكملها.

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

طريقة نمذجة ذلك ، بغض النظر عن كيفية تحديد الارتباطات (أو حتى إذا حددنا أي شيء للارتباطات) ، هي التعامل مع ذلك في userland. إذا كان تمثيل اللغة لنوع ما لا يتم تعيينه إلى ارتباط مباشر ، فسيلزم التحويل إلى تمثيل يقوم بذلك. على سبيل المثال ، إذا تم تمثيل سلاسل Haskell بالفعل كـ (type $haskellString (struct (field i8) (field (func (result (ref $haskellString)))))) ، فستحتاج إما إلى التحويل إلى سلسلة صارمة واستخدام ربط يشبه المخطط ، أو إلى مصفوفة نصية واستخدام ربط يشبه Java ، أو إلى CFFIString واستخدام رابط يشبه C. اقتراح القيمة لوجود أنواع ربط متعددة غير كاملة هو أن بعض هذه الأنواع أقل حرجًا بالنسبة إلى Haskell من غيرها ، ومن الممكن إنشاء أنواع Wasm-FFI دون الحاجة إلى تعديل المترجم.

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

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

بدلاً من ذلك ، سنبدأ في امتياز القليل

تقريبا بالتأكيد. السؤال هو ، ما هي درجة امتياز اللغات القليلة المدعومة على النحو الأمثل؟ ما مدى حرية اللغات المحرومة في إيجاد حل مريح؟

بينما تنمو بالفعل حديقة حيوانات كبيرة من الأشياء التعسفية.

لست متأكدًا مما تقصده بذلك. تفسيري لما هو تعسفي هو "ما هي اللغات التي ندعمها" ، ولكن هذا هو نفس "امتياز القليل" ، والذي سيكون حسابًا مزدوجًا. وبالتالي سيكون هذا معيبًا قاتلاً فقط على هذا المستوى الواحد ، بدلاً من المضاعفات: D

aardappel ، النسخة القصيرة هي أن هذه هي خطتي الاحتياطية إذا فشل النهج المجرد التصريحي: اذهب في الاتجاه المعاكس تمامًا ووصف تنسيق التسلسل. يتم ملاحظة أن الويب نفسه مبني بالكامل تقريبًا على النص ، لأنه قاسم مشترك منخفض للغاية. النص مفهومة بشكل تافه من قبل جميع الأدوات ، وبالتالي فإن شيئًا مثل الويب ممكنًا فوقه.

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

@ jgravelle-google ربما ينبغي الاحتفاظ بأنواع المراجع منفصلة؟ لذلك ، قد يكون التوقيع الأولي لوظائف معينة هو ref ref i32 i32 i32 i32 وهو في الواقع 2 anyrefs متبوعين بمخازن مؤقتة من نوع معين (محدد في المخطط الافتراضي أعلاه).

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

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

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

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

شكرا للجميع على ملاحظاتكم.

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

لتلخيص الملاحظات حتى الآن:

  • هناك إجماع ضئيل للغاية حول تنسيق التسلسل ، إن وجد ، الذي سيكون الأفضل للوضع. تشمل البدائل FlatBuffers أو الرسوم البيانية الهيكلية C ABI ذات المؤشرات الأولية أو تنسيق IDL المخصص للوصلة أو مزيجًا مما سبق.

  • يحتاج الاقتراح إلى مساحة سلبية أقوى. العديد من القراء في حالة ارتباك بسبب نطاق الاقتراح ، وحالات الاستخدام التي كان من المفترض تسهيلها (الارتباط الثابت مقابل الديناميكي ، والوحدة النمطية إلى المضيف مقابل المضيف إلى المضيف ، ومشاركة البيانات القابلة للتغيير مقابل تمرير الرسائل غير القابلة للتغيير).

  • عبرlukewagner عن بعض الحماس لإمكانية وجود نظام وحدة نمطية يربط بين وحدات عدم الثقة المتبادلة ، عند دمجها مع تكامل ESM. يجب أن يتوسع التكرار التالي للاقتراح في هذه الإمكانية ؛ على وجه الخصوص ، أعتقد أن وجود نظام نوع متوافق مع الإصدارات السابقة سيسمح لـ wasm باستخدام نموذج شجرة تبعية يشبه npm ، مع تجنب العبء الأكبر لمشكلة الماس التبعية.

  • كان هناك القليل من التعليقات حول موضوع القدرات ، أي القيم غير الشفافة التي يمكن إرجاعها وتمريرها ، ولكن لا يتم إنشاؤها من البيانات الأولية. أعتبرها علامة على أن التكرار التالي يجب أن يكون أكثر تركيزًا عليها.

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

    • التركيز كثيرًا على اللغات المرئية للغاية ، وترك المزيد من اللغات المتخصصة وراءك.
    • وجود تجريد مُسرب يحاول أن يكون عامًا جدًا ، لكنه لا يغطي حالة استخدام أي شخص بشكل ملائم أو فعال.
    • تغطية عدد كبير جدًا من الحالات ، وإنشاء تطبيق N * N متضخم لا يزال يعاني من المشكلات المذكورة أعلاه.

يحتاج تكرار الاقتراح التالي إلى معالجة هذه المخاوف بطريقة أو بأخرى.

على وجه الخصوص ، أعتقد أن المناقشة ستستفيد كثيرًا من بعض الأمثلة المبتذلة للتفكير. قد تتضمن هذه الأمثلة مكتبتين على الأقل ، مكتوبتين بلغات مختلفة بتخطيطات بيانات مختلفة (مثل C ++ و Java) ، يتم استهلاكهما بواسطة برنامجين على الأقل بلغتين مختلفتين (مثل Rust و Python) ، لتوضيح مشكلة n * n و استراتيجيات لمواجهتها.

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

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

@ jgravelle-google:

طريقة نمذجة ذلك ، بغض النظر عن كيفية تحديد الارتباطات (أو حتى إذا حددنا أي شيء للارتباطات) ، هي التعامل مع ذلك في userland.

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

أنا في حيرة من أمري ، أرى ذلك كقول "الربط بين اللغات مستحيل تمامًا ، لذا لا يجب أن نحاول على الإطلاق ،"

أعتقد أنه من المرغوب تمامًا تحديد DDL (نظام النوع) لتداخل البيانات بين اللغات. أنا فقط لا أعتقد أنه من الممكن بناء تحويلات إلى واسم. يجب تنفيذ التحويلات في أرض المستخدمين. تحدد طبقة الربط فقط التنسيق الذي يجب على كود المستخدم إنتاجه / استهلاكه.

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

عذرًا ، قصدت أنني أشك في أنه لن يكون هناك أي شيء أساسي بشكل رهيب حول هذه التحويلات. لذا فإن كلا من اختيارهم "تعسفي" ودلالاتهم الفردية.

كيف يمكننا التعامل مع أنواع المراجع؟

آه ، هذا سؤال جيد. FWIW ، نحن نحاول معالجة هذه المشكلة بالذات الآن لـ IDL / DDL لمنصة Dfinity. طالما لا يوجد سوى أي مرجع ، فإن الحل بسيط إلى حد ما: يحدد تنسيق التسلسل قطعتين ، شريحة ذاكرة تعرض البيانات الشفافة وشريحة جدول تعرض المراجع الموجودة. تتطلب أنواع المراجع المتعددة شرائح جدول متعددة وفقًا لذلك. السؤال الصعب هو ما يجب فعله بمجرد أن تصبح مجموعة أنواع المرجع غير محدودة (على سبيل المثال مع مراجع الوظائف المكتوبة).

بمجرد أن يكون لدينا أنواع GC ، يجب أن تكون هناك طريقة بديلة لتوفير البيانات ، والتي تكون كقيمة GC. في هذه الحالة ، لا تعتبر المراجع مشكلة ، لأنه يمكن خلطها بحرية.

PoignardAzur :

جانبا ، أنا غير معتاد على هاسكل ، لكن فكرة الخيط كقوائم كسولة من الأحرف تفجر ذهني.

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

تضمين التغريدة

أعتقد أنه من المرغوب تمامًا تحديد DDL (نظام النوع) لتداخل البيانات بين اللغات. أنا فقط لا أعتقد أنه من الممكن بناء تحويلات إلى واسم. يجب تنفيذ التحويلات في أرض المستخدمين.

أوافق ، وأضيف إلى ذلك: إنني متشكك في إضافة شيء ما إلى مواصفات wasm لهذا لأنني لا أعتقد أن wasm بحاجة أكبر قدرة أكبر @ aardappel . (لكنني أعتقد أن التجريب في مساحة المستخدمين أمر ممتع للغاية ، كما هو الحال في جميع الأنظمة الأساسية!)

الشيء الوحيد المميز الذي يمتلكه wasm ، على الأقل على الويب ، هو أنواع JavaScript / Web API للسلاسل والمصفوفات وما إلى ذلك. من الواضح أن القدرة على التفاعل معهم أمر مهم.

لا أعتقد أن wasm بحاجة إلى حل بين اللغات أكبر من المنصات الأخرى

أعتقد أنه كذلك. إن استخدامك على الويب بشكل افتراضي يعني أن الشفرة يمكن تشغيلها في سياقات مختلفة وسيتم تشغيلها. بنفس الطريقة التي قد يكون بها الشخص <script src="http://some.other.site/jquery.js"> ، أود أن أرى أشخاصًا يجمعون مكتبات wasm بطريقة متعددة الأصول. نظرًا للخصائص سريعة الزوال وقابلية التركيب التي يوفرها الويب ، فإن القيمة المضافة للقدرة على التفاعل مع وحدة أجنبية أعلى مما كانت عليه في أي وقت مضى على الأنظمة الأصلية.

ولا أعتقد أن لدى wasm قدرة أكبر على تنفيذ مثل هذا الحل من الأنظمة الأساسية الأخرى.

وأعتقد أنه كذلك. نظرًا لأنه يتم تشغيل wasm بواسطة embedder / في مضيف ، فإن إنشاء الكود يتم تجريده بشكل فعال. وبسبب ذلك ، فإن الجهاز الظاهري لديه المزيد من الأدوات + الفسحة لدعم الإنشاءات عالية المستوى غير الممكنة في الأنظمة الأصلية.

لذلك أعتقد أن شيئًا ما في هذا الفضاء هو أكثر قيمة وإمكانية أكثر من الأنظمة الأخرى ، ولهذا السبب يعتبر الوسم مميزًا في هذا السياق. بالنسبة لي ، فإن JS interop هي حالة خاصة لمفهوم أكثر عمومية بأن وحدات wasm تحتاج إلى أن تكون قادرة على التحدث إلى أشياء خارجية ذات وجهات نظر مختلفة تمامًا عن العالم.

المسار إلى الأمام لهذا هو دفع هذا بالكامل إلى التشغيل المتداخل على مستوى الأداة في الوقت الحالي ، وتأجيل التوحيد حتى نحصل على تنسيق ناجح. لذلك إذا كان الهدف هو الحصول على النظام البيئي السائد لمدير حزمة wasm باستخدام تنسيق واجهة معين ، (وهل هذا NPM أو WAPM أو بعض مدير الحزم الذي تم إنشاؤه حتى الآن؟) فيمكن أن يحدث ذلك بشكل مستقل عن التوحيد القياسي. من الناحية النظرية ، يمكننا توحيد ما يفعله الأشخاص بالفعل ، من أجل الحصول على أداء أفضل ، ولكن يمكن تنفيذ بيئة العمل في أرض المستخدمين. هناك خطر يتمثل في أن تنسيق اللغات الفائزة لا يفسح المجال للتحسين ، وينتهي بنا الأمر بمعيار واقعي دون المستوى الأمثل. إذا تمكنا من تصميم تنسيق بهدف التوحيد لاحقًا (النمط التعريفي في قسم مخصص يكون كافياً في الغالب؟) فهذا يزيل هذا الخطر ، ولكنه يؤخر أيضًا أي تحسينات في الأداء. بالنسبة لي ، يعد الأداء أحد أقل المحفزات إثارة لامتلاك هذا النوع من الأشياء ، لذا فأنا على ما يرام مع ذلك ، على الرغم من أن الآخرين قد يختلفون.

(وهل هذا NPM أو WAPM أو بعض مدير الحزم الذي تم إنشاؤه حتى الآن؟)

أعتقد أنه من السابق لأوانه أن يصبح WAPM مدير حزم قابل للتطبيق. نحتاج إلى ميزات مثل تكامل ESM و WASI وبعض أشكال الارتباطات بين اللغات ليتم توحيدها قبل أن يصبح مدير حزمة wasm ممكنًا.

كما هي ، لا أعتقد أن WAPM لديها إدارة تبعية.

لا أعتقد أن wasm بحاجة إلى حل بين اللغات أكبر من المنصات الأخرى

أعتقد أنه كذلك. إن استخدامك على الويب بشكل افتراضي يعني أن الشفرة يمكن تشغيلها في سياقات مختلفة وسيتم تشغيلها. بنفس الطريقة التي قد يفعلها المرء

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

هذا ملخص جيد بالنسبة لي.

أثناء كتابة مسودة جديدة ، لدي سؤال مفتوح للجميع في هذا الموضوع:

هل توجد مكتبة موجودة ، إذا تم تجميعها في WebAssembly ، فقد ترغب في أن تكون قادرًا على استخدامها من أي لغة؟

أنا أبحث بشكل أساسي عن حالات الاستخدام المحتملة لبناء التصميم عليها. لديّ (على وجه التحديد ، React ، ومحرك Bullet ، وأنظمة المكونات الإضافية) ، لكني أرغب في استخدام المزيد من الأمثلة.

PoignardAzur تستخدم الكثير من اللغات في لغة C نفس مكتبات Perl-Compatible Regular Expression (PCRE) ، ولكن في تضمين المتصفح ، من المحتمل أن تستخدم واجهة برمجة تطبيقات Regex الخاصة بـ JS.

PoignardAzur BoringSSL و libsodium يتبادر إلى الذهن.

أيضًا تنفيذ Cap'n Proto RPC ، ولكن هذا أمر غريب: يجب تنفيذ طبقة _serialization_ Cap'n Proto بواقعية بشكل مستقل في كل لغة نظرًا لأن معظمها عبارة عن طبقة API واسعة ولكن ضحلة تحتاج إلى أن تكون اصطلاحية ومضمنة -ودود. طبقة RPC ، OTOH ، ضيقة ولكنها عميقة. من حيث المبدأ ، يجب أن يكون من الممكن استخدام تطبيق C ++ RPC وراء أي تطبيق تسلسلي للغة تعسفية عن طريق تمرير مراجع مصفوفة البايت المشفرة بـ capnp عبر حدود FFI ...

أعتقد أن القيام بما هو مقترح في النهاية سيتطلب بعض التغييرات الغازية إلى حد ما على Web Assembly نفسه كما هو موجود بالفعل - ولكن يمكن القول إنه يستحق ذلك.

أود أن أشير إلى أن عالم SmallTalk كان لديه بعض التجارب الإيجابية مع مثل هذا الجهد الذي يمكن أن يكون مفيدًا في تطويرهم لبروتوكول النسخ المتماثل للدولة (SRP) وهو بروتوكول تسلسل فعال يمكن أن يمثل أي نوع من أي حجم إلى حد ما بكفاءة. لقد فكرت في جعله تخطيط ذاكرة أصلي لجهاز VM أو حتى FPGA ولكن لم أجربه. أعلم أنه تم نقله إلى لغة أخرى على الأقل ، Squeak ، بنتائج جيدة. بالتأكيد هناك شيء للقراءة على أنه يتداخل بشدة مع قضايا وتحديات وتجارب هذا الاقتراح.

أفهم لماذا كان Web IDL هو الاقتراح الافتراضي كلغة ملزمة: إنها لغة الربط التاريخية والناضجة إلى حد ما للويب. أنا أؤيد هذا القرار بشدة ، ومن المحتمل جدًا أنني كنت سأفعل الشيء نفسه. ومع ذلك ، قد ندرك أنه بالكاد يناسب السياقات الأخرى (فهم ، مضيفون / لغات أخرى). تم تصميم Wasm ليكون حياديًا للمضيف ، أو محايدًا للغة / النظام الأساسي. تعجبني فكرة استخدام تقنيات الويب الناضجة والعثور على حالة استخدام لسيناريوهات غير الويب ، ولكن في حالة Web IDL ، يبدو أنها مرتبطة حقًا بالويب. وهذا هو السبب في أنني أتابع تلك المحادثات عن كثب هنا.

لقد فتحت https://github.com/WebAssembly/webidl-bindings/issues/40 ، مما دفعني لطرح سؤال هنا لأنني لم أر أي ذكر له (أو فاتني).

في قصة الربط بأكملها ، ليس من الواضح "من" المسؤول عن إنشاء الارتباطات:

  • هل هو مترجم (يحول البرنامج إلى وحدة Wasm)؟
  • هل هو مؤلف برنامج (وهكذا ، هل الروابط مكتوبة بخط اليد)؟

أعتقد أن كلاهما صالح. وفي حالة Web IDL ، يبدو أنه يظهر بعض القيود (انظر الرابط أعلاه). ربما فاتني للتو خطوة مهمة في هذه العملية ، ولذا ، فكر في نسيان رسالتي.

حتى لو كان الهدف هو "إعادة تركيز" Web IDL ليكون أقل تمحورًا على الويب ، فهو في الوقت الحالي _ متمركز جدًا على الويب. وتبرز اقتراحات لاقتراح بدائل ، ومن هنا جاء هذا الخيط. لذلك ، أنا قلق من احتمال حدوث تجزئة. من الناحية المثالية (وهذه هي الطريقة التي تم بها تصميم Wasm حتى الآن) ، نظرًا لوحدة Wasm بما في ذلك ارتباطاتها ، فمن الممكن تشغيلها في أي مكان كما هي. مع الارتباطات المكتوبة في Web IDL ، Cap'n 'Proto ، FlatBuffers ، أيا كان ، أنا متأكد تمامًا من أنه لن يكتب جميع المترجمين أو مؤلفي البرامج نفس الارتباطات بصيغ مختلفة ليكونوا عبر الأنظمة الأساسية حقًا. من المضحك أن هذه حجة لصالح الارتباطات المكتوبة بخط اليد: يمكن للأشخاص المساهمة في برنامج عن طريق كتابة ارتباطات للمنصة P. ولكن دعنا نعترف بأن هذا لن يكون مثاليًا على الإطلاق.

لتلخيص ما يلي: أنا قلق من التشرذم المحتمل بين الارتباطات على الويب وغير المرتبطة بالويب. إذا تم الاحتفاظ بلغة غير مرتبطة بالويب ، فهل سيتم تنفيذها بشكل واقعي بواسطة متصفحات الويب؟ سيتعين عليهم كتابة روابط "Wasm ⟶ لغة الربط B Web IDL". لاحظ أن هذا هو نفس السيناريو لجميع المضيفين: Wasm ⟶ لغة الربط B ⟶ host API.

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

ربما يكون الاتجاه الحالي في "روابط webIDL" بعيدًا عن webIDL
بحد ذاتها. ومع ذلك ، فإن المعضلة هي:

اللغة "الطبيعية" للتعبير عن الوحدة النمطية ومضيف الوحدة
تعد إمكانية التشغيل البيني أكثر ثراءً من لغة WASM الطبيعية. هذه
يعني أن أي مكافئ لـ IDL قابل للاستخدام سيبدو تعسفيًا إلى حد ما من
WASM ل.

من ناحية أخرى ، للقوم الذين يرون العالم من عدسة C / C ++
(و Rust وأمثالها) أي شيء أكثر ثراءً من نموذج WASM يخاطر بأن يكون
غير صالح للإستعمال. يمكننا أن نرى هذا بالفعل بصعوبة دمج المرجع
أنواع في سلسلة الأدوات.

بالإضافة إلى ذلك ، ليس من التفويض المباشر لـ WASM دعم العامة
إمكانية التشغيل البيني بين اللغات. ولا ينبغي أن تكون المنظمة البحرية الدولية.

(هناك نسخة محدودة أكثر من إمكانية التشغيل البيني بين اللغات التي أنا
الإيمان ليس فقط داعمًا ولكنه حاسم أيضًا: إنه في كل منا
الاهتمام الذي يمكن لمقدمي القدرات ومستخدمي الإمكانات تلبيته
مع الحد الأدنى من الاحتكاك. (القدرة هي كلام الإدارة ولكن لدي
لم يتم العثور على مصطلح أفضل.) يتطلب هذا أسلوبًا مختلفًا من IDL وأسلوبًا واحدًا
هذا أسهل في التنفيذ مما هو مطلوب للغة بين اللغات الكاملة
interop.)

خلاصة القول: هناك حالة لوجود مكافئ لـ IDL ، ونحن بحاجة إليه
لدعم التشغيل المتداخل عبر حدود الملكية. ما ينتهي به الأمر
الوجود ليس واضحًا في الوقت الحالي.

يوم الاثنين 24 يونيو 2019 الساعة 7:02 صباحًا Ivan Enderlin [email protected]
كتب:

أفهم لماذا كان Web IDL هو الاقتراح الافتراضي كلغة ملزمة:
إنها لغة الربط التاريخية والناضجة إلى حد ما للويب. أنا
يدعم هذا القرار بشكل كبير ، ومن المحتمل جدًا أنني كنت سأقوم بعمل
نفس. ومع ذلك ، قد ندرك أنه بالكاد يناسب السياقات الأخرى
(فهم ، المضيفين / اللغات الأخرى). تم تصميم Wasm ليكون حيادي المضيف ،
أو لغة / حيادية النظام الأساسي. تعجبني فكرة استخدام الويب الناضج
والعثور على حالة استخدام لسيناريوهات غير الويب ، ولكن في الحالة
من Web IDL ، يبدو أنه مرتبط حقًا بالويب. وهذا هو سبب كوني شديدة
تتابع عن كثب تلك المحادثات هنا.

لقد فتحت WebAssembly / webidl-bindings # 40
https://github.com/WebAssembly/webidl-bindings/issues/40 ، الذي قادني
لطرح سؤال هنا لأنني لم أشاهد أي ذكر له (أو فاتني).

في القصة الملزمة بأكملها ، ليس من الواضح "من" المسؤول
إنشاء الارتباطات:

  • هل هو مترجم (يحول البرنامج إلى وحدة Wasm)؟
  • هل هو مؤلف برنامج (وهكذا ، هل الروابط مكتوبة بخط اليد)؟

أعتقد أن كلاهما صالح. وفي حالة Web IDL ، يبدو أنه يظهر بعضًا
القيود (انظر الرابط أعلاه). ربما فاتني للتو خطوة مهمة في
العملية ، وهكذا ، ضع في اعتبارك أن تنسى رسالتي.

حتى إذا كان الهدف هو "إعادة تركيز" Web IDL ليكون أقل تركيزًا على الويب ، في الوقت الحالي ،
فمن المركزية للشبكة للغاية. وتنشأ مقترحات لاقتراح بدائل ،
ومن هنا هذا الموضوع. لذلك ، أنا قلق من احتمال حدوث تجزئة.
من الناحية المثالية (وهذه هي الطريقة التي تم بها تصميم Wasm حتى الآن) ، مع إعطاء وحدة Wasm
بما في ذلك ارتباطاتها ، فمن الممكن تشغيلها في أي مكان كما هي. مع
الارتباطات المكتوبة في Web IDL ، Cap'n 'Proto ، FlatBuffers ، أيا كان ، أنا
بالتأكيد لن يكتب جميع المترجمين أو مؤلفي البرامج نفس الشيء
الارتباطات في صيغ مختلفة لتكون عبر النظام الأساسي حقًا. بشكل مضحك ، هذا هو
حجة لصالح الارتباطات المكتوبة بخط اليد: يمكن للناس المساهمة في أ
عن طريق كتابة ارتباطات للمنصة P. ولكن دعنا نعترف بأن هذا لن يكون كذلك
مثالي على الإطلاق.

لتلخيص ما يلي: أنا قلق من التشرذم المحتمل بين الويب و
روابط غير الويب. إذا تم الاحتفاظ بلغة غير ملزمة للويب ، فستكون كذلك
تم تنفيذه بواقعية بواسطة متصفحات الويب؟ سيكون عليهم أن يكتبوا
الارتباطات "Wasm ⟶ لغة الربط B Web IDL". لاحظ أن هذا هو نفسه
سيناريو لجميع المضيفين: Wasm ⟶ لغة الربط B ⟶ host API.

لأولئك الذين لديهم فضول ، أعمل في Wasmer وأنا مؤلف PHP-
https://github.com/wasmerio/php-ext-wasm ، Python-
https://github.com/wasmerio/python-ext-wasm ، روبي-
https://github.com/wasmerio/ruby-ext-wasm and Go-
https://github.com/wasmerio/go-ext-wasm تكامل Wasm. نحن بدأنا
وجود ملعب جميل لاختراق روابط مختلفة من أجل مختلف تمامًا
المضيفين. إذا كان أي شخص يريد مني دمج حلول مختلفة ، لجمع
ردود الفعل ، أو محاولة التجربة ، نحن جميعًا منفتحون ومستعدون للتعاون
ووضع المزيد من الموارد عليه.

-
أنت تتلقى هذا لأنه تم ذكرك.
قم بالرد على هذا البريد الإلكتروني مباشرة ، وقم بعرضه على GitHub
https://github.com/WebAssembly/design/issues/1274؟email_source=notifications&email_token=AAQAXUD6WA22DDUS7PYQ6F3P4DHYRA5CNFSM4HJUHVG2YY3PNVWWK3TUL52HS4DFVREXG43VMVE50
أو كتم الخيط
https://github.com/notifications/unsubscribe-auth/AAQAXUGM66AWN7ZCIVBTXVTP4DHYRANCNFSM4HJUHVGQ
.

-
فرانسيس مكابي
SWE

يمكننا بالفعل رؤية ذلك بصعوبة دمج أنواع المرجع في سلسلة الأدوات.

لا يمكنني التحدث بلغات أخرى ، لكن Rust + wasm-bindgen يدعم بالفعل:

لذا فضولي: ما الصعوبات التي تشير إليها؟

فهمي للصعوبات موجود أكثر في نهاية C ++. لدى Rust برمجة metaprogramm قوية بما يكفي لجعل هذا أكثر منطقية في نهاية اللغة ، لكن userland C ++ يواجه صعوبة في التفكير في أي مرجع على سبيل المثال.

سأكون فضوليًا لسماع المزيد حول المشكلات المحددة لـ C ++ هنا. (هل هي خاصة بـ C ++ أم خاصة بـ LLVM؟)

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

يوم الإثنين 24 يونيو 2019 الساعة 3:07 مساءً كتب Alon Zakai [email protected] :

سأكون فضوليًا لسماع المزيد حول المشكلات المحددة لـ C ++ هنا. (هل هم
C ++ محددة أو LLVM محددة؟)

-
أنت تتلقى هذا لأنه تم ذكرك.
قم بالرد على هذا البريد الإلكتروني مباشرة ، وقم بعرضه على GitHub
https://github.com/WebAssembly/design/issues/1274؟email_source=notifications&email_token=AAQAXUDW237MUBBUUJLKS6LP4FARJA5CNFSM4HJUHVG2YY3PNVWWK3TUL52HS4DFVREXG43VMV97
أو كتم الخيط
https://github.com/notifications/unsubscribe-auth/AAQAXUB4O3ZX4LRQSQRL763P4FARJANCNFSM4HJUHVGQ
.

-
فرانسيس مكابي
SWE

عند التحدث إلى fgmccabe في وضع

ما زلت أشعر بالفضول حول ما إذا كان هناك أي شيء خاص بـ C ++ هنا. لا أعتقد أن هناك؟

إن فهمي لما يجعل C ++ صعبة هنا هو إذا قلت:

struct Anyref; // opaque declaration
void console_log(Anyref* item); // declaration of ref-taking external JS API
Anyref* document_getElementById(const char* str);

void wellBehaved() {
  // This should work
  Anyref* elem = document_getElementById("foo");
  console_log(elem);
}

void notSoWellBehaved() {
  // ????
  Anyref* elem = document_getElementById("bar");
  Anyref* what = (Anyref*)((unsigned int)elem + 1);
  console_log(what);
}

الخبر السار هو أن المثال الأخير هو UB على ما أعتقد (المؤشرات غير الصالحة هي UB بمجرد إنشائها) ، ولكن كيف نحاول نمذجة ذلك في LLVM IR؟

@ jgravelle-google أعتقد أنه حتى struct Anyref; يفترض مسبقًا أنه شيء منطقي في الذاكرة الخطية. بدلاً من ذلك ، لماذا لا نمذجه بمقبض عدد صحيح كما ذكرنا سابقًا ، مثل مواد OpenGL ومقابض الملفات وما إلى ذلك؟

using Anyref = uint32_t; // handle declaration
void console_log(Anyref item); // declaration of ref-taking external JS API
Anyref document_getElementById(const char* str);

void wellBehaved() {
  // This should work
  Anyref elem = document_getElementById("foo");
  console_log(elem);
}

يجب البحث عن مقبض العدد الصحيح في الجدول عند استخدامه - مرة أخرى ، هذا مجرد جانب سلبي للغات التي تستخدم الذاكرة الخطية مثل C ++ و Rust. ومع ذلك ، يمكن بالتأكيد تحسينه محليًا على الأقل - إن لم يكن بواسطة LLVM ، فعندئذٍ على مستوى الوعاء.

سيعمل ذلك ، ولكن بعد ذلك تحتاج إلى التأكد من الاتصال بـ table_free(elem) أو ستحتفظ بمرجع إليه إلى الأبد. الذي ليس - هذا - غريبًا بالنسبة لـ C ++ ، ممنوح.

إنه شيء من رسم الخرائط الغريب لأنه لا يوجد طبقات بشكل جيد على ما أعتقد؟ يبدو الأمر وكأنه مكتبة على غرار OpenGL ، ولكنه يعتمد على سحر المترجم لتقديمه - لا أعتقد أنه يمكنك إنشاء anyref.h في C ++ حتى مع وجود لغة مضمنة ، إذا كنت تعتمد على إعلان منفصل طاولة.

على أي حال ، أعتقد أن كل شيء ممكن / يمكن تتبعه ، ولكن ليس كل شيء بسيطًا.

kripken صحيح أن الدعم "المناسب" الأصلي anyref سيتطلب بعض التغييرات على LLVM (وفي rustc) ، لكن هذا ليس عقبة في الواقع.

يقوم wasm-bindgen بتخزين wasm anyref s في جدول wasm ، ثم في الذاكرة الخطية يخزن فهرسًا صحيحًا في الجدول. لذلك يمكنه بعد ذلك الوصول إلى anyref باستخدام تعليمات wasm table.get .

حتى يتم تنفيذ wasm-gc ، ستحتاج لغات GC إلى استخدام نفس الإستراتيجية بالضبط ، لذلك لا يفوتك Rust (وآخرون).

إذن ما الذي سيكسبنا الدعم الأصلي anyref في LLVM؟ حسنًا ، سيمكن ذلك من تمرير / إرجاع anyref من الوظائف ، بدلاً من الحاجة إلى تحويل anyref بشكل غير مباشر من خلال جدول wasm. سيكون ذلك مفيدًا ، نعم ، ولكن هذا مجرد تحسين للأداء ، فهو لا يمنع في الواقع استخدام anyref .

تضمين التغريدة

يقوم wasm-bindgen بتخزين wasm anyrefs الأصلي في جدول wasm ، ثم في الذاكرة الخطية يخزن فهرسًا صحيحًا في الجدول. لذلك يمكنه بعد ذلك الوصول إلى anyref باستخدام تعليمات wasm table.get.

بالضبط ، نعم ، هذا هو النموذج الذي كنت أشير إليه.

حتى يتم تنفيذ wasm-gc ، ستحتاج لغات GC إلى استخدام نفس الإستراتيجية بالضبط ، لذلك لا يفوتك Rust (وآخرون).

نعم ، في الوقت الحالي ، لا تتمتع لغات GC بأي ميزة لأنه ليس لدينا لغة wasm GC الأصلية. لكن نأمل أن يتغير ذلك! :) في النهاية أتوقع أن تتمتع لغات GC بميزة واضحة هنا ، على الأقل إذا قمنا بعمل GC بشكل صحيح.

إذن ما الذي سيكسبنا دعم anyref الأصلي في LLVM؟ حسنًا ، سيمكن ذلك من تمرير / إرجاع أي مرجع مباشرة من الوظائف ، بدلاً من الحاجة إلى عدم توجيه anyref من خلال جدول wasm. سيكون ذلك مفيدًا ، نعم ، ولكن هذا مجرد تحسين للأداء ، فهو لا يمنع في الواقع استخدام أي مرجع.

متفق عليه ، نعم ، سيكون هذا فقط ميزة ممتازة للغات GC (في النهاية) على C ++ و Rust وما إلى ذلك. ولا يمنع استخدامها.

تمثل الدورات مشكلة أكبر لـ C ++ و Rust ، على الرغم من ذلك ، منذ جذر الجداول. ربما يمكننا الحصول على واجهة برمجة تطبيقات تتبع أو "كائنات ظل" ، وهي طريقة ما لتعيين بنية روابط GC داخل C ++ / Rust حتى يتمكن GC الخارجي من فهمها. لكن لا أعتقد أن هناك اقتراحًا فعليًا لأي من هؤلاء حتى الآن.

في النهاية ، أتوقع أن تتمتع لغات GC بميزة واضحة هنا ، على الأقل إذا قمنا بعمل GC بشكل صحيح.

قد أكون مخطئًا ، لكن سأندهش إذا كان هذا هو الحال: سيتعين على لغات GC تخصيص بنية wasm GC ومن ثم سيتعين على محرك wasm تتبع ذلك أثناء تدفقه عبر البرنامج.

بالمقارنة ، لا يحتاج Rust إلى تخصيص (فقط قم بتعيينه لجدول) ، ويحتاج فقط إلى تخزين عدد صحيح ، ويحتاج محرك wasm فقط إلى تتبع جدول ثابت واحد غير متحرك لأغراض GC.

أعتقد أنه من الممكن أن anyref الوصول قد يكون optimizable للغات GC، لأنها لن تحتاج إلى استخدام table.get ، ولكن أتوقع table.get ليكون سريع جدا.

فهل يمكنك أن تشرح المزيد عن الطريقة التي تتوقع أن يعمل بها برنامج wasm-gc بشكل أفضل من برنامج يستخدم جدول wasm؟

ملاحظة: لقد بدأ هذا في الابتعاد عن الموضوع ، لذا ربما يتعين علينا نقل هذه المناقشة إلى موضوع جديد؟

حقًا هذا فقط: تجنب table.get/table.set . مع GC ، يجب أن يكون لديك المؤشر الخام هناك ، مما يحفظ المراوغات. لكن نعم ، أنت محق في أن Rust و C ++ يحتاجان فقط إلى تخزين عدد صحيح ، وهما سريعان جدًا بشكل عام ، لذلك قد لا تكون أي ميزة GC مهمة!

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

تضمين التغريدة

يجب تنفيذ طبقة التسلسل Cap'n Proto بشكل واقعي بشكل مستقل في كل لغة نظرًا لأن معظمها عبارة عن طبقة API واسعة ولكن ضحلة تحتاج إلى أن تكون اصطلاحية ومضمنة. طبقة RPC ، OTOH ، ضيقة ولكنها عميقة

أي مجلد هو؟

PoignardAzur آسف ، لا أفهم سؤالك.

@ kentonv أنا أبحث في مستودع capnproto Github. أين طبقة التسلسل؟

PoignardAzur إذن ، هذا يعود إلى وجهة نظري. لا يوجد مكان واحد يمكنك الإشارة إليه والقول "هذه هي طبقة التسلسل". في الغالب ، "تسلسل" Cap'n Proto هو مجرد مؤشر حسابي حول الأحمال / المخازن إلى المخزن المؤقت الأساسي. بالنظر إلى ملف مخطط ، يمكنك استخدام منشئ التعليمات البرمجية لإنشاء ملف رأس يحدد الأساليب المضمنة التي تقوم بحساب المؤشر الصحيح للحقول المعينة المحددة في المخطط. يحتاج رمز التطبيق بعد ذلك إلى استدعاء هذه الموصلات التي تم إنشاؤها في كل مرة يقرأ فيها أو يكتب أي حقل.

هذا هو السبب في أنه ليس من المنطقي محاولة استدعاء تطبيق مكتوب بلغة مختلفة. سيكون استخدام FFI خام لكل وصول إلى الحقل مرهقًا للغاية ، لذلك لا شك في أنك ستنتهي بكتابة مُنشئ كود يلف FFI في شيء أجمل (ومخصص لمخططك). لكن هذا الرمز الذي تم إنشاؤه سيكون على الأقل معقدًا مثل الكود الذي يطبقه Cap'n Proto بالفعل - ربما يكون أكثر تعقيدًا (وأبطأ بكثير!). لذلك من المنطقي أن تكتب فقط مولد أكواد للغة الهدف مباشرة.

ربما تكون هناك بعض وظائف المساعد الداخلية ضمن تطبيق Cap'n Proto التي يمكن مشاركتها. على وجه التحديد ، يحتوي layout.c++ / layout.h على كل الكود الذي يفسر ترميز مؤشر capnp ، ويقوم بفحص الحدود ، وما إلى ذلك. تستدعي موصّل الشفرة المولدة هذا الرمز عند قراءة / كتابة حقول المؤشر. لذا ربما يمكنني تخيل تغليف هذا الجزء في مؤسسة مالية أجنبية ليتم استدعاؤها من لغات متعددة ؛ لكني ما زلت أتوقع كتابة مولدات الأكواد وبعض مكتبة دعم وقت التشغيل في كل لغة هدف.

نعم ، آسف ، قصدت العكس ^ ^ (طبقة RPC)

PoignardAzur Ohhh ، وأفترض أنك مهتم تحديدًا بالنظر إلى الواجهات ، نظرًا لأنك تفكر في كيفية تغليفها في FFI. إذن فأنت تريد:

  • capability.h : واجهات تجريدية لتمثيل القدرات واستدعاء RPC ، والتي من الناحية النظرية يمكن دعمها من خلال مجموعة متنوعة من التطبيقات. (هذا هو الجزء الأهم.)
  • rpc.h : تنفيذ RPC عبر الشبكة.
  • rpc-twoparty.h : محول النقل لـ RPC عبر اتصال بسيط.

تم استبدال هذا الاقتراح الآن بالرقم # 1291: ارتباطات OCAP.

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات

القضايا ذات الصلة

cretz picture cretz  ·  5تعليقات

spidoche picture spidoche  ·  4تعليقات

JimmyVV picture JimmyVV  ·  4تعليقات

jfbastien picture jfbastien  ·  6تعليقات

void4 picture void4  ·  5تعليقات