لو الكود بتاعك شغال كويس على 1000 سجل وبيموت على مليون، المشكلة مش في السيرفر. المشكلة إنك كتبت خوارزمية O(n²) وأنت فاكرها O(n).
Big O Notation: اللغة اللي لازم تتكلمها قبل ما تكتب سطر كود لـ production
المشكلة باختصار
معظم المطورين بيختبروا الكود على عينة صغيرة. الـ endpoint بيرد في 50ms، كله تمام، يروح production. بعد أسبوع، نفس الـ endpoint بياخد 8 ثواني. السبب؟ عدد السجلات زاد 100 ضعف، لكن الكود ما بيكبرش بنفس النسبة - بيكبر أسرع بكتير. Big O هي الأداة اللي بتخليك تتوقع ده قبل ما يحصل، مش بعد ما المستخدمين يتضايقوا.
إيه هي Big O فعلًا
Big O مش عن قياس الزمن بالثانية. هي عن العلاقة بين حجم البيانات وعدد الخطوات اللي الخوارزمية بتعملها. لو عندك دالة بتلف على array مرة واحدة، ده O(n). لو فيه حلقتين متداخلتين بيلفوا على نفس الـ array، ده O(n²). الرقم الثابت مش مهم - مش فرق بين 2n و 5n، الاتنين O(n).
الافتراض هنا إنك بتهتم بالسلوك مع كبر البيانات، مش مع 10 عناصر. كل خوارزمية بتبقى سريعة مع عينة صغيرة. Big O بتقولك إيه هيحصل لما العينة دي تكبر 1000 ضعف.
الخمسة أنواع اللي هتقابلك في 90% من الحالات
- O(1): وصول لعنصر في hash map، push على stack. الزمن ثابت مهما كبرت البيانات.
- O(log n): binary search في array مرتبة. كل خطوة بتقسم المشكلة لنصين.
- O(n): لفّة واحدة على array. لو ضاعفت البيانات، الزمن بيضاعف.
- O(n log n): أي sort محترم (mergesort أو quicksort). ده أفضل ما تقدر توصله في الترتيب العام بدون افتراضات عن البيانات.
- O(n²): حلقتين متداخلتين على نفس البيانات. مع مليون سجل ده ترليون عملية. هتموت.
مثال بيوضح الفرق بالظبط
عندك array فيه IDs ولازم تعرف لو فيه تكرار. الحل الساذج اللي بيطلع من أول مرة:
// O(n²) - بيموت على 100 ألف عنصر
function hasDuplicateSlow(arr) {
for (let i = 0; i < arr.length; i++) {
for (let j = i + 1; j < arr.length; j++) {
if (arr[i] === arr[j]) return true;
}
}
return false;
}
// O(n) - شغال على 10 ملايين عنصر
function hasDuplicateFast(arr) {
const seen = new Set();
for (const x of arr) {
if (seen.has(x)) return true;
seen.add(x);
}
return false;
}
قياس حقيقي: على array فيه 100,000 عنصر في Node.js، النسخة الساذجة بتاخد حوالي 8 ثواني. النسخة التانية بتاخد 6 ميلي ثانية. الفرق 1300 ضعف. على 10 ملايين عنصر، الأول عمليًا مستحيل - بيقعد ساعات. التاني بيخلص في أقل من ثانيتين. جرّب بنفسك بـ console.time() قبل ما تصدق.