تتيح لك ربط سلسلة رسائل بنواة معينة، مما قد يؤدي إلى تحسين الأداء (تعمل هذه المكتبة بشكل أفضل على نظام التشغيل Linux).
مكتبة OpenHFT Java Thread Affinity
راجع affinity/src/test/java للحصول على أمثلة عملية حول كيفية استخدام هذه المكتبة.
V3.2.0 - إضافة دعم لتكوين النص
V3.1.1 - ترقية تبعية JNA إلى 4.4.0
V2.0.1 - تمت إضافة getThreadId للعملية الخاصة بالموضوع.
سيحاول Java-Thread-Affinity استخدام JNA لتوفير الوصول إلى وظائف معالجة الخيوط الأصلية. يجب تثبيت JNA على نظامك لتحقيق أقصى استفادة من هذه المكتبة.
يعتمد Java-Thread-Affinity حاليًا على إصدار JNA 4.4.0، والذي يعتمد بدوره على إصدار GLIBC >= 2.14. إذا كان نظام التشغيل الخاص بك قديمًا، مع إصدار GLIBC قبل عام 2011، فلن تتمكن هذه المكتبة من استدعاء الوظائف الأصلية.
للتغلب على هذه المشكلة، قم بتقسيم المستودع وتجاوز علامة <version>
الخاصة بالمنتجات jna
و jna-platform
في ملف pom
الخاص بالمشروع.
sudo apt-get install libjna-java
سودو يم تثبيت jna
ستقرأ المكتبة /proc/cpuinfo
الخاص بك إذا كان لديك واحدة أو توفر واحدة وستحدد تخطيط وحدة المعالجة المركزية لديك. إذا لم يكن لديك واحدًا، فسوف تفترض أن كل وحدة معالجة مركزية موجودة على مقبس واحد لوحدة المعالجة المركزية.
تبحث المكتبة عن وحدات المعالجة المركزية المعزولة التي يتم تحديدها من خلال النظر إلى وحدات المعالجة المركزية التي لا تعمل عليها بشكل افتراضي. على سبيل المثال، إذا كان لديك 16 وحدة معالجة مركزية ولكن 8 منها غير متاحة للاستخدام العام (كما هو محدد من خلال تقارب العملية عند بدء التشغيل)، فسوف يبدأ التعيين لوحدات المعالجة المركزية هذه.
ملاحظة: إذا كان لديك أكثر من عملية واحدة تستخدم هذه المكتبة، فأنت بحاجة إلى تحديد وحدات المعالجة المركزية التي يمكن للعملية استخدامها وإلا فسيتم تعيين نفس وحدات المعالجة المركزية لكلتا العمليتين. للتحكم في وحدات المعالجة المركزية التي يمكن أن تستخدمها العملية، أضف -Daffinity.reserved={cpu-mask-in-hex} إلى سطر أوامر العملية.
ملاحظة: وحدة المعالجة المركزية 0 محجوزة لنظام التشغيل، ويجب تشغيلها في مكان ما.
https://github.com/peter-lawrey/Java-Thread-Affinity/wiki/Getting-started
https://github.com/peter-lawrey/Java-Thread-Affinity/wiki/How-it-works
http://vanillajava.blogspot.co.uk/2013/07/micro-jitter-busy-waiting-and-binding.html
يتطلب Java-Thread-Affinity أن تقوم أولاً بعزل بعض وحدات المعالجة المركزية (CPU).
بمجرد عزل نواة وحدة المعالجة المركزية، لن يستخدم برنامج جدولة Linux نواة وحدة المعالجة المركزية لتشغيل أي عمليات تتعلق بمساحة المستخدم. لن تشارك وحدات المعالجة المركزية المعزولة في موازنة التحميل، ولن يكون لها مهام تعمل عليها ما لم يتم تعيينها بشكل صريح.
لعزل نواة وحدة المعالجة المركزية الأولى والثالثة (تبدأ أرقام وحدة المعالجة المركزية من 0) على نظامك، أضف ما يلي إلى سطر أوامر kernel أثناء التمهيد:
معزولة = 1,3
يمكنك الحصول على قفل لوحدة المعالجة المركزية بالطريقة التالية:
في جافا 6
AffinityLock al = AffinityLock . acquireLock ();
try {
// do some work locked to a CPU.
} finally {
al . release ();
}
في جافا 7 أو 8
try ( AffinityLock al = AffinityLock . acquireLock ()) {
// do some work while locked to a CPU.
}
لديك المزيد من الخيارات مثل
يمكنك حجز نواة كاملة. إذا قمت بتمكين تقنية Hyper-threading، فسيستخدم هذا وحدة معالجة مركزية واحدة ويترك وحدة المعالجة المركزية المزدوجة الخاصة بها غير مستخدمة.
try ( AffinityLock al = AffinityLock . acquireCore ()) {
// do some work while locked to a CPU.
}
يمكنك اختيار تخطيط متعلق بقفل موجود.
try ( final AffinityLock al = AffinityLock . acquireLock ()) {
System . out . println ( "Main locked" );
Thread t = new Thread ( new Runnable () {
@ Override
public void run () {
try ( AffinityLock al2 = al . acquireLock ( AffinityStrategies . SAME_SOCKET ,
AffinityStrategies . ANY )) {
System . out . println ( "Thread-0 locked" );
}
}
});
t . start ();
}
في هذا المثال، ستفضل المكتبة وحدة المعالجة المركزية المجانية على نفس المقبس مثل الخيط الأول، وإلا فإنها ستختار أي وحدة معالجة مركزية مجانية.
يمكنك الحصول على معرف الموضوع الحالي باستخدام
int threadId = AffinitySupport . getThreadId ();
يمكنك الحصول على وحدة المعالجة المركزية الحالية المستخدمة من قبل
int cpuId = AffinitySupport . getCpu ();
تقارب العملية عند بدء التشغيل هو
long baseAffinity = AffinityLock . BASE_AFFINITY ;
وحدة المعالجة المركزية المتاحة للحجز هي
long reservedAffinity = AffinityLock . RESERVED_AFFINITY ;
إذا كنت ترغب في الحصول على/تعيين التقارب مباشرةً، يمكنك القيام بذلك
long currentAffinity = AffinitySupport . getAffinity ();
AffinitySupport . setAffinity ( 1L << 5 ); // lock to CPU 5.
للحصول على عرض تفصيلي لحالة التقارب الحالية (كما تراها المكتبة)، قم بتنفيذ البرنامج النصي التالي على أنظمة Linux:
# change to the affinity lock-file directory (defaults to system property java.io.tmpdir)
$ cd /tmp
# dump affinity state
$ for i in "$(ls cpu-*)";
do PID="$(cat $i | head -n1)"; TIMESTAMP="$(cat $i | tail -n1)";
echo "pid $PID locked at $TIMESTAMP in $i"; taskset -cp $PID;
cat "/proc/$PID/cmdline"; echo; echo
done
pid 14584 locked at 2017.10.30 at 10:33:24 GMT in cpu-3.lock
pid 14584's current affinity list: 3
/opt/jdk1.8.0_141/bin/java ...
مجموعة دعم Java Thread Affinity
للحصول على مقالة حول مقدار الفرق الذي يمكن أن يحدثه التقارب وكيفية استخدامه http://vanillajava.blogspot.com/2013/07/micro-jitter-busy-waiting-and-binding.html
أنا أعمل حاليًا على مشروع متعلق بالكشف عن حالة توقف تام في البرامج متعددة مؤشرات الترابط في Java. نحن نحاول تشغيل سلاسل الرسائل على معالجات مختلفة، وبالتالي عثرنا على منشورات جيثب الخاصة بك بخصوص نفس الشيء. https://github.com/peter-lawrey/Java-Thread-Affinity/wiki/Getting-started كوني مبتدئًا، لدي القليل من المعرفة وبالتالي أحتاج إلى مساعدتك. نحتاج إلى معرفة كيفية تشغيل سلاسل الرسائل على رقم وحدة المعالجة المركزية المحدد ثم تبديل سلاسل الرسائل عند الانتظار.
// lock a cpuId
try ( AffinityLock lock = AffinityLock . acquireLock ( n )) {
}
حيث n هي وحدة المعالجة المركزية التي تريد تشغيل الموضوع عليها.
أو
// lock one of the last CPUs
try ( AffinityLock lock = AffinityLock . acquireLockLastMinus ( n )) {
}
لدي cpuId في ملف التكوين، كيف يمكنني ضبطه باستخدام سلسلة؟
try ( AffinityLock lock = AffinityLock . acquireLock ( "last" )) {
assertEquals ( PROCESSORS - 1 , Affinity . getCpu ());
}
try ( AffinityLock lock = AffinityLock . acquireLock ( "last-1" )) {
assertEquals ( PROCESSORS - 2 , Affinity . getCpu ());
}
try ( AffinityLock lock = AffinityLock . acquireLock ( "1" )) {
assertEquals ( 1 , Affinity . getCpu ());
}
try ( AffinityLock lock = AffinityLock . acquireLock ( "any" )) {
assertTrue ( lock . bound );
}
try ( AffinityLock lock = AffinityLock . acquireLock ( "none" )) {
assertFalse ( lock . bound );
}
try ( AffinityLock lock = AffinityLock . acquireLock (( String ) null )) {
assertFalse ( lock . bound );
}
try ( AffinityLock lock = AffinityLock . acquireLock ( "0" )) { // prints a warning
assertFalse ( lock . bound );
}