العمال المتوازيون
يوزّع Greph فحوص النص وAST على تجمع عمال عندما يكون حجم العمل كافيًا لتبرير الكلفة الإضافية. يعتمد التجمع على pcntl_fork()، ويعود إلى التنفيذ داخل العملية نفسها عندما لا يتوفر ext-pcntl (في Windows وبعض بيئات PaaS وبيئات الاستضافة المقيّدة).
تفعيل الفحوص المتوازية
اضبط -j N في CLI أو jobs: N في كائن الخيارات المعني:
./vendor/bin/greph -F -j 8 "function" src
./vendor/bin/greph -p '$obj->$method($$$ARGS)' -j 4 src
./vendor/bin/rg --threads 8 -F "function" src
./vendor/bin/sg run --threads 8 --pattern '$obj->$method($$$ARGS)' src
use Greph\Greph;
use Greph\Text\TextSearchOptions;
Greph::searchText(
'function',
'src',
new TextSearchOptions(fixedString: true, jobs: 8),
);
متى يبدأ التنفيذ المتوازي
لا ينفّذ Greph العمل بالتوازي في كل الحالات. فتشغيل N من العمليات وإرسال نتائجها ذهابًا وإيابًا عبر الأنابيب يضيف كلفة، وقد تفوق هذه الكلفة البحث نفسه عندما تكون قائمة الملفات قصيرة. لذلك تحسب الواجهة عتبة استنادًا إلى عدد المهام ونمط البحث وشكل النمط. ولا تُوزع على تجمع العمال إلا قوائم الملفات التي تتجاوز العتبة.
الاستدلالات الحالية (في Greph\Greph::shouldUseTextWorkers وما شابه):
- تعمل المهام المفردة (
-j 1) دائمًا داخل العملية نفسها. - تحتاج فحوص النص الافتراضية إلى نحو
jobs * 2_000ملفًا قبل تفعيل التجمع. - تخفّض أوضاع العدد والملفات المطابقة والملفات غير المطابقة العتبة إلى نحو
jobs * 750لأن العمل لكل ملف أقل تكلفة. - ترفع أنماط السلاسل الثابتة القصيرة التي تشبه المعرّفات العتبة إلى نحو
jobs * 4_000، لأن المسار الحرفي السريع زهيد أصلًا، ونادرًا ما يبرر التشغيل المتفرع كلفته. - يستخدم بحث AST وإعادة كتابة AST العتبة
jobs * 750.
هذه الأرقام استدلالات وليست وعودًا. وهي مضبوطة وفق مجموعة بيانات قياس الأداء WordPress، وقد يعاد النظر فيها.
آلية عمل التجمع
يوزّع Greph\Parallel\WorkSplitter قائمة الملفات على N أجزاء. يشغّل Greph\Parallel\WorkerPool عملية عامل لكل جزء، وينفذ كل عامل الإغلاق نفسه على الجزء المخصص له، ثم يقرأ Greph\Parallel\ResultCollector النتائج المتسلسلة عبر زوج مقابس Unix لكل عامل. تنتظر العملية الأم انتهاء جميع العمال، ثم تدمج مجموعة النتائج وتعيد فرزها لضمان ثبات ترتيب المخرجات بغض النظر عن تقسيم العمل.
يستخدم تجمع العمال في وضع النص برنامج ترميز مخصصًا لنقل البيانات (Greph\Text\TextResultCodec) لإبقاء الحمولة المتسلسلة صغيرة. أما وضع AST فيستخدم PHP القياسي الخاص بـ serialize().
عند عدم توفر pcntl
إذا تعذّر استدعاء pcntl_fork (في Windows أو إصدارات PHP المشددة)، يعود التجمع تلقائيًا إلى تشغيل كل جزء داخل العملية نفسها. وتكون النتيجة مطابقة لـ -j 1. لا يُصدر Greph خطأً؛ بل يعمل بخيط تنفيذ واحد.
يمكنك اكتشاف ذلك أثناء التشغيل بالتحقق من function_exists('pcntl_fork').
نصائح الضبط
- ابدأ بضبط
-jعلى نصف عدد الأنوية الفعلية، ثم ارفع القيمة حتى تتوقف التحسينات. - غالبًا ما يكون التنفيذ بعملية واحدة أسرع من أي إعداد متوازٍ لعمليات البحث ذات السلاسل الثابتة فقط في المستودعات الصغيرة.
- لا يقيس أي معيار منشور بحث AST أو إعادة كتابته بالتوازي. أجرِ القياس على شجرتك قبل اعتماد عدد المهام.
- صفوف «وضع الفحص: النص المتوازي» في README (
1و2و4عمال على مجموعة البيانات WordPress) لا تقيس التجمع: فهي تبحث عن السلسلة الحرفية القصيرةfunction، وعتبتها البالغةjobs * 4_000ملفًا تتجاوز حجم مجموعة البيانات؛ لذلك تعمل كل الصفوف داخل عملية واحدة (#8).
القيود
- لا يدعم التجمع حاليًا توزيع العمل أثناء التنفيذ. إذا كان أحد الأجزاء أثقل بكثير من البقية، فسيتعين على التجمع انتظار أبطأ عامل.
- تُخزّن نتائج العمال مؤقتًا حتى ينتهي الجميع. لا يدعم الوضع المتوازي تدفق مخرجات الفحص طويل التشغيل بالطريقة التي يبث بها
rg --jsonالأحداث. - تعيد العملية الأم فرز النتائج بعد دمجها، لذلك لا يقلل تجمع العمال ذروة استخدام الذاكرة مقارنة بالفحص بعملية واحدة.
هذه القيود مقبولة لأعباء العمل التي يستهدفها Greph، مثل البحث التفاعلي في الأكواد ودورات عمل الوكلاء ومهام CI على اللقطات. وسيعاد النظر فيها إذا أظهر تحليل الأداء أنها تسبب اختناقًا في مجموعات بيانات واقعية.