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

لا تستطيع كل مؤسسة / بنك أن يتحمل تطوير هذا النوع من البرامج. لكن كنت محظوظًا لأن هذا المشروع تم إطلاقه داخل جدران بنك Raiffeisenbank ، وكان لدي التخصص المناسب - لقد تخصصت في أداء الشفرات في مختبر Intel Moscow Compiler Laboratory. صنعنا المجمعين ل C ، C ++ و Fortran. في Raiffeisenbank ، تحولت إلى Java. إذا قمت في وقت سابق بعمل نوع من الأدوات استخدمه كثير من الناس في ذلك الوقت ، فقد انتقلت الآن إلى الجانب الآخر من المتاريس وأشارك في التحليل التطبيقي لأداء ليس فقط الكود ، ولكن مكدس التطبيق بالكامل. بشكل منتظم ، تتعدى طريقة البحث عن مشكلة أداء ما أبعد من الشفرة ، على سبيل المثال ، في إعدادات النواة أو الشبكة.
جافا ليست ل highload؟
ويعتقد على نطاق واسع أن جافا ليست مناسبة للغاية لتطوير أنظمة محملة للغاية.
هذا لا يمكن الاتفاق عليه جزئيا. جافا جميلة في العديد من الجوانب. إذا قمنا بمقارنتها بلغة مثل C ++ ، فقد تكون النفقات العامة المحتملة أعلى ، ولكن في بعض الأحيان قد تعمل الحلول المماثلة وظيفيًا في C ++ ببطء أكبر. هناك تحسينات تعمل تلقائيًا في Java ، ولكنها لا تعمل في C ++ ، والعكس صحيح. بالنظر إلى جودة الكود الذي يأتي بعد برنامج التحويل البرمجي Java JIT ، أريد أن أصدق أن الأداء سيكون أدنى مما يمكنني تحقيقه في ذروة ، لا أكثر من عدة مرات. لكن في الوقت نفسه ، حصلت على تطوير سريع للغاية وأدوات ممتازة ومجموعة واسعة من المكونات الجاهزة.
دعنا نواجه الأمر: في عالم C ++ ، تكون بيئات التطوير (IDEs) وراء IntelliJ و Eclipse بشكل كبير. إذا كان المطور يستخدم أيًا من هذه البيئات ، فإن سرعة تصحيح الأخطاء والبحث عن الأخطاء وكتابة المنطق المعقد تكون بترتيب أعلى. نتيجة لذلك ، اتضح أنه من الأسهل حفظ Java في الأماكن الصحيحة بحيث يعمل بسرعة كافية من القيام بكل شيء من نقطة الصفر ولوقت طويل جدًا في C ++. أطرف ما في الأمر هو أنه عند كتابة التعليمات البرمجية التنافسية ، تتشابه طرق المزامنة في كل من Java و C ++: فهي إما بدائية على مستوى نظام التشغيل (على سبيل المثال ،
التزامن / std :: mutex ) أو البدائل الحديدية (
Atomic * / std :: atomic <*> ) . ومن المهم للغاية رؤية هذا التشابه.
بشكل عام ، نحن نعمل على تطوير تطبيق بدون حمولة كبيرة))
ما هو الفرق بين الحمل الزائد وتطبيق الكمون المنخفض؟
لا يعكس المصطلح "الحمل الزائد" بشكل كامل تفاصيل عملنا - فنحن نشارك في
أنظمة زمن الاستجابة . ما هو الفرق؟ بالنسبة للأنظمة شديدة التحميل ، من المهم العمل بسرعة متوسطة إلى حد ما ، مع الاستفادة الكاملة من موارد الأجهزة. في الممارسة العملية ، هذا يعني أن كل مائة / ألف / / مليون طلب للنظام يمكن أن تعمل ببطء شديد ، لأننا نركز على القيم المتوسطة ولا نأخذ دائمًا في الاعتبار أن مستخدمينا يعانون بشكل كبير من الفرامل.
نحن منخرطون في أنظمة يكون فيها مستوى التأخير بالغ الأهمية. مهمتنا هي التأكد من أن النظام لديه دائما استجابة يمكن التنبؤ بها. قد لا يتم تحميل
الأنظمة الحساسة زمنياً بشكل كبير إذا كانت الأحداث نادراً ما تكفي ، ولكن يلزم توفر وقت استجابة مضمون. وهذا لا يجعل تنميتها أسهل. العكس تماما! الأخطار تكمن في الانتظار في كل مكان. الغالبية العظمى من مكونات الأجهزة والبرامج الحديثة موجهة نحو العمل الجيد "في المتوسط" ، أي
لالانتاجية .
خذ على الأقل هياكل البيانات. نستخدم جداول التجزئة ، وإذا حدثت إعادة تجزئة بنية البيانات بأكملها على مسار حرج ، فقد يؤدي ذلك إلى الفرامل الملموسة لمستخدم معين بناءً على طلب واحد. أو برنامج التحويل البرمجي JIT - يعمل على تحسين نمط التعليمات البرمجية الذي يتم تنفيذه بشكل متكرر ، مما يؤدي إلى تشاؤم نمط التعليمات البرمجية نادر التنفيذ. لكن سرعة هذه الحالة النادرة يمكن أن تكون مهمة للغاية بالنسبة لنا!
ربما يعالج هذا الرمز نوعًا نادرًا من الطلبات؟ أو بعض أوضاع السوق غير العادية التي تحتاج إلى استجابة سريعة؟ نحاول التأكد من أن رد فعل نظامنا على هذه الأحداث التي يحتمل أن تكون نادرة يستغرق بعض الوقت المتوقع ، ويفضل أن يكون ذلك لفترة قصيرة للغاية.
كيفية تحقيق وقت رد الفعل يمكن التنبؤ به؟
لا يمكن الإجابة عن هذا السؤال في جملتين. في التقريب الأول ، من المهم أن نفهم ما إذا كان هناك أي نوع من المزامنة -
متزامن ، أو
reentrantlock أو شيء من
java.util.concurrent . غالبًا ما يتعين عليك استخدام المزامنة على مشغول spin'ah. استخدام أي التزامن البدائي هو دائما حل وسط. ومن المهم أن نفهم كيف تعمل بدايات التزامن هذه والمفاضلات التي تحملها. من المهم أيضًا تقييم مقدار القمامة التي تولدها قطعة معينة من التعليمات البرمجية. أفضل طريقة لمكافحة جامع القمامة هي عدم تشغيله. كلما قل إنتاجنا للقمامة ، كلما قل تشغيلنا لجامع للقمامة ، وسيعمل النظام لفترة أطول دون تدخل.
نستخدم أيضًا مجموعة واسعة من الأدوات المختلفة التي تسمح لنا بتحليل ليس فقط المؤشرات المتوسطة. علينا أن نحلل بعناية شديدة كيف يعمل النظام ببطء كل مائة ، كل ألف مرة. من الواضح أن هذه المؤشرات ستكون أسوأ من المتوسط أو المتوسط. ولكن من المهم للغاية بالنسبة لنا أن نعرف كم. وهناك أدوات مثل
Grafana و
Prometheus و
HDR histograms و
JMH تساعد في إظهار ذلك.
هل يمكنني إزالة غير آمنة؟
غالبًا ما يتعين عليك استخدام ما يطلق عليه المدافعون واجهة برمجة تطبيقات غير موثقة. أنا أتحدث عن غير آمنة الشهيرة. أعتقد أن الوضع غير الآمن أصبح جزءًا فعليًا من API العامة لأجهزة Java. ليس من المنطقي إنكار ذلك. يستخدم Unsafe الكثير من المشاريع التي نستخدمها جميعًا بنشاط. وإذا رفضنا ذلك ، فماذا سيحدث لهذه المشاريع؟ إما سيعيشون على الإصدار القديم من Java ، أو سيتعين عليهم مرة أخرى إنفاق الكثير من الطاقة لإعادة كتابة كل هذا. هل المجتمع مستعد لهذا؟ هل هي على استعداد لفقدان عشرات في المئة من الإنتاجية؟ والأهم من ذلك ، في مقابل ماذا؟
بشكل غير مباشر ، يؤكد رأيي
الإزالة الدقيقة
جدًا للطرق من طريقة غير آمنة - في Java11 تمت إزالة أكثر الطرق عديمة الفائدة من الطريقة غير الآمنة. أعتقد أنه إلى أن ينتقل ما لا يقل عن نصف جميع المشاريع التي تستخدم برنامج "غير آمن" إلى شيء آخر ، سيكون "غير آمن" متاحًا بشكل أو بآخر.
هناك رأي: بنك + جافا = المؤسسة المتحجرة الدموية؟
فريقنا ليس لديه مثل هذه الفظائع. في فصل الربيع ، ربما كتبنا عشرة سطور ، وبواسطةي)) نحن نحاول عدم استخدام التقنيات الكبيرة. نحن نفضل القيام بالأعمال الصغيرة والأنيقة والسريعة ، حتى نتمكن من إدراكها والتحكم فيها وتعديلها إذا لزم الأمر. هذا الأخير مهم للغاية للأنظمة (مثل نظامنا) ، والتي لها متطلبات غير قياسية ، والتي قد تختلف عن متطلبات 90 ٪ من مستخدمي الإطار. وفي حالة استخدام إطار عمل كبير ، لن نتمكن من توصيل احتياجاتنا إلى المجتمع أو تصحيح السلوك بشكل مستقل.
في رأيي ، يجب أن يكون المطورون دائمًا قادرين على استخدام جميع الأدوات المتاحة. جئت إلى عالم Java من C ++ وأنا مندهش جدًا من تقسيم المجتمع إلى أولئك الذين يطورون
وقت تشغيل الجهاز الظاهري / المترجم أو الجهاز الظاهري نفسه وإلى مطوري التطبيقات. يظهر هذا بوضوح في كود فئة JDK القياسي. غالبًا ما يستخدم مؤلفو JDK واجهة برمجة تطبيقات مختلفة. من المحتمل ، هذا يعني أننا لا نستطيع تحقيق أعلى أداء. بشكل عام ، أعتقد أن استخدام نفس واجهة برمجة التطبيقات لكتابة كل من المكتبة القياسية ورمز التطبيق هو مؤشر ممتاز على نضج النظام الأساسي.
شيء آخر
أعتقد أنه من المهم للغاية لجميع المطورين معرفة كيف ، إن لم يكن المكدس بالكامل ، فإن نصفه على الأقل يعمل: كود جافا ، رمز بايت ، الأجزاء الداخلية من وقت تشغيل الجهاز الظاهري والمجمع ، الأجهزة ، نظام التشغيل ، الشبكة. وهذا يتيح نظرة أوسع على المشاكل.
الأداء الجدير بالذكر أيضا. من المهم جدًا عدم التركيز على المتوسط وإلقاء نظرة دائمًا على النسب المئوية المتوسطة والعالية (أسوأ قياسات 10/100/1000 / ...).
سأتحدث عن كل هذا في
اجتماع لمجموعة مستخدمي جافا في 30 مايو في سان بطرسبرغ. لقاء مع سيرجي ملنيكوف ، هذا أنا فقط)) يمكنك التسجيل
هنا .
ما الذي سنتحدث عنه؟- حول التوصيف واستخدام منشئ ملفات التعريف ولينكس القياسيين: كيف نتعايش معهم ، وما يقيسونه وكيف يفسرون نتائجهم. وستكون هذه مقدمة إلى التنميط العام ، مع النصائح ، والمتطفلين على الحياة ، وكيفية الضغط على كل شيء ممكن من المحلل حتى يتمكنوا من التعريف بأقصى قدر من الدقة والتردد.
- حول ميزات المعدات للحصول على ملف تعريف أكثر تفصيلًا وعرض ملف تعريف الأحداث النادرة. على سبيل المثال ، عندما يتم تشغيل الرمز الخاص بك 10 مرات أبطأ كل مرة مائة. لن يخبرنا المحلل عن هذا. سنقوم بكتابة ملف التعريف الصغير الخاص بنا باستخدام آلية Linux kernel القياسية ونحاول مشاهدة ملف تعريف بعض الأحداث النادرة.
تعال إلى الاجتماع ، ستكون أمسية رائعة ، وستكون هناك العديد من القصص المثيرة للاهتمام حول برنامجنا ولغتنا المفضلة.
أراك لاحقًا ؛)