01
READY يفصل بين حالتين.
ينتظر READY الجديد اكتمال المهام السابقة قبل تحديث حالة الخوادم. تبدأ الأحداث التالية بعد ذلك، فلا تستطيع المهام القديمة الكتابة فوق الحالة الجديدة.
خلف كواليس Fjord
بوت مكتوب بلغة Rust، ومحرك رسوميات نطوره داخليًا، إلى جانب الأطر والمكتبات وقواعد البيانات التي يعتمد عليها Fjord.
نوضح هنا ما نطوره بأنفسنا والتقنيات التي تجتمع في Fjord.
Fjord
يعالج Fjord أحداث Discord بالترتيب وينفّذ المهام المستقلة بالتوازي. يربط Twilight البوت بـ Discord ويُبقي بيانات الخوادم متاحة محليًا. يخزّن Dragonfly الأحداث المعلّقة ويدعم تنسيق اتصالات البوابة.
01
ينتظر READY الجديد اكتمال المهام السابقة قبل تحديث حالة الخوادم. تبدأ الأحداث التالية بعد ذلك، فلا تستطيع المهام القديمة الكتابة فوق الحالة الجديدة.
02
تبدأ أحداث الخادم نفسه حسب ترتيب وصولها. وينتظر كل حدث انتهاء سابقه حتى لا تتجاوز تغييرات الخادم بعضها بعضًا.
03
يميّز موزّع المهام بينها بواسطة مفاتيح. يمكن لخوادم مختلفة العمل معًا، ولا تنتظر إلا المهام التي تحمل المفتاح نفسه.
04
تصل الرسالة نفسها إلى AutoMod وسجل النشاط في الوقت نفسه. ويعالجها كل منهما بشكل منفصل لأداء مهمته.
05
تُخزّن أحداث Discord المعلّقة وبياناتها في Dragonfly. ويستخدم AutoMod وسجلات النشاط هذا المخزن المشترك للحالات المؤقتة أيضًا. ويظل البوت مسؤولًا عن تنفيذ المهام.
06
عندما يتطابق مرشح AutoMod مفعّل، يتوقف فحص الرسالة. ولا تُطلق المرشحات الأخرى إجراء إشراف ثانيًا للحدث نفسه.
07
يُبقي Twilight بيانات الخوادم والأعضاء والأدوار والقنوات والرموز التعبيرية وحالات الحضور والصوت محدّثة في الذاكرة. ولا تُخزّن الرسائل في هذه الذاكرة المؤقتة.
08
تُجدول التفاعلات بشكل مستقل عن أحداث الخوادم. ويحدّد READY حدود الحالة داخل كل اتصال بالبوابة.
09
ينسّق Dragonfly مسؤولية كل شارد، أي كل اتصال بالبوابة. وبعد انتقال المسؤولية، لا يمكن للمالك السابق استلام أحداث أخرى أو إكمالها.
01 / تطويرنا الخاص
Fjell هو محرك الرسومات الخاص بنا والمكتوب بلغة Rust. يجمع الخلفيات والصور الرمزية والنصوص في بطاقات ترحيب شخصية.
أردنا التحكم في كيفية إنشاء هذه الصور. لذلك طورنا حلاً يناسب احتياجات Fjord ويمنحنا حرية التصميم.
ولا تقل كفاءة التكلفة أهمية عن ذلك. يقدم Fjell أعلى أداء من دون التضحية بالجودة، مع استخدام المعالج والذاكرة بأكبر قدر ممكن من الكفاءة أثناء التوليد. وهذا يخفض تكاليف الخوادم لدينا بشكل كبير.
يمتد تطويرنا إلى معالجة البكسلات. تستخدم حلقات SIMD التي كتبناها تقنيات AVX2 وFMA وBMI1/BMI2 لحساب عدة بكسلات بالتوازي.
قياس الأداء
أربعة مستويات للحمل مع تغييرات مضبوطة للبطاقات وإعداد اختبار واحد.
| التوازي | بطاقة/ث | بطاقة/د | متوسط التصيير | التصيير P50 | التصيير P95 | التصيير P99 | المتوسط الكلي | الإجمالي P50 | الإجمالي P95 | الإجمالي P99 | متوسط CPU | متوسط RAM |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 797,48 | 47.849 | 1,062 ms | 1,061 ms | 1,226 ms | 1,242 ms | 1,253 ms | 1,251 ms | 1,428 ms | 1,473 ms | 88,3 % | 381,2 MiB |
| 2 | 1.577,95 | 94.677 | 1,038 ms | 1,004 ms | 1,225 ms | 1,421 ms | 1,266 ms | 1,236 ms | 1,470 ms | 1,715 ms | 173,5 % | 360,1 MiB |
| 4 | 3.173,00 | 190.380 | 1,023 ms | 1,011 ms | 1,188 ms | 1,230 ms | 1,259 ms | 1,243 ms | 1,448 ms | 1,557 ms | 344,9 % | 375,3 MiB |
| 8 | 5.850,25 | 351.015 | 1,050 ms | 1,026 ms | 1,194 ms | 1,290 ms | 1,366 ms | 1,349 ms | 1,578 ms | 1,803 ms | 647,0 % | 385,8 MiB |
معدل المعالجة المقاس مقارنة بالتوسع الخطي المثالي.
| العمّال | المقاس | الخطي المثالي | التوسع | الكفاءة |
|---|---|---|---|---|
| 1 | 797,48 | 797,48 | 1,00× | 100,0 % |
| 2 | 1.577,95 | 1.594,96 | 1,98× | 98,9 % |
| 4 | 3.173,00 | 3.189,92 | 3,98× | 99,5 % |
| 8 | 5.850,25 | 6.379,84 | 7,34× | 91,7 % |
استمرت الاختبارات المحلية الأربعة 60 ثانية لكل منها على AMD Ryzen 9 9950X. استُخدمت 100 خلفية خفيفة بألوان عادية أو رسومات توضيحية وبأحجام ملفات من نحو 100 إلى 300 كيلوبايت، وعادة قرابة 200 كيلوبايت. بقيت الطبقة السائلة معطلة والخط ثابتًا؛ وتغيرت بين البطاقات ألوان النص والدائرة ومواضع المظللات الخاصة بهما.
يشمل زمن التصيير إنشاء الصورة وترميز PNG وضغطها حتى اكتمال ملف PNG النهائي. لا يشمل نقل الشبكة أو زمن التنزيل.
استخدم مولد الحمل 1 أو 2 أو 4 أو 8 طلبات متوازية حسب الاختبار. لم يبدأ طلب جديد إلا بعد استلام ملف PNG السابق كاملًا والتحقق منه. نشأ استخدام CPU المعروض تحت هذا الحمل تحديدًا. استطاع محرك الرسومات توزيع العمل على عدة أنوية.
* قياسات داخلية غير متحقق منها بصورة مستقلة ضمن الظروف الموضحة. لا تمثل خاصية مضمونة أو ضمانًا أو التزامًا بالأداء. قد يختلف الأداء الفعلي حسب النظام والحمل والبيئة.
اختبار عشوائي مكثف
إعداد أكثر تنوعًا بكثير يضم 1,000 خلفية و237 خطًا وتأثيرات عشوائية لكل طلب.
| التوازي | بطاقة/ث | بطاقة/د | متوسط التصيير | التصيير P50 | التصيير P95 | التصيير P99 | المتوسط الكلي | الإجمالي P50 | الإجمالي P95 | الإجمالي P99 | متوسط CPU | متوسط RAM |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 92,65 | 5.559 | 9,775 ms | 10,478 ms | 12,781 ms | 13,401 ms | 10,788 ms | 11,553 ms | 14,006 ms | 14,784 ms | 93,6 % | 1.205,6 MiB |
| 2 | 184,53 | 11.072 | 9,944 ms | 10,621 ms | 12,858 ms | 13,550 ms | 10,832 ms | 11,576 ms | 13,938 ms | 14,698 ms | 189,1 % | 1.278,8 MiB |
| 4 | 358,82 | 21.529 | 10,209 ms | 10,855 ms | 13,240 ms | 13,997 ms | 11,138 ms | 11,857 ms | 14,363 ms | 15,212 ms | 377,7 % | 1.300,9 MiB |
| 8 | 660,52 | 39.631 | 10,897 ms | 11,610 ms | 14,343 ms | 15,336 ms | 12,101 ms | 12,889 ms | 15,838 ms | 16,880 ms | 744,8 % | 1.308,6 MiB |
معدل المعالجة المقاس مقارنة بالتوسع الخطي المثالي.
| العمّال | المقاس | الخطي المثالي | التوسع | الكفاءة |
|---|---|---|---|---|
| 1 | 92,65 | 92,65 | 1,00× | 100,0 % |
| 2 | 184,53 | 185,30 | 1,99× | 99,6 % |
| 4 | 358,82 | 370,60 | 3,87× | 96,8 % |
| 8 | 660,52 | 741,20 | 7,13× | 89,1 % |
استمرت هذه الاختبارات المحلية الأربعة 60 ثانية لكل منها على جهاز AMD Ryzen 9 9950X نفسه. اختار كل طلب من 1,000 خلفية أكثر تعقيدًا بأحجام من 800 كيلوبايت إلى 2.4 ميغابايت ومن 237 خطًا. وتغيرت النصوص والشفافية وأحجام الخط والصورة الرمزية والإطار وألوان النص والدائرة وزاوية المظللات وقوتها وكثافتها. وفُعّلت الطبقة السائلة في نحو نصف البطاقات أيضًا مع لون وشفافية وتمويه عشوائي.
استخدم مولد الحمل 1 أو 2 أو 4 أو 8 عمال متوازيين في حلقة مغلقة. لم يبدأ كل عامل طلبه التالي إلا بعد استلام ملف PNG السابق كاملًا والتحقق منه. انتهت جميع اختبارات الـ60 ثانية دون أخطاء أو انتهاء مهلة أو ملفات PNG غير صالحة.
يشمل زمن التصيير إنشاء الصورة وترميز PNG وضغطها حتى اكتمال ملف PNG النهائي. لا يشمل نقل الشبكة أو زمن التنزيل.
* قياسات داخلية غير متحقق منها بصورة مستقلة ضمن الظروف الموضحة. لا تمثل خاصية مضمونة أو ضمانًا أو التزامًا بالأداء. قد يختلف الأداء الفعلي حسب النظام والحمل والبيئة.
02 / أساسنا التقني
إلى جانب محركنا الخاص نستخدم Rust وLeptos وTypeScript وVue وTwilight وDragonfly وPostgreSQL وScyllaDB وRustFS. لكل تقنية دور واضح داخل النظام.
لغة البرمجة
تشكّل Rust أساس بوت Discord والواجهة الخلفية ومحرر البطاقات ومحرك الرسوميات Fjell لدينا.
إطار ويب
نستخدم Leptos في أجزاء من واجهة الويب. يتيح لنا الإطار استخدام Rust في المتصفح ويتكامل بصورة طبيعية مع بقية تقنياتنا.
لغة البرمجة
نكتب الصفحات العامة التفاعلية باستخدام TypeScript. يساعد فحص الأنواع على الحفاظ على اتساق المكونات والحالة.
شعار TypeScript الرسمي. يُستخدم وفق إرشادات العلامة التجارية لـ TypeScript.
إطار ويب
يشكّل Vue مكونات الموقع العام، من التنقل والتوثيق إلى الأجزاء التفاعلية الأخرى، لتبقى الواجهة سهلة الصيانة والتطوير.
الشعار © Evan You. CC BY-NC-SA 4.0 · دون تعديل
مكتبة لمنصة Discord
نستخدم Twilight للاتصال بمنصة Discord. تربط هذه المكتبة البوت المكتوب بلغة Rust بمنصة Discord.
الشعار من Fezhoof. CC BY-SA 4.0 · دون تعديل
قاعدة البيانات
Dragonfly هو مخزننا المشترك للبيانات المؤقتة لأحداث Discord وتنسيق الشاردات واتصالات البوابة المتعددة وAutoMod وسجلات النشاط.
البرنامج بترخيص BSL 1.1 مع منح إضافي للاستخدام.
قاعدة بيانات علائقية
يكمل PostgreSQL طبقة البيانات لدينا للبيانات والبنى العلائقية. ويعمل إلى جانب ScyllaDB كجزء مستقل من البنية التحتية.
قاعدة البيانات
يشكل ScyllaDB جزءًا من طبقة البيانات إلى جانب PostgreSQL. نستخدم النظامين لمهام مختلفة داخل Fjord.
تخزين الكائنات
نستخدم RustFS لتخزين الكائنات المتوافق مع S3. وهو يضيف طبقة تخزين مستقلة إلى جانب PostgreSQL وScyllaDB.
البرنامج مرخص بموجب Apache 2.0. RustFS علامة تجارية لشركة RustFS, Inc.