
تأخیر یک معیار کارایی (Performance Metric) است که میزان مکث یا تأخیر زمانی در سیستم شما را اندازهگیری میکند. به عنوان یک توسعهدهنده، احتمالاً به صورت غیررسمی در مورد زمان پاسخگویی (Response Time) یا لگ (Lag) صحبت کردهاید که این خود یکی از راههای تعریف تأخیر است. با این حال به تعریف دقیقتری از تأخیر نیاز داریم.
تعریفی از تأخیر که در ادامه استفاده خواهیم کرد به این شرح است:
تأخیر، فاصله زمانی بین یک علت و اثرِ مشاهدهشدهی آن است.
اگر این تعریف را بشکافیم، دو نکته را بیان میکند. اول اینکه ما عملی را انجام میدهیم و پیامدی را مشاهده میکنیم. دوم اینکه، تأخیر همان مدت زمان سپری شده بین این دو رویداد است. بنابراین، اندازهگیری تأخیر بسته به کانتکست (Context)، میتواند معانی مختلفی داشته باشد.
یکی از مثالها برای درک تأخیر در عمل، روشن و خاموش کردن چراغها با استفاده از کلید برق است. این یک مثال روزمره و بسیار ساده است که شاید تا به حال به آن فکر نکرده باشید. من تازه زمانی به تأخیرِ روشن و خاموش شدن چراغها دقت کردم که لامپهای هوشمند خریدم، شروع به کار با آنها کردم و متوجه یک تأخیر عجیب شدم. وقتی چراغها را از طریق اپلیکیشن روی گوشی هوشمندم روشن کردم، انتظار داشتم که فوراً روشن شوند؛ چرا که کلیدهای برق همیشه اینگونه کار کردهاند. اما در مورد لامپهای هوشمند، بین فشردن دکمه «روشن کردن چراغها» و روشن شدن واقعی آنها، یک تأخیر کاملا محسوس وجود داشت.
بعدا متوجه شدم آنچه مشاهده میکردم اساساً تأخیر شبکه (Network Delay) بود: فشردن دکمه، ابتدا پیامی را از طریق شبکه بیسیمِ گوشی من به یک هاب کنترلی و سپس از طریق شبکهای مانند بلوتوث یا ZigBee به خود لامپ ارسال میکرد و تازه پس از آن بود که چراغها روشن میشدند. تأخیر در این مثال، زمان بین فشردن دکمه در اپلیکیشن گوشی (علت) و روشن شدن چراغها (اثر مشاهدهشده) است.
برای مشاهده چنین پدیدهای حتی به لامپهای هوشمند هم نیازی ندارید؛ تنها چیزی که نیاز دارید لامپهای LED مدرن است که ظاهراً میتوانند تا 2 ثانیه در روشن شدن تأخیر داشته باشند. اگر تا به حال روی تأخیر کلیدهای برق حساس نشدهاید، با نزدیکترین کلیدهای برق آزمایشی انجام دهید. این کار به طرز شگفتآوری سرگرمکننده است و دو چیز را به شما ثابت میکند: اول اینکه تأخیر دارای واریانس و پراکندگی است (چراغهای مختلف تأخیرهای متفاوتی دارند)، و دوم اینکه تأخیر بر تجربه کاربری (User Experience) تأثیر میگذارد. اینها دو موضوع حیاتی در مبحث Latency هستند که درباره آنها بحث خواهیم کرد.
در ادامه، بیایید تأخیر در سرویسدهی به یک درخواست HTTP را بررسی کنیم؛ وقتی کاربری یک URL را در مرورگر تایپ میکند و کلید Enter را میفشارد، یک تأخیر End-to-End را بین فشردن Enter (علت) و دیدن صفحه وبی که درخواست کرده (اثر مشاهدهشده) تجربه میکند. با این حال، زمان پاسخگوییِ (Response Time) کلی به عوامل بسیاری بستگی دارد: ماشین کلاینت، شبکه، سرور و سایر سرویسهای درگیر برای پردازش درخواست. به عنوان مثال، اگر کاربر یک نام دامنه (Domain Name) را تایپ کند، مرورگر باید یک جستجوی DNS انجام دهد تا آدرس IP متناظر با دامنه را پیدا کند. تأخیر این عملیات DNS ،بستگی به این دارد که آیا پاسخ در کش (Cache) ماشین محلی موجود است یا مرورگر باید درخواستی (Query) را به یک سرور DNS راه دور ارسال کند. توجه داشته باشید که تا زمانی که جستجوی DNS کامل نشود، نمیتوانیم درخواست HTTP را از مرورگر ارسال کنیم؛ این نمونهای از نحوه تجمیع و ترکیب شدن تأخیرها (Compound Latency) است .
پس از ارسال موفقیتآمیز درخواست HTTP توسط کلاینت به سرور، کامپوننتهای متعددی درگیر میشوند که همگی در تأخیر End-to-End نقش دارند. به عنوان مثال، صفحه وب ارائهشده ممکن است حاوی محتوای داینامیکی باشد که سرور باید آن را از یک سرویس خارجی مانند یک Key-Value Store یا دیتابیس واکشی (Fetch) کند. زمان مورد نیاز برای واکشی دادهها از این سیستمهای خارجی، مستقیما به تأخیر End-to-End قابل مشاهده توسط کاربر اضافه میشود، زیرا سرور باید منتظر بماند تا سرویسهای خارجی درخواستهایشان را کامل کنند تا بتواند به پردازش تسکهای خود ادامه دهد. علاوه بر این، زمانی که کلاینت پاسخ HTTP را دریافت میکند، باز هم پتانسیل تأخیر بیشتری وجود دارد. برای مثال، مرورگر باید صفحه را رندر (Render) کند، که ممکن است شامل اجرای کدهای جاوا اسکریپت یا ارسال درخواستهای HTTP اضافی باشد که این خود تأخیر درکشده توسط کاربر (User-Perceived Latency) را افزایش میدهد.
شما در تمامی لایههای استک نرمافزار/سختافزار با تأخیر مواجه هستید. به عنوان آخرین مثال از یک تأخیر خاص، به پردازش بستههای شبکه (Network Packets) در سطح سختافزار و سیستمعامل در لینوکس توجه کنید. وقتی یک پکت از شبکه میرسد، ابتدا توسط کارت شبکه (NIC) هندل میشود؛ سختافزاری که وظیفه تبدیل سیگنالهای شبکه به دادههای باینری را دارد تا استک نرمافزاری بتواند با آنها کار کند. کارت شبکه، پکت را در یکی از صفهای دریافت (Receive Queues) خود قرار میدهد که استک شبکه در سیستمعامل به طور پیوسته آن را Polling میکند. وقتی سیستمعامل یک پکت جدید را میبیند، آن را به استک شبکه فوروارد میکند که معمولاً به عنوان یک Thread کرنل (Kernel Thread) روی یک هسته پردازشی اجرا میشود. استک شبکه کرنل به یک Thread در فضای کاربر (Userspace Application Thread) اطلاع میدهد که دادههای جدید در دسترس هستند. متعاقباً، Thread فضای کاربر یک فراخوانی سیستمی (System Call) از نوع recvmsg را برای خواندن دادههای تازه رسیدهشده آغاز میکند. فاصله زمانی بین رسیدن یک پکت به کارت شبکه تا در دسترس قرار گرفتن آن در یک Thread فضای کاربر، تأخیر پردازش پکت را نشان میدهد.
هنگام بهینهسازی برای دستیابی به Low Latency، درک این نکته ضروری است که چندین نقطه در مسیر عبور یک پکت در استک شبکه کرنل لینوکس وجود دارد که بر روی تأخیر نهایی تأثیر میگذارند. برای مثال، فرض کنید Thread کرنلِ استک شبکه، روی یک CPU متفاوت از Thread فضای کاربر در حال اجراست. در این حالت، کرنل باید یک وقفه بینپردازشی (Inter-Process Interrupt) پرهزینه ایجاد کند تا به Thread دیگر اطلاع دهد. یا اگر تمام پکتها به یک صف واحد برسند، کرنل لینوکس ممکن است نتواند از تمام هستههای در دسترس پردازنده برای پردازش پکتها به درستی استفاده کند .
ما تأخیر را با واحدهای زمان اندازهگیری میکنیم. به عنوان مثال، تأخیر دسترسی به دادهها در یک دیسک SSD حدود 100 میکروثانیه و تأخیر رفتوبرگشت شبکه (Round-Trip) از نیویورک به لندن معادل 60 میلیثانیه است. این مقادیر در جدول زیر که لیستی از برخی ثابتهای کلیدی تأخیر برای محاسبات سرانگشتی است، نشان داده شده است. همانطور که میبینیم، در بالاترین سطح از سلسلهمراتب حافظه، رجیسترهای CPU، کشهای پردازنده و حافظه DRAM را داریم که تأخیر دسترسیِ آنها از مرتبه نانوثانیه تا صدها نانوثانیه متغیر است. با حرکت به سمت پایینتر یعنی دیسکها، زمان دسترسی به مرتبه میکروثانیه میرسد. در نهایت، با حرکت به سمت ارتباطات خارجی مانند شبکه، تأخیر در مرتبه میلیثانیه و بالاتر قرار میگیرد.

قوانین فیزیک برای ثابتهای تأخیر محدودیت ایجاد میکنند. سرعت نور که به طور تقریبی معادل 300,000 کیلومتر بر ثانیه است، حد بالایی سرعت انتقال اطلاعات در فواصل مختلف را تعیین میکند. به عبارت دیگر، سرعت نور، کمترین میزان تأخیرِ قابل دستیابی را دیکته میکند. البته سرعت نور فقط نشاندهنده سقف تئوری است. بسیاری از شبکههای کامپیوتری از کابلهای فیبر نوری برای انتقال نور استفاده میکنند، اما سرعت نور در آنها به دلیل عدم وجود خلأ، کندتر از حد تئوری است. عوامل متعدد دیگری نیز بر تأخیر تأثیرگذارند. اما نکته کلیدی این است که محدودیتهای فیزیکی مرزهای قطعی برای تأخیر ایجاد میکنند؛ موضوعی که با ورود به بحث هممکانی (Colocation) سرورها مشهودتر است.