حول تسرب الذاكرة
Webman هو إطار عمل عالي الأداء يعتمد على الذاكرة، لذا نحتاج إلى الانتباه قليلاً لحالة تسرب الذاكرة. ومع ذلك، لا يحتاج المطورون إلى القلق كثيرًا، لأن تسرب الذاكرة يحدث في ظروف قصوى جدًا، ومن السهل تجنبه. تجربة تطوير Webman مشابهة إلى حد كبير لتطوير الإطارات التقليدية، ولا داعي للقيام بعمليات زائدة لإدارة الذاكرة.
تنبيه
عملية المراقبة المدمجة في Webman ستراقب استخدام الذاكرة لكل العمليات، وإذا كانت الذاكرة المستخدمة في عملية ما تقترب من القيمة المحددة فيmemory_limit
في php.ini، سيتم إعادة تشغيل العملية تلقائيًا بأمان لتحرير الذاكرة، دون التأثير على الأعمال.
تعريف تسرب الذاكرة
مع زيادة الطلبات، تزداد ذاكرة Webman بشكل غير محدود (انتبه، هو غير محدود)، وتصل إلى مئات الميجا بايت أو أكثر، وهذا يعد تسرب ذاكرة. إذا كانت هناك زيادة في الذاكرة ولكنها لم تعد تنمو بعد ذلك، فلا يُعد ذلك تسرب ذاكرة.
عادة ما يكون استهلاك الذاكرة بضع عشرات من الميجا بايت أمرًا طبيعيًا، وعندما تتعامل العملية مع طلبات ضخمة أو تحافظ على اتصالات ضخمة، قد يصل استهلاك الذاكرة في عملية واحدة إلى مئات الميجا بايت، وهذا أمر شائع. بعد استخدام هذه الذاكرة، قد لا تقوم PHP بإرجاعها بالكامل لنظام التشغيل. بدلاً من ذلك، تُحتفظ بها لإعادة الاستخدام، لذا قد يحدث أن تظل الذاكرة المستخدمة أكبر بعد معالجة بعض الطلبات الضخمة، وهذا أمر طبيعي (يمكنك استدعاء طريقة gc_mem_caches() لتحرير جزء من الذاكرة الفارغة).
كيف يحدث تسرب الذاكرة
يجب أن تتحقق الشروط التالية لحدوث تسرب الذاكرة:
- وجود مصفوفة ذات عمر طويل (لاحظ أن هذه مصفوفة ذات عمر طويل، بينما لا تمثل المصفوفات العادية مشكلة).
- وأن هذه المصفوفة ذات العمر الطويل ستتوسع بلا حدود (العمل يواصل إدخال البيانات فيها دون تنظيف).
إذا تحقق الشرطان 1 و 2 معًا (لاحظ أنهما يجب أن يتحققا معًا)، سيحدث تسرب الذاكرة. وإذا لم تتحقق الشروط أعلاه أو تحققت أحدهما فقط، فلا يكون هناك تسرب ذاكرة.
مصفوفات ذات عمر طويل
المصفوفات ذات العمر الطويل في Webman تشمل:
- مصفوفات مع الكلمة المفتاحية static
- خصائص مصفوفة العينة
- مصفوفات مع الكلمة المفتاحية 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 لن يتم استرجاعها بعد انتهاء تنفيذ الدالة أو طريقة الفئة، لذا فهي مصفوفة ذات عمر طويل، ستؤدي الشيفرة أعلاه إلى تسرب الذاكرة مع زيادة الطلبات. بالمثل، المصفوفة المعرفة داخل دالة أو طريقة باستخدام الكلمة المفتاحية static والتي تتوسع بلا حدود ستؤدي أيضًا إلى تسرب الذاكرة، مثل:
class Index
{
public function index(Request $request)
{
static $data = [];
$data[] = time();
return response($foo->sayHello());
}
}
التوصيات
يوصى المطورين بعدم التركيز كثيرًا على تسرب الذاكرة، لأنه نادر الحدوث. إذا حدث ذلك بشكل غير محظوظ، يمكننا العثور على الكود المسبب للتسرب من خلال اختبارات الضغط وبالتالي تحديد المشكلة. حتى لو لم يتمكن المطور من العثور على نقطة التسرب، فإن خدمة المراقبة المدمجة في Webman ستقوم بإعادة تشغيل العمليات التي حصل فيها تسرب الذاكرة بشكل آمن في الوقت المناسب، مما يحرر الذاكرة.
إذا كنت ترغب في تجنب تسرب الذاكرة قدر الإمكان، يمكنك النظر في النصائح التالية:
- حاول عدم استخدام مصفوفات مع الكلمة المفتاحية
global
وstatic
، وإذا استخدمتها، تأكد من أنها لن تتوسع بلا حدود. - بالنسبة للفئات غير المألوفة، حاول عدم استخدام العينة، وبدلاً من ذلك قم بتهيئتها باستخدام الكلمة المفتاحية new. إذا كانت هناك حاجة إلى العينة، تحقق مما إذا كانت تحتوي على مصفوفات متوسعة بلا حدود.