من فضلك تسجيل الدخول أو تسجيل لتفعل ذلك.

لقد وضعنا المسودة أخيرًاJEP “الثوابت المحسوبة”عامة ولا أطيق الانتظار لأخبركم المزيد عنها!ComputedConstantالكائنات هي أصحاب قيمة فائقة السرعة غير قابلة للتغيير ويمكن تهيئتها بشكل مستقل عن وقت إنشائها. كميزة إضافية ، قد يتم تحسين هذه الكائنات في المستقبل بشكل أكبر عبر“مكثفات”التي قد تصبح متاحة في النهاية من خلال المشروعليدن.

خلفية

في كثير من الأحيان نستخدمstaticالحقول لعقد الكائنات التي تمت تهيئتها مرة واحدة فقط:

// ordinary static initializationprivate static final Logger LOGGER=Logger.getLogger("com.foo.Bar");...LOGGER.log(...);

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

تتمثل إحدى طرق منع تهيئة جميع الحقول الثابتة في الفصل الدراسي في نفس الوقت في استخدام الامتدادلغة حامل الفئةالسماح لنا بتأجيل التهيئة حتى نحتاج بالفعل إلى المتغير:

// Initialization-on-demand holder idiomLogger logger() {    class Holder {         static final Logger LOGGER=Logger.getLogger("com.foo.Bar");    }    return Holder.LOGGER;}...logger().log(...);

بينما يعمل هذا جيدًا من الناحية النظرية ، إلا أن هناك عيوبًا كبيرة:

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

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

// Double-checked locking idiomclass Foo {    private volatile Logger logger;    public Logger logger() {        Logger v=logger;        if (v==null) {            synchronized (this) {                v=logger;                if (v==null) {                    logger=v=Logger.getLogger("com.foo.Bar");                }            }        }        return v;    }}...foo.logger().log(...);

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

الComputedConstantيأتي الفصل إلى الإنقاذ هنا ويقدم أفضل ما في العالمين: تهيئة مرنة وأداء جيد!

ثابت محسوب

هنا هو كيفComputedConstantيمكن استخدامها مع مثال المسجل:

class Bar {    // 1. Declare a computed constant value    private static final ComputedConstant<Logger> LOGGER=            ComputedConstant.of( () -> Logger.getLogger("com.foo.Bar") );    static Logger logger() {        // 2. Access the computed value        //    (evaluation made before the first access)        return LOGGER.get();    }}

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

المعايير

لقد أجريت بعض المعايير على جهاز Mac Pro M1 ARM الخاص بي وتشير النتائج الأولية إلى أداء ممتاز لـstaticComputedConstantمجالات:

Benchmark      Mode  Cnt  Score   Error  UnitsstaticHolder   avgt   15  0.561 ? 0.002  ns/opdoubleChecked  avgt   15  1.122 ? 0.003  ns/opconstant       avgt   15  0.563 ? 0.002  ns/op // static ComputedConstant

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

مجموعات ComputedConstant

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

مثل أComputedConstantمتغير ، أList>يتم إنشاء المتغير من خلال توفير مخطط عنصر – عادةً في شكل تعبير lambda ، والذي يستخدم لحساب القيمة المرتبطة بالعنصر i منListعند الوصول إلى قيمة العنصر لأول مرة:

class Fibonacci {    static final ListInteger>> FIBONACCI=            ComputedConstant.of(1_000, Fibonacci::fib);    static int fib(int n) {        return (n <2)                ? n                : FIBONACCI.get(n - 1) + FIBONACCI.get(n - 2);    }    int[] fibs=IntStream.range(0, 10)            .map(Fibonacci::fib)            .toArray(); // { 0, 1, 1, 2, 3, 5, 8, 13, 21, 34 }}

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

عندما تعتمد عملية حسابية على المزيد من العمليات الحسابية الفرعية ، فإنها تستحث رسمًا بيانيًا للتبعية ، حيث تكون كل عملية حسابية عقدة في الرسم البياني ، ولها حواف صفرية أو أكثر لكل عقد من عقد الحساب الفرعي التي تعتمد عليها. على سبيل المثال ، الرسم البياني للتبعية المرتبط بـfib(5)يرد أدناه:

               ___________fib(5)___________              /                                    ____fib(4)____                ____fib(3)____       /                            /                   fib(3)         fib(2)         fib(2)          fib(1)    /             /             /        fib(2)  fib(1) fib(1)  fib(0) fib(1)  fib(0)

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

مجموعات المعايير

تم تشغيل هذه المعايير على نفس النظام الأساسي كما هو مذكور أعلاه وتظهر مجموعات منComputedConstantتتمتع العناصر بنفس مزايا الأداء التي تتمتع بها العناصر الفردية:

Benchmark      Mode  Cnt  Score   Error  UnitsstaticHolder   avgt   15  0.570 ? 0.005  ns/op // int[] in a holder classdoubleChecked  avgt   15  1.124 ? 0.044  ns/opconstant       avgt   15  0.562 ? 0.005  ns/op // List

مرة أخرى ، فإنComputedConstantالساعات في سرعة مصفوفة ثابتة أصلية مع توفير مرونة أفضل بكثير عند التهيئة.

أداء المثيل

يتفوق أداء متغيرات وكائنات المثيل على أصحابها الذين يستخدمون المصطلح المزدوج الموضح أعلاه كما يمكن رؤيته في المعايير أدناه:

Benchmark      Mode  Cnt  Score   Error  UnitsdoubleChecked  avgt   15  1.259 ? 0.023  ns/opconstant       avgt   15  0.728 ? 0.022  ns/op // ComputedConstant

لذا،ComputedConstantأسرع بنسبة 40٪ من فئة الحامل المزدوج التي تم اختبارها على جهازي.

أين هي؟

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

موارد

شكر وتقدير

تمت كتابة أجزاء من النص في هذه المقالة بواسطة موريزيو سيمادامور

اقرأ أكثر

مشتري Chromebook ، احذروا: لا تزال Amazon تبيع 13 طرازًا غير مدعوم
تعرض أميال الخطوط الجوية ونقاط الفنادق وبيانات المستخدم المجانية للخطر بسبب العيوب في منصة النقاط

Reactions

0
0
0
0
0
0
بالفعل كان رد فعل لهذا المنصب.

ردود الفعل