Design: هل يمكن لـ WebAssembly.Instance إعادة ترجمة وحدة تم تجميعها بالفعل؟

تم إنشاؤها على ٢٧ أكتوبر ٢٠١٦  ·  94تعليقات  ·  مصدر: WebAssembly/design

قل لدي هذا الرمز:

let descriptor = /* ... */;
let memories = Array.apply(null, {length: 1024}).map(() => new WebAssembly.Memory(descriptor));
let instance = fetch('foo.wasm')
  .then(response => response.arrayBuffer())
  .then(buffer => WebAssembly.compile(buffer))
  .then(module => new WebAssembly.Instance(module, { memory: memories[1023] }));

يُسمح بمنع WebAssembly.Instance لفترة طويلة من الوقت. هل يمكنها على سبيل المثال إعادة ترجمة WebAssembly.Module ؟

في معظم الحالات ، سأقول لا ، ولكن ماذا لو لم تعجب الشفرة المجمعة بالفعل الذاكرة التي تتلقاها؟ لنفترض ، لأن هذه الذاكرة هي ذاكرة ذات وضع بطيء وتم تجميع الرمز بافتراض الوضع السريع؟ ربما كان memories[0] ذاكرة ذات وضع سريع ، لكن من المؤكد أن memories[1023] لن يكون كذلك.

ماذا عن هذا الرمز بدلاً من ذلك:

let instances = [0,1,2,3,4,5,6,7].map(v => fetch(`foo${v}.wasm`)
  .then(response => response.arrayBuffer())
  .then(buffer => WebAssembly.compile(buffer))
  .then(module => new WebAssembly.Instance(module)));

هل يُسمح لهذه المكالمات إلى WebAssembly.Instance بالتسبب في إعادة التحويل البرمجي؟

بافتراض أن ما ورد أعلاه منطقي ، إليك بعض الأسئلة ذات الصلة:

  • هل نريد وظيفة غير متزامنة تعود بالوعد يمكنها تجميع _و_ إنشاء مثيل لها؟ أنا لا أقول أنه يجب علينا التخلي عن أي من واجهات برمجة التطبيقات المتزامنة وغير المتزامنة التي لدينا بالفعل ، فأنا أقترح واجهة برمجة تطبيقات جديدة غير متزامنة.
  • كيف يكشف المستعرض أن الشفرة المجمعة في WebAssembly.Module سريعة ، وأن مثيل WebAssembly.Memory مناسب لمثل هذا الرمز السريع؟ في الوقت الحالي ، يبدو أن الإجابة هي "جربها وشاهد ما إذا كان يمكنك ملاحظتها".
  • كيف يعرف المستخدم عدد المرات WebAssembly.Memory التي يُسمح بها قبل أن يحصل على رمز بطيء (عد تلك الضمنية ، على سبيل المثال كما تم إنشاؤها بواسطة المثال الثاني)؟
JS embedding

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

kgryte كان يجب أن أوضح أن تعليقي يتعلق في المقام الأول بالمتصفح كسياق تنفيذ. لقد وصلنا إلى سطح API لا يزال يعرض واجهات برمجة التطبيقات المتزامنة. قد تفرض المتصفحات حدًا للحجم على الوحدات التي تم تمريرها إلى واجهات برمجة التطبيقات المتزامنة (Chrome يفعل ذلك بالفعل ، على سبيل المثال) ، ولكن هذا الحد قابل للتكوين بواسطة أداة التضمين ولا يجب تطبيقه على Node.

ال 94 كومينتر

سيكون من الجيد أن يتسبب WebAssembly.Instance أحيانًا في إعادة التجميع ، وبهذه الطريقة يمكن أن تكون متغيرات الكرة الأرضية غير القابلة للتغيير ثابتة في الكود الذي تم إنشاؤه. على سبيل المثال ، يُنشئ Emscripten رمزًا قابلًا لإعادة تحديد موضعه عن طريق موازنة جميع المؤشرات ببيانات ثابتة. يتم تمرير الإزاحة كمتغير عام غير قابل للتغيير عند إنشاء الوحدة النمطية. إذا كان بإمكان WebAssembly.Instance إعادة التحويل البرمجي ، فيمكنه

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

في 27 أكتوبر 2016 الساعة 03:24 ، مايكل بيبينيتا إخطارات github.com
كتب:

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

-
أنت تتلقى هذا لأنك مشترك في هذا الموضوع.
قم بالرد على هذا البريد الإلكتروني مباشرة ، وقم بعرضه على GitHub
https://github.com/WebAssembly/design/issues/838#issuecomment -256522163 ،
أو كتم الخيط
https://github.com/notifications/unsubscribe-auth/AEDOO9sJPgujK3k0f6P7laYV_zaJxES5ks5q3_1LgaJpZM4Kh1gM
.

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

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

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

  • يمكن للضمني القيام بالتخزين المؤقت الضمني الذي يعالج المحتوى (والذي يمكن أن يتضمن معلمات محيطة في المفتاح) ، كما نفعل مع asm.js حاليًا في FF. قد يكون هذا نوعًا من الألم ولديه جميع مشاكل القدرة على التنبؤ / الكشف عن مجريات الأمور لأي ذاكرة تخزين مؤقت ضمنية.
  • يمكننا إنشاء طريقة جديدة (على سبيل المثال ، واجهة برمجة تطبيقات جديدة WebAssembly.Cache حيث تقوم بتمرير رمز بايت ومعلمات إنشاء مثيل واستعادة Promise<Instance> .

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

@ rossberg-chromium يبدو أنني أوضحت هدفي بشكل سيئ: لا أريد المجادلة بشأن ما تقوله المواصفات. أحاول أن أشير إلى ما يبدو أنه مفاجأة جادة للمطورين ، يختبئون تحت واجهة برمجة التطبيقات. لن يتوقع المطور إعادة تجميع نتيجة .compile . هذا يبدو وكأنه عيب في التصميم بالنسبة لي.

lukewagner حتى مع التخزين المؤقت الضمني أو الصريح ، قد نواجه نفس المشكلة: كم WebAssembly.Memory يمكن إنشاؤه في نفس مساحة العنوان / الأصل هو أحد قيود المتصفح. يعجبني ما تقترحه ، لكنني أعتقد أنه أمر متعامد مع هذه المشكلة. اسمحوا لي أن أعرف إذا كنت قد أسأت فهم ما تقترحه.

ربما يمكن منح .compile و Module Memory ، و Instance له خاصية .memory التي يمكن تمريرها إلى مجموعات / إنشاءات أخرى ؟

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

jfbastien مع التخزين المؤقت الضمني / الصريح الذي تم توفير معلمات إنشاء مثيل معينة (لذلك Memory ) ، لا أرى كيف ستكون هناك حاجة لإعادة التجميع.

jfbastien مع التخزين المؤقت الضمني / الصريح الذي تم توفير معلمات إنشاء مثيل معينة (لذلك Memory ) ، لا أرى كيف ستكون هناك حاجة لإعادة التجميع.

قد يكون هناك:

  1. إنشاء العديد من Memory s.
  2. قم بترجمة الشفرة ، باستخدام فحص واضح (بطيء) للحدود نظرًا لوجود عدد كبير جدًا من Memory ies.
  3. تخزين هذا الرمز.
  4. غادر الصفحة.
  5. تحميل الصفحة مرة أخرى.
  6. قم Memory واحد فقط ، والذي يحصل على الإصدار السريع.
  7. احصل من ذاكرة التخزين المؤقت.
  8. تلقي رمز بطيء Instance .

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

كما قلت: أحب API Cache الذي تقترحه ، أعتقد أنه يجعل WebAssembly أكثر قابلية للاستخدام ، لكن أعتقد أن المشكلة لا تزال قائمة. 😢

حسنًا ، هذه وجهة نظري حول وجود ذاكرة تخزين مؤقت مُحسّنة تقبل معلمات إنشاء مثيل ورمز بايت: ذاكرة التخزين المؤقت مجانية لإعادة الترجمة إذا كان ما تم تخزينه مؤقتًا لا يتطابق مع معلمات إنشاء مثيل. لذا فإن الخطوات ستكون فقط:

  1. إنشاء العديد من Memory s
  2. طلب Instance من ذاكرة التخزين المؤقت ، مروراً بواحدة من تلك (بطيئة) Memory s
  3. يتم تجميع الكود البطيء وتخزينه مؤقتًا وإعادته كـ Instance
  4. غادر الصفحة
  5. تحميل الصفحة مرة أخرى
  6. تخصيص Memory واحد فقط
  7. طلب Instance من ذاكرة التخزين المؤقت ، تمرير سريع Memory
  8. يتم تجميع الكود السريع وتخزينه مؤقتًا وإعادته كـ Instance

وبعد الخطوة 8 ، سيتم تخزين جميع عمليات تحميل الصفحات المستقبلية في ذاكرة التخزين المؤقت بسرعة أو بطيئة.

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

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

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

أعتقد أن هذا يعني أن المواصفات ستشجع البائعين على التقارب للسماح فقط بحجوزات 4 جيجا بايت في أي وقت يتم فيه تخصيص ذاكرة wasm ، أو الحصول على تحسينات ذاكرة التخزين المؤقت / lazy-compile / profile لاكتشاف ذلك.

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

من المحزن أننا نلاحظ هذا الآن فقط ، لكنني مندهش لأنكم لا ترون أن هذه مشكلة أكبر. هل هناك بعض التخفيف غير التخزين المؤقت الذي أغفله؟

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

إذا كان الأمر كذلك ، كيف ستبدو هذه البدائل للتخزين المؤقت أو غير المتزامن مثل:

  1. يجب أن يتطلب مؤلف الوحدة 4 غيغابايت كذاكرة دقيقة / قصوى
  2. متغير من التحويل البرمجي (غير متزامن على الأقل ، وربما أيضًا متزامن) ينتج مثيلاً يقبل الذاكرة السريعة فقط.

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

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

يوم 2: لا يزال الأمر غير مفيد جدًا للمطور: إذا استخدم هذا المتغير وفشل ، فماذا بعد؟

kripken لا أعتقد أن التجميع المزدوج فكرة جيدة.

kripken أعتقد أن هذا ما سنفعله بدون أي حل آخر لهذه المشكلة.

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

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

يجب أن يتطلب مؤلف الوحدة 4 غيغابايت كذاكرة دقيقة / قصوى

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

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

لا أعتقد أننا نريد تجميعات مزدوجة.

@ pizlonator حتى الآن ، لم نأخذ في الاعتبار التصميمات التي تتطلب أوضاعًا مختلفة من الكودجين: لقد خصصنا دائمًا مناطق 4 جيجابايت على 64 بت ولاحظنا نجاح ذلك لعدة آلاف من الذكريات على Linux و OSX و Windows. لدينا حد أعلى محافظ لمنع الاستنفاد الكلي التافه لمساحة العنوان المتاحة والتي أتوقع أنها ستكون كافية لدعم حالة استخدام العديد من المكتبات الصغيرة. لذلك أعتقد أن القيد الجديد الذي نتناوله هنا هو أن iOS به بعض قيود مساحة العنوان الافتراضية والتي يمكن أن تقلل من عدد تخصيصات 4 جيجابايت.

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

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

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

حتى الآن ، لم نأخذ في الاعتبار التصميمات التي تتطلب أوضاعًا مختلفة من الكودجين: لقد خصصنا دائمًا مناطق 4 جيجابايت على 64 بت ولاحظنا نجاح ذلك لعدة آلاف من الذكريات على Linux و OSX و Windows. لدينا رقم إجمالي متحفظ لمنع استنفاد إجمالي تافه لمساحة العنوان المتاحة والتي أتوقع أنها ستكون كافية لدعم حالة استخدام العديد من المكتبات الصغيرة. لذلك أعتقد أن القيد الجديد الذي نتناوله هنا هو أن iOS به بعض قيود مساحة العنوان الافتراضية والتي يمكن أن تقلل من عدد تخصيصات 4 جيجابايت.

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

ما هو الحد الذي لديك لعدد 4 جيجا بايت من الذكريات التي ستخصصها؟ ماذا تفعل عندما تصل إلى هذا الحد - تستسلم تمامًا ، أو تعيد التحويل البرمجي عند إنشاء مثيل؟

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

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

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

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

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

لذا ، هذا ليس حلاً رائعًا.

إلى جانب الانزعاج من الاضطرار إلى الخلاف في المواصفات والتطبيقات ، ما هي عيوب الجمع بين التجميع والتشكيل في إجراء واحد موعود به؟

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

أنا لست خبيرًا في ASLR ولكن ، iiuc ، حتى لو لم يكن لدينا حد متحفظ (أي ، إذا سمحنا لك بمواصلة التخصيص حتى فشل mmap لأن النواة وصلت إلى رقمها - نطاقات العناوين كحد أقصى) ، سيتم استهلاك جزء صغير فقط من المساحة القابلة للتوجيه البالغة 47 بت بالكامل ، لذا سيستمر وضع الكود في كونه عشوائيًا للغاية على مساحة 47 بت هذه. كما أن وضع كود IIUC و ASLR ليس عشوائيًا تمامًا ؛ يكفي فقط لجعل من الصعب التنبؤ بمكان وجود أي شيء.

ما هو الحد الذي لديك لعدد 4 جيجا بايت من الذكريات التي ستخصصها؟ ماذا تفعل
عندما تصل إلى هذا الحد - الاستسلام كليًا ، أو إعادة التحويل البرمجي عند إنشاء مثيل له؟

حسنًا ، نظرًا لأنه من أيام asm.js ، 1000 فقط. ثم يتم تخصيص الذاكرة فقط. ربما سنحتاج إلى التغلب على هذا ، ولكن حتى مع وجود العديد من التطبيقات فائقة الوحدات (مع العديد من الوحدات النمطية المنفصلة لكل منها) تشارك نفس العملية ، لا أستطيع أن أتخيل أننا سنحتاج إلى المزيد. أعتقد أن Memory يختلف عن ArrayBuffer s العادي في أن التطبيقات لن ترغب بشكل طبيعي في إنشاء الآلاف.

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

كما ذكرت أعلاه ، فإن إضافة Promise<Instance> eval(bytecode, importObj) API أمر جيد ، لكنه الآن يضع المطور في موقف صعب لأنه يتعين عليهم الآن الاختيار بين تعزيز الأداء على بعض الأنظمة الأساسية مقابل القدرة على تخزين الكود المترجم الخاص بهم مؤقتًا على جميع المنصات. يبدو أننا بحاجة إلى حل يتكامل مع التخزين المؤقت وهذا ما كنت أفكر فيه أعلاه باستخدام واجهة برمجة التطبيقات Cache الصريحة.

فكرة جديدة: ماذا لو أضفنا إصدارًا غير متزامن new Instance ، لنقل WebAssembly.instantiate ، وكما هو الحال مع WebAssembly.compile ، نقول أنه من المفترض أن يستخدم كل شخص الإصدار غير المتزامن؟ هذا شيء كنت أفكر فيه _ على أي حال_ نظرًا لأن إنشاء مثيل قد يستغرق بضع مللي ثانية إذا تم استخدام التصحيح. ثم نقول في المواصفات أن المحرك يمكنه القيام بعمل مكلف إما compile أو instantiate (أو لا شيء ، إذا كان المحرك يقوم بعملية التحقق / التجميع البطيئة!).

لا يزال هذا يترك السؤال عما يجب فعله عند تخزين compile d Module في IDB ، لكن هذا مجرد سؤال صعب عندما تكون هناك أوضاع تشفير متعددة _ على أي حال_. تتمثل إحدى الأفكار في أن Module s التي يتم تخزينها أو استردادها من IDB تمسك بمقبض إدخال IDB الخاص بهم ويضيفون رمزًا مجمعًا جديدًا إلى هذا الإدخال. وبهذه الطريقة ، فإن دخول البنك الإسلامي للتنمية سوف يتراكم ببطء واحد أو أكثر من الإصدارات المجمعة من وحدته ويكون قادرًا على توفير ما هو مطلوب أثناء إنشاء مثيل.

جزء IDB هو عمل أكثر قليلاً ، لكن هذا يبدو قريبًا جدًا من المثالية والأداء. WDYT؟

أعتقد أن إضافة غير متزامن instantiate أمر منطقي ، لكنني سأضيف أيضًا معلمة Memory إلى compile . إذا قمت بتمرير ذاكرة مختلفة إلى instantiate فيمكنك إعادة تجميعها ، وإلا فقد "ربطت" الذاكرة بالفعل عند التجميع.

لم أفكر في التخزين المؤقت بما يكفي للحصول على رأي كامل التكوين حتى الآن.

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

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

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

حسنًا ، نظرًا لأنه من أيام asm.js ، 1000 فقط. ثم يتم تخصيص الذاكرة فقط. ربما سنحتاج إلى التغلب على هذا ، ولكن حتى مع وجود العديد من التطبيقات فائقة الوحدات (مع العديد من الوحدات النمطية المنفصلة لكل منها) تشارك نفس العملية ، لا أستطيع أن أتخيل أننا سنحتاج إلى المزيد. أعتقد أن Memory يختلف عن ArrayBuffers القديم البسيط في أن التطبيقات لن ترغب بشكل طبيعي في إنشاء الآلاف.

1000 يبدو حد معقول. سوف أسأل مع رجال الأمن.

كما ذكرت أعلاه ، إضافة وعدإن واجهة برمجة تطبيقات Eval (bytecode، importObj) جيدة ، لكنها الآن تضع المطور في موقف صعب لأنه يتعين عليهم الآن الاختيار بين تعزيز الأداء على بعض الأنظمة الأساسية مقابل القدرة على تخزين الكود المترجم على جميع الأنظمة الأساسية. يبدو أننا بحاجة إلى حل يتكامل مع التخزين المؤقت وهذا ما كنت أفكر فيه أعلاه باستخدام واجهة برمجة تطبيقات ذاكرة التخزين المؤقت الصريحة.

حق. أستطيع أن أرى بعض الطرق التي يمكن أن تعمل بها واجهة برمجة التطبيقات هذه. قد تكون واجهة برمجة التطبيقات (API) المبتذلة والعملية هي التحميل الزائد للتقييم:

  1. examplePromise = EVAL (bytecode، importObj)
  2. examplePromise = EVAL (module، importObj)

ثم مثيل له جامع:

الوحدة النمطية = example.module

حيث الوحدة هي هيكل قابل للاستنساخ.

ما رأيك بهذا؟

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

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

جزء IDB هو عمل أكثر قليلاً ، لكن هذا يبدو قريبًا جدًا من المثالية والأداء. WDYT؟

مثيرة للاهتمام. بالنسبة لفكرتي أعلاه:

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

هناك ثلاثة مجالات لا يمنح فيها اقتراحك المستخدم قدرًا من التحكم مثل لي:

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

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

تعتمد هذه المشكلة على عدد المرات التي تجعل فيها التجزئة التخصيص سريعًا
ذاكرة (راجع للشكل الذي ستفشل فيه 4 غيغابايت + الحد الأقصى للإزاحة المدعومة ، أو 8 غيغابايت). إذا كان
ربما تكون طريقة أقل من 1٪ ، فقد لا يكون ذلك غير منطقي تمامًا
يجب أن يكون هذا الوضع OOM.

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

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

يوم الخميس ، 27 أكتوبر 2016 الساعة 9:03 مساءً ، pizlonator [email protected]
كتب:

mtrofin https://github.com/mtrofin

يجب أن يتطلب مؤلف الوحدة 4 غيغابايت كذاكرة دقيقة / قصوى

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

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

لا أعتقد أننا نريد تجميعات مزدوجة.

-
أنت تتلقى هذا لأنك مشترك في هذا الموضوع.
قم بالرد على هذا البريد الإلكتروني مباشرة ، وقم بعرضه على GitHub
https://github.com/WebAssembly/design/issues/838#issuecomment -256738329 ،
أو كتم الخيط
https://github.com/notifications/unsubscribe-auth/ALnq1F6CYUaq0unla0H6RYivUC8jfxIAks5q4PWIgaJpZM4Kh1gM
.

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

هناك كل هذه العكازات التي يمكننا استخدامها ، مثل التجميع المزدوج أو nop ، ولكن لماذا حتى لدينا عكازات؟

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

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

ومع ذلك ، أعتقد أنه لا ينبغي لنا استبعاد WebAssembly.compile والمنشئ Module : إنني أتخيل السيناريوهات التي يكون لديك فيها "خادم رمز" (يوفر تخزينًا مؤقتًا للرمز عبر الأصل عبر IDB + postMessage ؛ لقد نوقش هذا على وجه التحديد مع بعض المستخدمين بالفعل) الذي يريد تجميع الكود وتخزينه مؤقتًا دون الحاجة إلى "تزوير" معلمات إنشاء مثيل. (قد يكون هناك أيضًا بعض النفقات العامة غير الضرورية (القمامة ، والترقيع ، وما إلى ذلك) لإجراء إنشاء مثيل غير ضروري.) ولحالات الزاوية نفسها التي تريد تجميعًا متزامنًا (عبر new Module ) ، سنحتاج إلى الاحتفاظ بـ new Instance .

لذلك إذا تم الاتفاق على ذلك ، فإن ما يتلخص في هذا هو اقتراح مضاف بحت للحمل الزائدين WebAssembly.eval الذي ذكرته. نعم؟

تعديل واحد ، على الرغم من: أعتقد أنه لا ينبغي أن يكون لدينا module getter لأن هذا سيتطلب Instance للاحتفاظ ببعض البيانات الداخلية حول (بمعنى ، الرمز الثانوي) طوال عمر Instance ؛ الآن يمكن عادةً الحصول على GCed Module فور إنشاء مثيل. قد يقترح هذا إما خاصية بيانات (يمكن للمستخدم إزالتها ، على الرغم من أنه قد ينسى ذلك على الأرجح) ، أو ربما إصدار ثالث من eval بإرجاع {instance, module} الزوج ...

إن وجود واجهة برمجة تطبيقات غير متزامنة بخطوة واحدة كحالة موصى بها لتطبيق monolithic نموذجي أمر منطقي كنمط موصى به.

تم الاتفاق مع lukewagner على أن كل من حالة المزامنة (تجميع مضمنة) التي تغطيها وحدة نمطية جديدة + مثيل جديد مفيدة.
كما يبدو أيضًا أن خادم تجميع الخلفية (غير المتزامن) مع إنشاء مثيل المزامنة مفيد أيضًا.

يبدو أن إضافة متغيري التقييم المُقترحتين طريقة جيدة لتقديم ذلك.

ومع ذلك ، لا يعجبني الاسم ، لأنه سيتم خلطه في ذهن الناس (الأمان) مع js EVAL (الذي يشبه بطريقة واحدة ، ولكن ليس من حيث التقاط النطاق).
ماذا عن WebAssembly.instantiate؟

هاه ، نقطة جيدة ، إن EVAL لديها القليل من مندوب . +1 إلى WebAssembly.instantiate .

ما هو الدليل الإرشادي للمطور الذي سيتم كتابته عند استخدام إنشاء مثيل غير متزامن؟

mtrofin لاستخدام WebAssembly.instantiate افتراضيًا ما لم يكن لديهم بعض أنظمة مشاركة / تحميل التعليمات البرمجية الخاصة التي تتطلب تجميع Module s بشكل مستقل عن أي استخدام معين.

lukewagner هذا يبدو معقولا.

هاه ، نقطة جيدة ، إن EVAL لديها القليل من مندوب. +1 إلى WebAssembly.instantiate.

متفق.

لذلك إذا تم الاتفاق على ذلك ، فإن ما يتلخص في هذا هو اقتراح مضاف بحت من مجموعتي WebAssembly.eval الزائد الذي ذكرته. نعم؟

هذا ما يبدو عليه الأمر.

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

من المؤكد أن خاصية البيانات أفضل. أو أن يكون لديك WebAssembly.instantiate دائمًا بإرجاع مثيل ، زوج وحدة.

هل هذا صحيح: افترض أنك WebAssembly.instantiate بهدف الحصول على متغير وحدة الذاكرة السريعة. يمكنك الآن الحصول على الوحدة النمطية واستنساخها الهيكلية. الآن ، هذه الوحدة بحاجة إلى أن يتم إنشاء مثيل لها باستخدام Memory -es لدعم الذاكرة السريعة.

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

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

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

  1. إنشاء مثيل غير متزامن لوحدة نمطية واحدة.
  2. إنشاء مثيل غير متزامن لوحدة نمطية ، مع مشاركة الذاكرة مع الوحدات النمطية الأخرى.
  3. إنشاء مثيل متزامن لوحدة واحدة (لا أعتقد أن الوحدة المتعددة المتزامنة مفيدة؟).
  4. التخزين المؤقت لكل هذه الأشياء (التخزين في ذاكرة التخزين المؤقت ، وكذلك الاسترداد والتكوين ، مع الذاكرة).
  5. تحديث وحدة .wasm ، وأحمال مخزنة مؤقتًا للوحدات الأخرى.

أي شيء آخر؟ يبدو أن lukewagner لديه أفكار حول الواردات التي لا أتذمر منها تمامًا.

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

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

mtrofin على اليمين ، إذا كان Module m ، يمكنك استدعاء WebAssembly.instantiate(m) وهو غير متزامن. يمكنك _could_ الاتصال بـ new Instance(m) وقد يكون ذلك مكلفًا ، لكن هذا لا يختلف عن new Module(m) .

jfbastien بافتراض أنك عندما تقول "إنشاء مثيل غير متزامن" فإنك تعني "تجميع وإنشاء مثيل غير متزامن" ، فإليك النسخة القصيرة:

  1. WebAssembly.instantiate(bytecode, imports)
  2. WebAssembly.instantiate(bytecode, imports) ، حيث يتضمن imports الذاكرة المشتركة
  3. new Instance(new Module(bytecode), imports)
  4. في جميع الحالات ، يمكنك الحصول على Module ، ثم تحصل على put في IDBObjectStore . لاحقًا ، استعدت get a Module m واستدعيت WebAssembly.instantiate(m, imports) .
  5. لا يوجد شيء مميز هنا: أنت WebAssembly.instantiate وحدة واحدة من bytecode و instantiate الباقي من Module s التي تم سحبها من IDB.

هل يجب أن نوصي باستخدام إنشاء إنشاء المزامنة إذا كنت تشعر أنه يمكنك استخدام تجميع المزامنة وإنشاء مثيل غير متزامن إذا كنت تشعر أنه يجب عليك استخدام الترجمة غير المتزامنة؟

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

mtrofin 99٪ مما يكتبه المطورون (أو WebAssembly.instantiate . ستستخدم فقط واجهات برمجة التطبيقات للمزامنة لـ "أنا أكتب JIT في wasm" و WebAssembly.compile إذا كنت تكتب بعض أنظمة مشاركة التعليمات البرمجية ، لذلك أعتقد أن دروس "البدء" ستغطي حصريًا WebAssembly.instantiate .

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

إذن ملخص التغييرات (فقط حتى أكون واضحًا):

  • ترجع إضافة WebAssembly.instantiate (بايت ، عمليات الاستيراد) الوعد {المثيل: الوحدة النمطية:}
  • ترجع إضافة WebAssembly.instantiate (وحدة نمطية ، عمليات الاستيراد) وعدًا بـ {مثيل: ، وحدة:}
  • التغيير إلى وحدة جديدة (بايت ، واردات ) بإرجاع الوحدة النمطية
  • يؤدي التغيير إلى WebAssembly.compile (البايت والواردات ) إلى إرجاع الوعد بالمثيل

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

WDYT؟

عفوًا ، لقد قصدت وضع الواردات كوسيط على Instance . لست مقتنعًا بأنه ضروري من أجل Module أو compile . [تحرير: لأنه إذا كانت لديك ، فما عليك سوى الاتصال بـ instantiate ]

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

+1 على تركيز التوجيه على الزوج غير المتزامن من الترجمة والإنشاء - يجعل الرسالة بسيطة ويخفي تعقيدات مشكلة القرار عن المطور.

نعم ، أعتقد أننا جميعًا متفقون على أننا سنوجه الأشخاص إلى:
اول مرة:
WebAssembly.instantiate (بايت ، عمليات الاستيراد) -> الوعد بـ {module، example} (cache module to indexeddb)
مرة ثانية:
WebAssembly.instantiate (وحدة ، عمليات استيراد) -> وعد بـ {module ،ثيل}

أي اعتراضات على أن يكون هذا هو النمط الرئيسي؟

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

أفكار؟

mtrofin (حسنًا ، من الناحية الفنية ، فقط instantiate .)

lukewagner (أعتقد أن هذا ما يعنيه mtrofin )

lukewagner ، flagxor حسنًا ، لكننا نحتفظ بواجهة برمجة تطبيقات التجميع غير المتزامن ، أليس كذلك؟

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

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

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

نعم ، يجب أن يكون من الممكن (حتى تشجيع) تمرير Memory إلى التجميع.

mtrofin Right ، compile للاستخدامات المتقدمة. أفترض أن مثال البرنامج المساعد هو حالة صالحة حيث تريد _compile_ ، _ و_ لديك Memory ، لكنك لا تريد إنشاء مثيل (حتى الآن).

@ pizlonator Btw ، قصدت أن أسأل سابقًا ، بافتراض أن الاختراق "رمي إذا كان أكثر من 1000 خريطة سعة 4 جيجابايت لكل عملية" كافٍ لمعالجة مخاوف ASLR / الأمان ، فهل لا تزال هناك حاجة إلى الوضع البطيء / الوضع السريع بسبب النظام الأساسي قيود حصة العنوان الظاهري؟ لأنه إذا لم يكن هناك شيء ، فمن المؤكد أنه سيكون من الجيد إذا لم يكن هذا حتى اعتبارًا للأداء حتى للمستخدمين المتقدمين. (تبدو واجهات برمجة التطبيقات instantiate مفيدة للإضافة للأسباب الأخرى التي ذكرناها بالطبع.)

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

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

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

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

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

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

lukewagner أعتقد ذلك ، لأننا إذا

  • كنت قلقًا بشأن هجوم كان يحتاج إلى هذا السقف لينزل.
  • سأقلق بشأن التحسينات في مكان آخر في المكدس والتي تقلل من مقدار مساحة العنوان الافتراضية المتاحة لنا ، والتي تتطلب منا بعد ذلك إعادة تقييم ما إذا كان السقف منخفضًا بدرجة كافية.
  • سأقلق بشأن منع أنماط البرمجة التي تنشئ عن عمد آلاف الوحدات النمطية. على سبيل المثال ، أعلم أن معظم عملاء إطار عمل JavaScriptCore ينشئون جهاز افتراضي ، ويقومون ببعض الأعمال الصغيرة ، ثم يدمرونه. إذا تم استخدام WebAssembly بنفس الطريقة من JS مثل JSC من Objective-C ، فعندئذٍ لجعله يعمل على أنظمة 64 بت ، يجب أن يعرف GC أنه إذا قمت بتخصيص 1000 ذاكرة - حتى لو كانت كل منها صغيرة - فعليك GC في حالة نجاح التخصيص التالي على أساس أن تلك الذكريات الألف لا يمكن الوصول إليها الآن. إن القدرة على تخصيص ذكريات لا تحتوي على 4 غيغابايت من القرصنة بعد أن تكون هناك بالفعل ، على سبيل المثال ، 10 ذكريات لاختراق 4 غيغابايت مباشرة تعني أن GC لن تضطر إلى تغيير أساليبها التجريبية كثيرًا. لن يكون من الضروري القيام بـ GC عندما تخصص الوحدة 1001st في الحلقة-> run-> die loop. سيكون هذا مفيدًا للأنماط التي تستخدم ذاكرة صغيرة. أي شيء أقل من 1 ميغا بايت ، ومن المنطقي أن يكون لديك 1000 منها. يمكنني تخيل أشخاص يقومون بأشياء مفيدة في 64 كيلو بايت.
  • أنا قلق من أن يكون هذا أقل فائدة لسياقات JavaScript الأخرى. أريد ترك الباب مفتوحًا لعملاء JSC C API و Objective-C API للوصول إلى WebAssembly API من كود JS الخاص بهم. ربما يفضل هؤلاء العملاء حدًا صغيرًا لعدد الذكريات التي تبلغ 4 جيجابايت التي نخصصها. من المغري حتى جعل هذه الحصة قابلة للتكوين في مثل هذا السياق.

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

@ pizlonator Fair بما فيه الكفاية ، وهي واجهة برمجة تطبيقات أنظف / أبسط ، لذا أعتقد أنه من الجيد إضافتها.

بالنسبة إلى سبب عدم اهتمامي بهذه العناصر التي ذكرتها (في هذا الوقت):

  • قد يلزم رفع الحد ؛ هذا سهل.
  • في أي حد معقول ، سيتم استخدام جزء صغير فقط من إجمالي مساحة العنوان 64 بت ، لذلك لست على دراية بما هو متجه الهجوم هنا ؛ المحتوى المحدد له طرق عديدة ل OOM نفسها
  • نحن نتصدى لاستدلال GC بما يتناسب مع حجم الحجز ، وبالتالي يؤدي الانتقال من خلال Memory s فقط إلى GC أكثر عدوانية. المزيد من GC ليس رائعًا ، لكنني لست متأكدًا من أن هذا سيكون نمطًا شائعًا.

لكن من يدري ما سنراه في المستقبل ، لذلك أفترض أنه من المفيد أن تكون لديك المرونة المضمنة الآن.

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

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

يوم الجمعة ، 28 أكتوبر 2016 ، الساعة 2:15 صباحًا ، JF Bastien [email protected]
كتب:

نعم ، يجب أن يكون من الممكن (حتى يتم تشجيعه) لتمرير الذاكرة إلى
التحويل البرمجي.

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

-

أنت تتلقى هذا لأنك علقت.
قم بالرد على هذا البريد الإلكتروني مباشرة ، وقم بعرضه على GitHub
https://github.com/WebAssembly/design/issues/838#issuecomment -256805006 ،
أو كتم الخيط
https://github.com/notifications/unsubscribe-auth/ALnq1KXrUWaegRZwEhznmT1YcyI33IN9ks5q4T6TgaJpZM4Kh1gM
.

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

إذن ما الذي يتبقى لحل هذه المشكلة؟ شيء واحد هو تحديث http://webassembly.org/getting-started/js-api ، وهو ما يمكنني فعله. قد يكون الأمر الآخر هو أن يقوم Binaryen بإصدار هذا افتراضيًا (يبدو جيدًا @ kripken؟). titzer هل يطبق Canary WebAssembly.instantiate ؟

أي شيء آخر؟

lukewagner : لست متأكدًا مما تطلبه ،

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

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

kripken لست متأكدًا من فهمي: النهج الحالي هو عدم استخدام واجهة برمجة تطبيقات غير متزامنة على الإطلاق؟

نعم . راجع هذه المشكلة لإضافة أشياء غير متزامنة.

أعتقد أن drainJobQueue() وفي V8 أسمع أن هناك %RunMicroTasks() . يبدو أنه يمكنك ببساطة اختبار WebAssembly.instantiate واستخدامه عند التواجد بشكل افتراضي.

بالتأكيد ، ولكن أولاً ، قد يكون دعم Promise في أحدث node.js ، لكنه ليس في الإصدارات شائعة الاستخدام (الإصدار الافتراضي في توزيعات Linux على سبيل المثال). وثانيًا ، المشكلة الأكبر هي أنه عندما نصدر HTML ، فإننا نتحكم في كيفية تحميل الصفحة (يصدر emcc كود التحميل للمستخدم) بينما عندما نصدر JS ، يُفترض أن JS ينفذ خطيًا ، ويعتمد المستخدمون على ذلك ، على سبيل المثال يمكن أن يكون لديهم علامة نصية أخرى مباشرة بعد JS. في هذه الحالة ، يكتب المستخدم رمز التحميل الخاص به.

نتيجة لكليهما ، كما ذكرنا سابقًا ، يمكننا استخدام Promise APIs عند إرسال HTML (فأنت بالتأكيد لست في shell ولديك التحكم في التحميل) ، ولكن ليس عند إرسال JS. هناك يمكننا فقط توثيقه.

هل يوجد لدى Node إصدارات تدعم WebAssembly ولكنها لا تدعم Promise؟ هل يهتم الأشخاص Node بهذه الإصدارات؟

أنا لا أفهم شيء خط مستقيم JS. إذا كنت تعيد الوعد دائمًا ، ألن يعمل هذا فقط (يحتاج مستخدمو الكود إلى الوفاء بالوعد)؟

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

حول مشكلة الخط المستقيم: ينبعث emcc JS الذي يعد وقت التشغيل ويتصل بالكود المترجم. قد تستدعي بعض JS في علامة البرنامج النصي مباشرة بعد ذلك الرمز المترجم ، على سبيل المثال باستخدام

عقدة IMO مع WebAssembly ولكن بدون وعود ليست قيد تصميم يجب أن نقلق بشأنه. يعد polyfill to WebAssembly أمرًا سخيفًا جدًا في هذا السياق.

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

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

لماذا يعتبر polyfill to wasm سخيفًا على العقدة؟ لا يزال يبدو مفيدًا في هذا السياق ، حتى لو كان أقل من الحالات الأخرى :)

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

هل هذا يعالج مخاوفك؟

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

""

""

doSomething يحتاج Module.my_func في الوجود. إذا أعاد output.js الوعد للتو ، فهذا يعني أنه غير موجود بعد. لذلك سيكون هذا تغييرًا جذريًا.

هل هذا منطقي الآن؟

لماذا يعتبر polyfill to wasm سخيفًا على العقدة؟ لا يزال يبدو مفيدًا في هذا السياق ، حتى لو كان أقل من الحالات الأخرى :)

إن polyfill to wasm ليس سخيفًا. تقديم الطعام إلى تثبيتات Node التي لا تحتوي على wasm ، وقم بتعويضها ، وليس لديها وعد ولكن لا تقوم بإكمال ذلك ، أمر سخيف. إنه نصف مؤكد. يجب أن يحصلوا على النصف الآخر من الحمار 😁

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

هل هذا يعالج مخاوفك؟

حسنا هذا جيد! طالما أن معظم صفحات الويب تستخدم API الوعد ، فأنا سعيد.

[قص]

هل هذا منطقي الآن؟

نعم فعلا. شكرا للتوضيح.

من وجهة نظري ، على الرغم من ذلك ، لم يعد Emscripten يعمل فقط في إصدار JS بعد الآن! مثالك منطقي بالنسبة لرموز Ye Olden ، لكن الأشياء الجديدة يجب أن تفترض وعود IMO.

راجع للشغل ، نظرت إلى تبديل webassembly.org/demo لاستخدام instantiate ومن الصعب بعض الشيء أن يحدث new Instance المتزامن الحالي في سياق يريد نتيجة متزامنة. لذلك بمجرد تحديث Binaryen لإصدار instantiate افتراضيًا ، سيكون من الجيد إعادة إنشاء عرض AngryBots من البداية.

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

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

نظرًا للجوانب السلبية المحتملة لعدم استخدام WebAssembly.instantiate API ، أعتقد أنه من الجدير أن نطلب منهم التفكير في استخدامه.

هل هذه السلبيات موثقة؟ ستكون الإرشادات الواضحة حول هذا الأمر على موقع الويب الرئيسي أو صفحة emscripten wasm wiki أمرًا مناسبًا لتوجيه الأشخاص إليها.

لقد قمت للتو بقراءة هذه المشكلة الطويلة بنفسي ، ولم أفهم الجوانب السلبية بعد ، لذلك أريد أن أقرأ ذلك أيضًا :)

kripken التحدي مع الكود الحالي هو أن binaryen / emscripten يوفر فقط الواردات الضرورية (مطلوبة كوسيطات لـ instantiate ) في نفس الوقت الذي تكون فيه الصادرات مطلوبة بشكل متزامن. إذا كان من الممكن توفير عمليات الاستيراد "مقدمًا" ، فمن السهل جدًا وضع WebAssembly.instantiate في ذيل XHR غير المتزامن (كما فعلت في العرض التوضيحي الحالي مع compile المتزامن رأيته ، فإن تصميم AngryBots الحالي لدينا هو دون المستوى الأمثل ويحتاج إلى تحديث على أي حال.

أوه ، لم أفهم أن توفير الواردات قبل بدء wasm XHR هو المفتاح هنا. هذا أكثر تعقيدًا بعد ذلك. لذا فإن معظم ما قلته من قبل خاطئ.

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

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

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

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

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

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

توقيع instantiate هو WebAssembly.instantiate(bytes, importObj) ، لذلك لإطلاق الترجمة غير المتزامنة + إنشاء مثيل ، تحتاج إلى تمرير importObj .

أثناء التحدث دون اتصال بالإنترنت ، أعجبني

  1. توفير الذاكرة عند التجميع.
  2. توفير كافة الواردات عند التجميع (مجموعة شاملة من السابق).
  3. القيام بكل هذا بشكل غير متزامن.

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

لكن بعض الخيارات الأخرى سهلة الاستخدام بشكل تافه:

  • يتطلب 1 + 3 واجهة برمجة تطبيقات جديدة مثل instantiate(bytes, Memory) -> Promise . السبب في سهولة استخدامه هو أنه يمكن إنشاء الذاكرة مبكرًا على أي حال (في حين أن جميع الواردات الأخرى تقريبًا هي وظائف JS ، والتي لا يمكننا الحصول عليها في وقت مبكر).
  • 2 في حد ذاته ، بدون 3 ، على سبيل المثال ، new Instance(bytes, imports) . وهذا يعني ، التجميع المتزامن للبيانات الثنائية + الواردات. السبب في سهولة استخدام هذا هو أن الكود الحالي لدينا يقوم بهذا: instance = new WebAssembly.Instance(new WebAssembly.Module(getBinary()), imports) لذلك سنقوم بإدراج ذلك في استدعاء واحد لواجهة برمجة التطبيقات.

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

أقترح كائنات التعريف التي تصف الواردات (الذاكرة) لكسر القيد الذي يجب تخصيص الواردات قبل التجميع. ثم قد يؤدي الأسلوب instantiate حدوث خطأ إذا كانت الذاكرة المتوفرة لا تتطابق مع الذاكرة المتوقعة ولن تتأخر في إعادة التجميع.

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

هذا شيء تم اقتراحه حسب الضرورة في بداية هذا المشروع منذ عدة سنوات الآن!

kripken بينما المؤكد أنها يجب أن تكون المسار غير الموصى به وإلا سنقدم أطنانًا من الرسائل غير الضرورية غير الضرورية ، وهو انحدار مقارنة بـ asm.js +

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

دعنا نصغير ونتحدث عن تجربة المستخدم لثانية واحدة.


فيما يلي مقارنة بين تحميل العرض التوضيحي لـ AngryBots بشكل غير متزامن (عبر asm.js) ، يسارًا ، ومتزامنًا (عبر WebAssembly في V8) ، يمينًا.

comparison

يوفر التجميع المتزامن تجربة مستخدم رهيبة ويكسر أشرطة التقدم أو أي مؤشر مرئي آخر لتحميل التطبيق.

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

نحتاج إلى تشجيع WebAssembly.compile & WebAssembly.instantiate بشكل صريح وعدم تشجيع new WebAssembly.Module & new WebAssembly.Instance .


دعونا نتعمق قليلاً ونرى مدى سوء شريط التقدم على اليمين ، بالنسبة لـ WebAssembly.

إليك أثر تم التقاطه باستخدام لوحة أداء DevTools:

screen shot 2016-12-28 at 1 26 59 pm

يستغرق الأمر 30 ثانية على جهاز MacBook Air لإظهار أي شريط تقدم على الإطلاق.

ما الذي يستغرق هذا الوقت؟ لنقترب من 20 ثانية تقريبًا بعد تنزيل وحدة wasm عندما يكون الخيط الرئيسي مغلقًا تمامًا:

screen shot 2016-12-28 at 2 18 36 pm

يستغرق التجميع حوالي 20 ثانية ويستغرق إنشاء مثيل ثانيتين تقريبًا.

لاحظ أنه في هذه الحالة ، يقوم مُحمل Unity بالفعل باستدعاء WebAssembly.compile غير المتزامن إذا كان مدعومًا ، لذا فإن العشرينات هي لأن V8 لا يزال يقوم بتجميع متزامن تحت الغطاء. سم مكعبtitzerflagxor هذا شيء V8 يحتاج حقا إلى الإصلاح.

يرجع سبب خطأ إنشاء مثيل 2s إلى رمز أداة تحميل الوحدة التي تستدعي المتزامن new WebAssembly.Instance . هذا ما نحتاجه حقًا لإصلاحه في كل من Unity code و Emscripten.


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

(إذا كنت ترغب في استكشاف التتبع بمزيد من التفاصيل ، يمكنك عرض الجدول الزمني الكامل هنا: https://chromedevtools.github.io/timeline-viewer/ ؟loadTimelineFromURL=https://www.dropbox.com/s/ noqjwql0pq6c1wy / wasm؟ dl = 0)

أوافق بنسبة 100٪ على أن عدم المزامنة أمر رائع :) لكنني أقول أنه أمر متعامد مع تحسين الحصول على الذاكرة في نفس الوقت الذي يتم فيه تجميع الوحدة النمطية. وأنه لا يمكننا الحصول على هذا التحسين غير المتزامن بشكل تافه - يمكننا الحصول على هذا التحرير والسرد ، ولكن إما على حساب بعض النفقات العامة ، أو على حساب الوقت إذا قدمنا ​​علامة جديدة له ووجدنا طريقة لتطبيقه على مراحل ليكون افتراضيًا .

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

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

kripken ، أعتقد أنك توصلت إلى استنتاجات مختلفة عما لدي ، و lukewagner و @ s3thompson لأن الجزء الأكثر أهمية بالنسبة لك هو تقديم انتقال سلس من asm.js للمطورين الحاليين.

هل هذا صحيح؟

أوافق على أن هذا مصدر قلق صحيح. أزنها أقل لأن IMO مع WebAssembly نجلب معه مطورين أكثر من asm.js. أرغب في تجنب حرق المستخدمين الأوائل ، لكن مطوري IIUC الحاليين مرنون جدًا ويريدون تجميعًا غير متزامن.

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

لقد أعربت في وقت سابق عن قلقك بشأن حجم العمل الذي ينطوي عليه جانب Emscripten لدعم هذا. هل ما زلت تعتقد أن هذه مشكلة؟

FWIW ، ستستخدم الوحدة 5.6 WebAssembly.instantiate.

جوناس

في 28 كانون الأول (ديسمبر) 2016 ، الساعة 11:42 مساءً ، كتب Seth Thompson [email protected] :

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

دعنا نصغير ونتحدث عن تجربة المستخدم لثانية واحدة.

فيما يلي مقارنة بين تحميل عرض AngryBots بالمكالمات غير المتزامنة (عبر asm.js) والمكالمات اليسرى والمتزامنة (تنفيذ WebAssembly الحالي) ، على اليمين.

يوفر التجميع المتزامن تجربة مستخدم رهيبة ويكسر أشرطة التقدم أو أي مؤشر مرئي آخر لتحميل التطبيق.

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

نحن بحاجة إلى تشجيع WebAssembly.compile و WebAssembly بشكل صريح. فرض وتثبيط WebAssembly.Module الجديد و WebAssembly.Instance الجديد.

دعونا نتعمق قليلاً ونرى مدى سوء شريط التقدم على اليمين ، بالنسبة لـ WebAssembly.

إليك أثر تم التقاطه باستخدام لوحة أداء DevTools:

يستغرق الأمر 30 ثانية على جهاز MacBook Air لإظهار أي شريط تقدم على الإطلاق.

ما الذي يستغرق هذا الوقت؟ لنقترب من 20 ثانية تقريبًا بعد تنزيل وحدة wasm عندما يكون الخيط الرئيسي مغلقًا تمامًا:

يستغرق التجميع حوالي 20 ثانية ويستغرق إنشاء مثيل ثانيتين تقريبًا.

لاحظ أنه في هذه الحالة ، يقوم مُحمل Unity بالفعل باستدعاء WebAssembly.compile غير المتزامن إذا كان مدعومًا ، لذا فإن العشرينات هي لأن V8 لا يزال يقوم بعمل ترجمة متزامنة تحت الغطاء. سم مكعبtitzerflagxor هذا شيء V8 يحتاج حقا إلى الإصلاح.

يرجع سبب خطأ إنشاء مثيل 2s إلى رمز محمل Unity الذي يستدعي WebAssembly الجديد المتزامن. هذا ما نحتاجه حقًا لإصلاحه في كل من Unity code و Emscripten.

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

(إذا كنت ترغب في استكشاف التتبع بمزيد من التفاصيل ، يمكنك عرض الجدول الزمني الكامل هنا: https://chromedevtools.github.io/timeline-viewer/ ؟loadTimelineFromURL=https://www.dropbox.com/s/ noqjwql0pq6c1wy / wasm؟ dl = 0)

-
أنت تتلقى هذا لأنه تم ذكرك.
قم بالرد على هذه الرسالة الإلكترونية مباشرةً ، أو اعرضها على GitHub ، أو قم بكتم صوت الموضوع.

jfbastien ربما لا أفهم ما تعنيه "الاستنتاجات". أنا في الغالب أقدم فقط خيارات هنا. ليس لدي استنتاج بنفسي.

إذا أردنا اختيار Memory-at-Compile-time في الوقت الحالي ، فقد اقترحت بعض الخيارات التي يمكن أن تسمح لنا بالحصول عليها في أسرع وقت ممكن ، وتعديل تجميع المزامنة الحالي بشكل بسيط.

أو إذا أردنا اختيار ذلك الآن بطريقة غير متزامنة ، فقد اقترحت خيارًا ("1 + 3" ، أي عدم تلقي جميع الواردات في وقت التجميع ، فقط الذاكرة) التي يمكن أن تتيح لنا الحصول عليها في أسرع وقت ممكن أيضًا.

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

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

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

للتأكد من فهمي:

  1. ما هي النفقات العامة؟

    • هل هذه النفقات العامة متأصلة في Async + Memory-at-compile-time ، أم أنها قيود تنفيذ يمكن إصلاحها لاحقًا؟ إذا كانت IMO متأصلة في A + M ، فيجب علينا إصلاح API في أسرع وقت ممكن.

    • IIUC النفقات العامة هي شيء مؤقت سواء على الواردات أو الصادرات ، وليست متأصلة في A + M ، هل هذا صحيح؟ هل يمكنك تفصيل هذا قليلا؟

  2. أي المستخدمين نتحدث عن كسر؟ مستخدمو asm.js الذين يريدون نفس الرمز لاستهداف wasm أيضًا؟

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

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

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

أنه ليس لدينا استيراد JS حتى يصبح JS جاهزًا (ولكن لدينا ذاكرة!)

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

حول المستخدمين المنفصلين: إذا قدمنا ​​مسار ترحيل بسيطًا (مثل حدث / وعد "onload") ، فيجب أن يكون ترحيل المستخدمين أمرًا سهلاً ، مع اعتبار الجزرة هي كل المكاسب الرئيسية للأداء. لا أعتقد أن لدينا أي دليل على أن backcompat مصدر asm.js الدقيق هو مطلب صعب للتكوين الافتراضي ؛ لدينا العديد من الأمثلة على العكس تمامًا: المستخدمون على استعداد لفعل أي شيء لتحقيق الكمال الأمثل لأن هذا هو ، بالطبع ، بيت القصيد.

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

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

@ kripken عظيم! قد يكون من المفيد أن يكون لديك رسم تخطيطي يوضح مثيلات مختلفة / JS / import / export / memory / table. هل تريد نقل هذه المناقشة إلى مكان آخر (Emscripten / binaryen repo)؟ لدي صورة ذهنية لما أعتقد أنه يجب تنظيم كود C ++ فيه ، ولكن من الواضح الآن أنه ليس لديك نفس الصورة! لديك المزيد من الخبرة هناك ، لذلك أود أن أتعلم منها وأن أساعد بقدر ما أستطيع.

jfbastien : بالتأكيد. لست واضحًا بعد بشأن ما تبحث عنه في الرسم التخطيطي ، ولكن نعم ، ربما يكون مكان آخر أفضل. لتنفيذ هذا في emscripten ، هناك المشكلة المذكورة من قبل ، https://github.com/kripken/emscripten/issues/4711 ، لا تتردد أيضًا في فتح أخرى إذا كان ذلك لا يغطي ما تريد.

يستخدم IIUC Emscripten هذا افتراضيًا الآن. إغلاق.

لمتابعة تعليق @ s3thompson ، لاحظ أن التجميع المتزامن وإنشاء مثيل مفيد. والجدير بالذكر ، أنني واجهت مؤخرًا موقفًا أردت فيه تحميل وحدة WebAssembly وتجميعها بشكل متزامن في Node.js ( v7.7.2 ). إذا كانت واجهات برمجة التطبيقات (API) التي تقدم وعودًا متاحة فقط ، فهذا يعني أنني لن أتمكن من توفير تصدير متزامن.

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

kgryte كان يجب أن أوضح أن تعليقي يتعلق في المقام الأول بالمتصفح كسياق تنفيذ. لقد وصلنا إلى سطح API لا يزال يعرض واجهات برمجة التطبيقات المتزامنة. قد تفرض المتصفحات حدًا للحجم على الوحدات التي تم تمريرها إلى واجهات برمجة التطبيقات المتزامنة (Chrome يفعل ذلك بالفعل ، على سبيل المثال) ، ولكن هذا الحد قابل للتكوين بواسطة أداة التضمين ولا يجب تطبيقه على Node.

@ s3ththompson شكرا للتوضيح.

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

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

bguiz picture bguiz  ·  93تعليقات

ngzhian picture ngzhian  ·  41تعليقات

dcodeIO picture dcodeIO  ·  48تعليقات

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

autumnontape picture autumnontape  ·  38تعليقات