حول تسرب الذاكرة
webman هو إطار عمل مقيم في الذاكرة، لذلك نحتاج إلى الانتباه قليلاً لتسرب الذاكرة. ومع ذلك، لا يحتاج المطورون إلى القلق المفرط، لأن تسرب الذاكرة يحدث فقط في ظروف قصوى جداً ويسهل تجنبه. تجربة التطوير مع webman تشبه إلى حد كبير الأطر التقليدية؛ ولا حاجة لعمليات إضافية لإدارة الذاكرة.
نصيحة
عملية المراقبة المدمجة في webman تراقب استخدام الذاكرة لجميع العمليات. عندما يقترب استخدام ذاكرة عملية ما من القيمة المعينة فيmemory_limitفي php.ini، ستُعاد تشغيل العملية المقابلة تلقائياً وبأمان لتحرير الذاكرة، دون تأثير على التطبيق.
تعريف تسرب الذاكرة
من الطبيعي أن يزداد استخدام ذاكرة webman مع زيادة عدد الطلبات. بشكل عام، عندما تصل العملية إلى حجم معين من الطلبات (عادة بملايين)، تستقر الذاكرة أو تزداد قليلاً أحياناً فقط.
في معظم التطبيقات، ينتهي استخدام الذاكرة لكل عملية بالاستقرار عند حوالي 10M–100M. لا داعي للقلق طالما أن استخدام الذاكرة لكل عملية يبقى أقل من 100M.
بالإضافة إلى ذلك، عند معالجة الملفات الكبيرة أو الطلبات الكبيرة أو قراءة كميات كبيرة من البيانات من قاعدة البيانات، يخصص PHP قدراً كبيراً من الذاكرة. قد يحتفظ PHP بجزء من هذه الذاكرة لإعادة استخدامها بدلاً من إرجاعها كلها للنظام التشغيل، مما قد يؤدي إلى استخدام ذاكرة مرتفع. بما أن الذاكرة تُعاد استخدامها، فلا داعي للقلق.
نصيحة
في مشاريع phar أو الثنائية المعبأة، إذا كان حجم الحزمة كبيراً، فمن الطبيعي أن يتجاوز استخدام الذاكرة 100M.
كيفية تأكيد تسرب الذاكرة
إذا عالجت عملية أكثر من مليون طلب، واستخدام الذاكرة يتجاوز 100M، والذاكرة لا تزال تزداد بعد كل طلب، فقد يحدث تسرب ذاكرة.
كيفية تحديد موقع تسرب الذاكرة
طريقة بسيطة هي إجراء اختبارات الضغط على كل واجهة برمجة التطبيقات وتحديد أيها يستمر في زيادة استخدام الذاكرة بعد ملايين الطلبات.
بعد العثور على الواجهة المشكلة، يمكن استخدام البحث الثنائي: تعليق نصف كود الأعمال في كل مرة حتى تحديد الكود المسبب.
كيف يحدث تسرب الذاكرة
يحدث تسرب الذاكرة فقط عند استيفاء الشرطين التاليين معاً:
- وجود مصفوفة ذات دورة حياة طويلة (المصفوفات العادية ليست مشكلة)
- وهذه المصفوفة ذات دورة الحياة الطويلة تنمو بلا حدود (التطبيق يواصل إدراج البيانات ولا يحذفها أبداً)
يحدث التسرب فقط عندما يُستوفى كلا الشرطين. إذا لم يُستوف أي شرط أو شرط واحد فقط، فلا يوجد تسرب.
مصفوفات ذات دورة حياة طويلة
في webman، تشمل مصفوفات دورة الحياة الطويلة:
- مصفوفات بالكلمة المفتاحية
static - خصائص المصفوفة في الكائنات المفردة (singletons)
- مصفوفات بالكلمة المفتاحية
global
ملاحظة
يسمح webman باستخدام البيانات ذات دورة الحياة الطويلة، ولكن يجب ضمان أن البيانات محدودة وأن عدد العناصر لا ينمو بلا حدود.
فيما يلي أمثلة على كل حالة.
مصفوفة static تنمو بلا حدود
class Foo
{
public static $data = [];
public function index(Request $request)
{
self::$data[] = time();
return response('hello');
}
}
المصفوفة $data المعرفة بـ static لها دورة حياة طويلة. في المثال، تستمر $data في النمو مع كل طلب، مما يسبب تسرب الذاكرة.
خاصية مصفوفة كائن مفرد تنمو بلا حدود
class Cache
{
protected static $instance;
public $data = [];
public function instance()
{
if (!self::$instance) {
self::$instance = new self;
}
return self::$instance;
}
public function set($key, $value)
{
$this->data[$key] = $value;
}
}
كود الاستدعاء
class Foo
{
public function index(Request $request)
{
Cache::instance()->set(time(), time());
return response('hello');
}
}
Cache::instance() تُرجع كائناً مفرداً Cache له دورة حياة طويلة. رغم أن الخاصية $data لا تستخدم static، فإن الفئة نفسها لها دورة حياة طويلة، لذا $data هي أيضاً مصفوفة ذات دورة حياة طويلة. مع استمرار إضافة مفاتيح مختلفة إلى $data، يزداد استخدام الذاكرة ويحدث التسرب.
ملاحظة
إذا كانت المفاتيح المضافة عبرCache::instance()->set(key, value)محدودة العدد، فلن يحدث تسرب، لأن مصفوفة$dataلا تنمو بلا حدود.
مصفوفة global تنمو بلا حدود
class Index
{
public function index(Request $request)
{
global $data;
$data[] = time();
return response($foo->sayHello());
}
}
المصفوفات المعرفة بـ global لا تُحرر بعد انتهاء الدالة أو Method، لذا لها دورة حياة طويلة. الكود أعلاه يسبب تسرباً مع زيادة الطلبات. بالمثل، المصفوفات المعرفة بـ static داخل دالة أو method لها أيضاً دورة حياة طويلة؛ إذا نما حجمها بلا حدود، يحدث تسرب، مثلاً:
class Index
{
public function index(Request $request)
{
static $data = [];
$data[] = time();
return response($foo->sayHello());
}
}
توصيات
ينصح بعدم التركيز المفرط على تسرب الذاكرة، لأنه نادر. عند حدوثه، تساعد اختبارات الضغط في العثور على الكود المسبب. حتى لو لم يجد المطور مكان التسرب، خدمة المراقبة المدمجة في webman ستعيد تشغيل العملية المتأثرة في الوقت المناسب لتحرير الذاكرة.
للحد قدر الإمكان من مخاطر التسرب، يمكن اتباع هذه التوصيات:
- تجنب ما أمكن مصفوفات
globalوstatic؛ عند استخدامها، التأكد من أنها لا تنمو بلا حدود. - للفئات غير المألوفة، يُفضَّل التهيئة بـ
newبدلاً من الكائنات المفردة. عند استخدام كائن مفرد، التحقق من وجود خصائص مصفوفة قد تنمو بلا حدود.