جاء هذا أثناء مناقشة مع صديقي حول العودية. لماذا لا نبني
طريقة Javascript JSON.stringify كتمرين برمجة متكرر؟ يبدو وكأنه عظيم
فكرة.
قمت بصياغة الإصدار الأول بسرعة. وكان أداؤه فظيعًا! ال
الوقت المطلوب كان حوالي 4 أضعاف الوقت المطلوب في المعيار JSON.stringify.
function json_stringify(obj) { if (typeof obj == "number" || typeof obj == "boolean") { return String(obj); } if (typeof obj == "string") { return `"${obj}"`; } if (Array.isArray(obj)) { return "[" obj.map(json_stringify).join(",") "]"; } if (typeof obj === "object") { const properties_str = Object.entries(obj) .map(([key, val]) => { return `"${key}":${json_stringify(val)}`; }) .join(","); return "{" properties_str "}"; } }
من خلال تشغيل ما يلي، يمكننا أن نرى أن json_stringify الخاص بنا يعمل كـ
مُتوقع.
const { assert } = require("console"); const test_obj = { name: "John Doe", age: 23, hobbies: ["football", "comet study"] }; assert(json_stringify(test_obj) === JSON.stringify(test_obj))
لاختبار المزيد من السيناريوهات، وعمليات التشغيل المتعددة للحصول على فكرة متوسطة عن كيفية عملنا
عند تشغيل البرنامج النصي، قمنا بإنشاء برنامج نصي اختباري بسيط!
function validity_test(fn1, fn2, test_values) { for (const test_value of test_values) { assert(fn1(test_value) == fn2(test_value)); } } function time(fn, num_runs = 1, ...args) { const start_time = Date.now() for (let i = 0; iبتشغيل هذا نحصل على التوقيتات كما يلي.
Testing 1000 times Std lib JSON.stringify() took 5 ms Custom json_stringify() took 20 ms Testing 10000 times Std lib JSON.stringify() took 40 ms Custom json_stringify() took 129 ms Testing 100000 times Std lib JSON.stringify() took 388 ms Custom json_stringify() took 1241 ms Testing 1000000 times Std lib JSON.stringify() took 3823 ms Custom json_stringify() took 12275 msقد يتم تشغيله بشكل مختلف على أنظمة مختلفة ولكن نسبة الوقت المستغرق
بواسطة std JSON.strngify إلى json_stringify المخصص لدينا يجب أن يكون حول
1:3 - 1:4قد يكون الأمر مختلفًا أيضًا في حالة مثيرة للاهتمام. تابع القراءة لمعرفة المزيد عن
الذي - التي!تحسين الأداء
أول شيء يمكن إصلاحه هو استخدام وظيفة الخريطة. يخلق
مجموعة جديدة من القديمة. في حالتنا للكائنات، يتم إنشاء مصفوفة من
خصائص كائن JSON من المصفوفة التي تحتوي على إدخالات الكائن.يحدث شيء مماثل أيضًا مع تقييد عناصر المصفوفة أيضًا.
علينا تكرار العناصر الموجودة في المصفوفة، أو إدخالات الكائن! لكن
يمكننا تخطي إنشاء مصفوفة أخرى فقط للانضمام إلى أجزاء JSON المربوطة.إليك الإصدار المحدث (فقط الأجزاء التي تم تغييرها معروضة للإيجاز)
function json_stringify(val) { if (typeof val === "number" || typeof val === "boolean") { return String(val); } if (typeof val === "string") { return `"${val}"`; } if (Array.isArray(val)) { let elements_str = "[" let sep = "" for (const element of val) { elements_str = sep json_stringify(element) sep = "," } elements_str = "]" return elements_str } if (typeof val === "object") { let properties_str = "{" let sep = "" for (const key in val) { properties_str = sep `"${key}":${json_stringify(val[key])}` sep = "," } properties_str = "}" return properties_str; } }وإليك مخرجات البرنامج النصي للاختبار الآن
Testing 1000 times Std lib JSON.stringify() took 5 ms Custom json_stringify() took 6 ms Testing 10000 times Std lib JSON.stringify() took 40 ms Custom json_stringify() took 43 ms Testing 100000 times Std lib JSON.stringify() took 393 ms Custom json_stringify() took 405 ms Testing 1000000 times Std lib JSON.stringify() took 3888 ms Custom json_stringify() took 3966 msيبدو هذا أفضل كثيرًا الآن. يستغرق json_stringify المخصص لدينا 3 مللي ثانية فقط
أكثر من JSON.stringify لتضييق نطاق كائن متداخل بعمق 10000 مرة.
وعلى الرغم من أن هذا ليس مثاليًا، إلا أنه تأخير مقبول.تضغط أكثر؟؟
قد يكون التأخير الحالي بسبب إنشاء السلسلة وتسلسلها بالكامل
هذا يحدث. في كل مرة نقوم بتشغيل Elements_str = sep json_stringify(element)
نحن نقوم بتسلسل 3 سلاسل.ربط السلاسل مكلف لأنه يتطلب
- إنشاء مخزن مؤقت جديد للسلسلة ليناسب السلسلة المدمجة بالكامل
- نسخ السلاسل الفردية إلى المخزن المؤقت المنشأ حديثًا
باستخدام المخزن المؤقت بأنفسنا وكتابة البيانات مباشرة هناك قد يمنحنا
تحسين الأداء. نظرًا لأنه يمكننا إنشاء مخزن مؤقت كبير (على سبيل المثال 80 حرفًا)
ثم قم بإنشاء مخازن مؤقتة جديدة لتناسب 80 حرفًا أكثر عند نفادها.لن نتجنب إعادة تخصيص/نسخ البيانات تمامًا، ولكننا سنفعل
الحد من تلك العمليات.التأخير المحتمل الآخر هو العملية العودية نفسها! على وجه التحديد
استدعاء الوظيفة الذي يستغرق وقتا. خذ بعين الاعتبار استدعاء وظيفتنا json_stringify(val)
الذي يحتوي على معلمة واحدة فقط.فهم استدعاءات الوظائف
الخطوات ستكون
- ادفع عنوان الإرجاع إلى المكدس
- ادفع مرجع الوسيطة إلى المكدس
- في الوظيفة المطلوبة
- أخرج مرجع المعلمة من المكدس
- أخرج عنوان الإرجاع من المكدس
- ادفع القيمة المرجعة (الجزء المقيد) إلى المكدس
- في وظيفة الاتصال
- احذف القيمة التي ترجعها الدالة من المكدس
تحدث كل هذه العمليات لضمان حدوث استدعاءات الوظائف وهذا يضيف وحدة المعالجة المركزية
التكاليف.إذا قمنا بإنشاء خوارزمية غير متكررة لـ json_stringify كل هذه العمليات
المذكورة أعلاه لاستدعاء الوظيفة (مرات عدد هذه المكالمات) ستكون
تم تخفيضه إلى لا شيء.يمكن أن تكون هذه محاولة مستقبلية.
اختلافات إصدار NodeJs
شيء أخير يجب ملاحظته هنا. خذ بعين الاعتبار الإخراج التالي للبرنامج النصي للاختبار
Testing 1000 times Std lib JSON.stringify() took 8 ms Custom json_stringify() took 8 ms Testing 10000 times Std lib JSON.stringify() took 64 ms Custom json_stringify() took 51 ms Testing 100000 times Std lib JSON.stringify() took 636 ms Custom json_stringify() took 467 ms Testing 1000000 times Std lib JSON.stringify() took 6282 ms Custom json_stringify() took 4526 msهل كان أداء json_stringify المخصص لدينا أفضل من معيار NodeJs
JSON.stringify؟؟؟حسنا نعم! ولكن هذا إصدار أقدم من NodeJs (الإصدار 18.20.3). تبين، ل
هذا الإصدار (وربما أقل أيضًا) يعمل لدينا json_stringify المخصص
أسرع من المكتبة القياسية!تم إجراء جميع الاختبارات لهذه المقالة (باستثناء هذا الاختبار الأخير) باستخدام
العقدة v22.6.0لقد زاد أداء JSON.stringify من الإصدار 18 إلى الإصدار 22. هذا عظيم جدًا
من المهم أيضًا ملاحظة أن أداء البرنامج النصي الخاص بنا كان أفضل في NodeJs v22.
وهذا يعني أن NodeJs قد زادت من الأداء العام لوقت التشغيل أيضًا.
من المحتمل أن يكون قد حدث تحديث للمحرك الأساسي V8 نفسه.حسنًا، لقد كانت هذه تجربة ممتعة بالنسبة لي. وأتمنى أن يكون كذلك
أنت أيضاً. وفي خضم كل هذه المتعة، تعلمنا شيئًا أو اثنين!واصل البناء، استمر في الاختبار!
تنصل: جميع الموارد المقدمة هي جزئيًا من الإنترنت. إذا كان هناك أي انتهاك لحقوق الطبع والنشر الخاصة بك أو الحقوق والمصالح الأخرى، فيرجى توضيح الأسباب التفصيلية وتقديم دليل على حقوق الطبع والنشر أو الحقوق والمصالح ثم إرسالها إلى البريد الإلكتروني: [email protected]. سوف نتعامل مع الأمر لك في أقرب وقت ممكن.
Copyright© 2022 湘ICP备2022001581号-3