أمثلة البرمجيات

في علم الحاسوب، يستخدم مصطلح تحسين البرمجيات (بالإنكليزية: Program optimization) لوصف عملية التعديل على نظام برمجي لجعل بعض جوانبه تعمل بشكل أكثر كفاءة أو لجعله يستخدم مصادر أقل. بشكل عام، يمكن أن يحسن البرنامج لجعله يعمل بشكل أسرع أو لجعله قادرا على العمل باستخدام ذاكرة أقل ومصادر أخرى أقل أو لجعله يستغل طاقة أقل.

لمحة عامة

بالرغم من أن مصطلح "التحسين" يتشارك نفس الأصل مع كلمة  " الأمثل"، إلا إنه من النادر أن تنتج عملية التحسين نظام مثالي كما ينبغي. سيكون النظام المحسن مثالياً كما هو متوقع في تطبيق واحد فقط أو لشخص واحد. حيث يمكن تقليل الوقت الذي يستغرقه البرنامج لأداء بعض المهام لكن بالمقابل سيستنفذ ذاكرة أكبر. كما يمكن للفرد اختيار خوارزميات حاسوبية أبطء لاستخدام ذاكرة أقل، وذلك في التطبيقات التي تكون بها مساحة الذاكرة هي أهم عامل. وفي الغالب، لا يوجد تصميم واحد يناسب الكل لذلك يقوم المهندسون بعمل حلول وسط لتحسين الميزات للحصول على أقصى فائدة. علاوة على ذلك، يعد الجهد المبذول لجعل البرمجيات مثاليةً تماماً أكثر من منفعة البرنامج؛ لذا يمكن لعملية التحسين أن تتوقف مؤقتاً قبل الوصول للحل النهائي الأمثل. ولحسن الحظ، غالباً ما تأتي التحسينات الكبرى في بداية العملية.

مستويات التحسين

يمكن أن تحدث عملية التحسين في عدد من المستويات. عادةً ما تكون المستويات العليا لها التأثير الأقوى ويصعب تغييرها في وقت لاحق في المشروع، متطلباً تغييرات جذرية أو إعادة صياغة كاملة إذا أردت تغييرها. وهكذا، يمكن لعملية التحسين أن تستأنف عادةً من خلال التنقية من أعلى إلى أسفل، محققاً مكاسب أولية أكبر بعمل أقل ومكاسب لاحقة  أقل متطلبة عمل أكثر. ومع هذا، يعتمد الأداء الكلي في بعض الحالات على أداء أجزاء صغيرة المستوى من البرنامج وتغييرات صغيرة في المرحلة الأخيرة  أو اعتبارات مبدئية لتفاصيل صغيرة المستوى يمكن أن تحدث تأثير هائل. عادةً تَعطى بعض الاعتبارات للكفاءة خلال المشروع- بالرغم من أن ذلك يتغير كثيراً- لكن غالباً ما تعتبر التحسينات الكبرى من مرحلة التدقيق التي تتم مؤخراً. يوجد عادة دوائر لتحسين المشروعات طويلة المدى، حيث أن تحسين مجال واحد يكشف عن أوجه القصور في مجال آخر، ويتم تقليصها عادةً إذا كان الأداء مقبولاً أو إذا أصبحت المكاسب أصغر أو أقل تكلفة.
بما أن الأداء جزء من ميزات البرنامج- فإن البرنامج البطيء غير القابل للاستخدام لا يفي بالغرض: حيث تعد لعبة الفيديو 60هرتز (كادر في الثانية) مقبولة، لكن ذات 6 كادر في الثانية متقطعة وغير مقبولة- حيث يؤخذ الأداء بعين الاعتبار منذ البداية، وللتأكيد على أن النظام قادر على تقديم أداء كاف، فإن النماذج الأولية تحتاج إلى أداء مقبول على نحو تقديري للتأكد من أن النظام النهائي سيحقق أداء مقبول (مع التحسين). وفي بعض الأحيان يهمل للاعتقاد بأن التحسين دائماً يمكن أن يتم في وقت لاحق، محدثاً نظام أولي بطئ جداً أونظام يفشل في نهاية المطاف لأنه معمارياً لا يستطيع تحقيق أهداف الأداء الخاصة به مثل (Intel 432 (1981 أو تلك التي تستغرق سنوات من العمل لتحقيق أداء مقبول مثل (Java (1995 التي حققت أداءً مقبولاً فقط بنقطة الاتصال  (HotٍٍSpot (1999. يمكن للدرجة التي يتغير بها الأداء ما بين النموذج الأولي والنظام النهائي وكيفية قابليته للتحسين أن تكون مصدراً كبيراً لعدم اليقين والمخاطر.

على مستوى التصميم

في أعلى مستوى يمكن تحسين التصميم، للحصول على الاستخدام الأمثل للمصادر المتاحة و تحقيق الأهداف المعطاة و عدم تجاوز القيود. حيث يؤثر التصميم المعماري للنظام تأثيراً بالغاً على أداءه. يتم اختيار التصميم بناءَ على الأهداف المراد تحقيقها: فعند تصميم المحول البرمجي(بالإنجليزية: Compiler)، إذا كانت سرعة الترجمة و التجميع هي الأولوية الرئيسية، فكومبايلر ذا مسار واحد أسرع من كومبايلر متعدد المسارات (يؤدي نفس العمل)، لكن إذا كانت سرعة إخراج التعليمات البرمجية هو الهدف، فإن كومبايلر متعدد المسارات أبطء سيفي بالغرض أكثر، على الرغم من أن الأمر يستغرق وقتاً أطول في حد ذاته. يتم اختيار البرنامج ولغة البرمجة في هذا المستوى، ويتطلب تغيرهم في كثير من الأحوال إعادة كتابة كاملة للبرنامج، بالرغم من أن نظام الوحدات قد يسمح بإعادة كتابة بعض المكونات فقط - على سبيل المثال، يمكن إعادة كتابة فقط بعض الأجزاء المهمة بلغة ال C لبرنامج كتب بلغة البايثون. في نظام التوزيع، يتم اختيار الهندسة المعمارية (خادم-عميل، نظير-إلى-نظير، إلخ) على مستوى التصميم، وقد يكون من الصعب تغيرها لاحقاً.

الخوارزميات وهيكلة البيانات

بعد التصميم،   يؤثر اختيار الخوارزميات و بنية البيانات على الكفاءة أكثر من أي ميزات أخرى للبرنامج. فتعد هيكلة البيانات بصفة عامة أكثر صعوبة في التغيير من الخوارزميات، كما تستخدم افتراضات هيكلة البيانات وافتراضات أدائها من خلال البرنامج، على الرغم من أنه يمكن تقليص ذلك باستخدام أنواع بيانات مجردة في تعريفات الدالة وحفظ تعريفات بنية بيانات محددة تقتصر على أدوار قليلة.
بالنسبة للخوارزميات، لابد التأكد من أنها عبارة عن ثابت (O(1، لوغاريتمي (O(log n، خط مستقيم (O(n، مستقيم لوغاريتمي  (O(n log n حيث المدخلات (المساحة والوقت).  تخفق الخوارزميات ذات التعقيد الرباعي (O(n2 في القياس و حتى الخوارزميات الخطية تسبب مشاكل إذا تم استدعائها مراراً وتكراراً، وعادة ما يتم استبدال مع خوارزمية ثابت أو لوغاريتم إذا أمكن.
تعد التقنية العامة لتحسين الأداء هي تجنب الجهد. وخير مثال هو استخدام مسار سريع للحالات المتشابهة، محسناً الأداء عن طريق تجنب الجهد غير الضروري. على سبيل المثال، استخدام تصميم لوغاريتمي بنص بسيط للنص اللاتيني. يعد التخزين المؤقت الذي يجنبنا العمليات الحسابية الزائدة عن الحاجة تقنية أخرى ذات أهمية. ونظراً لأهمية التخزين المؤقت، غالباً ما تكون هناك مستويات عديدة للتخزين المؤقت في النظام الذي يمكن أن يسبب مشاكل من استخدام الذاكرة وصحة المعلومات في التخزين المؤقت.

مستوى البرنامج (code)

بعيداً عن اللوغاريتمات العامة وتطبيقاتها على الآلة المجردة، يمكن لخيارات مستوى التعليمات البرمجية أن تحدث فارقاً كبيراً. على سبيل المثال: (while(1 أبطأ من (;;)for، لأن تقييم (while(1 قفزة شرطية التي اختبرت إذا كان الأمر صحيحاً، بينما ل(؛؛)for كان لها قفزة غير مشروطة. حيث يمكن لبعض التحسينات هذه الأيام أن تتم عن طريق تحسين الكومبايلر. ويعتمد ذلك على لغة المصدر ولغة الجهاز المستهدف والكومبايلر، ويمكن أن يصعب كلاً من فهمه أو توقعه والتغيرات عبر الزمن؛ يعد هذا المكان الرئيسي حيث يمكن فهم المحولات البرمجية والتعليمات البرمجية للجهاز لتحسين الأداء. كما يعد كود الحلقة الثابتة وتحسين إرجاع القيمة أمثلة للتحسينات التي تقلل من الحاجة إلى المتغيرات الإضافية.

مستوى البناء

مستوى البناء بين مستوى البرنامج و مستوى الكومبايلر، يمكن للتعليمات والعلامات أن تستخدم لتقليص خيارات الأداء في التعليمات البرمجية للمصدر وبرنامج التحويل البرمجي على التوالي، مثل تعريف استخدام المعالج إلى تعطيل ميزات البرامج غير الضرورية، محسناً لنماذج معالج محددة أو قدرات الأجهزة، أو التنبؤ بالمنطق التفريعي، على سبيل المثال. كما يمكن لنظم توزيع البرامج المستندة إلى المصدر مثل المنقولات، توزيعة برمجيات بيركلي وبورتج جنتو من نموذج التحسين هذا على الوجه الأمثل.

مستوى التنسيق

يهدف استخدام كومبايلر محسن إلى التأكيد على أن البرنامج المنفذ معدل على الأقل بالقدر المتوقع من الكومبايلر.

مستوى التجميع

في المستوى الأدنى؛ يمكن أن تُنتج شفرة الكتابة باستخدام لغة التجميع المصممة لبرنامج أجهزة معينة والتي تعتبر أكثر الشفرات كفاءة إذا استفاد المبرمج من المجموعة الكاملة لتعليمات الآلة. تمت كتابة العديد من أنظمة التشغيل المستخدمة في الأنظمة المضمنة بلغة التجميع لأسباب الكفاءة. نادرًا ما تُكتب البرامج (بخلاف البرامج الصغيرة جدا) من البداية إلى النهاية بلغة التجميع بسبب الوقت والتكاليف المتعلقة بها. تُكتب غالباً بلغة عالية المستوى ثم إلى لغة التجميع ويتم التحسين اليدوي منها. عندما تكون الكفاءة والحجم أقل أهمية فربما تُكتب الأجزاء الكبيرة بلغة عالية المستوى.
مع المحولات البرمجية المحسنة الفعالة الجديدة و وحدات المعالجة المركزية الحديثة فإنه من الصعب كتابة الشفرة أكثر كفاءة مما ينتجه المترجم، وتحتاج القليل من المشاريع إلى خطوة التحسين "النهائية".
يراد تشغيل العديد من الشفرات المكتوبة اليوم على أكبر عدد ممكن من الأجهزة. نتيجة لذلك؛ لا يستفيد المبرمجون وبرامج الترجمة عادةً من التعليمات الأكثر كفاءة التي توفرها وحدات المعالجة المركزية الجديدة.
إجمالاً؛ سيستخدم المبرمجون مفككًا لتحليل ناتج برنامج الترجمة اليوم بدلاً من الكتابة بلغة التجميع وتغير الشفرة ذات المصدر عالي المستوى بحيث يمكن ترجمته بطريقة أكثر كفاءة أو فهم سبب عدم الكفاءة.

وقت التشغيل

يمكن أن ينتج برنامج الترجمة شفرة لجهاز مخصص معتمدة على بيانات وقت التشغيل على حساب تكلفة ترجمة البرامج. تعود هذه التقنية إلى تركيب التعابير النمطية والتي انتشرت على نطاق واسع Java HotSpot و V8 لJavaScript. في بعض الحالات؛ قد يكون التحسين التكيفي قادرًا على أداء التحسين وقت التنفيذ والذي يتجاوز قدرة برامج الترجمة الثابتة عن طريق ضبط المعاملات ديناميكيًا وفقًا للإدخال الفعلي أو العوامل الأخرى.
تقنية تحسين ترجمة البرامج في وقت سابق (بالإنجليزية: Profile-guided optimization) بناء على بيانات التعريف الخاصة بوقت التشغيل والمشابهة للنظير الثابت "متوسط الحالة" للتقنية الديناميكية الخاصة بالتحسين التكيفي.
يمكن أن يُبدل التعديل الذاتي للشفرة (بالإنجليزية: Self-modifying code) من تلقاء نفسه استجابة لظروف وقت التشغيل بهدف تحسين الشفرة. يعتبر ذلك أكثر شيوعًا في برامج لغة التجميع.
يمكن لبعض تصميمات وحدة المعالجة المركزية أداء بعض التحسينات في وقت التشغيل. تشتمل بعض الأمثلة على التنفيذ الخارج عن النظام والتنفيذ التخميني وخطوط أنابيب التعليمات والتنبؤات الفرعية.

التحسينات المعتمدة و المستقلة عن النظام الأساسي

يمكن أيضًا تصنيف شفرة التحسين بصفة عامة كتحسين معتمد على النظام الأساسي وتحسين مستقل عن النظام الأساسي. في حين أن النوع الأخير فعّال في معظم أو كل النظم الأساسية. تستخدم التقنيات المعتمدة على النظام الأساسي خصائص معينة للنظام الواحد أو تعتمد على معاملات تعتمد على نظام أساسي فردي أو حتى على معالج معلومات. لذلك تكون هناك حاجة إلى كتابة أو إنتاج نسخ مختلفة من نفس الشفرة للمعالجات المختلفة. على سبيل المثال؛ في حالة التحسين على مستوى الترجمة تعد التقنيات المستقلة عن النظام الأساسي تقنيات عامة والتي تؤثر على معظم تصميمات وحدة المعالجة المركزية بطريقة مشابهة.  بشكل عام؛ يؤدي ذلك إلى تقليل طول مسار التعليمات الكلي المطلوب لإكمال البرنامج أو تقليل الذاكرة الكلية المستخدمة أو كلاهما أثناء العملية. من ناحية أخرى؛ تتضمن التقنيات المعتمدة على النظام الأساسي تعليمات مجدولة وتوازي على مستوى التعليمات وتوازي مستوى البيانات وتقنيات تحسين ذاكرة التخزين المؤقتة (بمعني أن المتغيرات تختلف بين الأنظمة الأساسية المختلفة) والتعليمات المجدولة المثلى ربما تختلف حتى في المعالجات المختلفة لنفس التصميم.

تخفيض القوة

مهام الحاسوب يمكن أدائها في طرق مختلفة متعددة بفاعلية مختلفة. نسخة فعالة أكثر بوظيفة مساوية تعرف كتخفيض القوة.
التحسين، يؤدى أحيانا أوتوماتيكيا عن طريق برنامج مؤلف فعال، هو أن يتم اختيار طريقة (نظام العد العشري) الأكثر تأثيرا، من خلال الاحتفاظ بالأداء الوظيفي المماثل.

المبادلات

مع ذلك، فإنه في بعض الحالات؛ يعتمد التطوير على استخدام خوارزميات أكثر تفصيلًا جاعلًا من استخدام "حالات معينة" و"خدع" معينة والتنفيذ مبادلاتٍ معقدة. فالوضع الأمثل للبرنامج قد يكون من الصعب فهمه وبالتالي قد ينطوي على أخطاء برمجية أكثر من الإصدارات غير المطورة. وبعد القضاء على الأنماط بشكلٍ واضح فإن بعض أكواد مستوى التطوير يصيبها الانخفاض بشكلٍ مستمر.
سيركز التطوير في المجمل على تحسين واحدة واثنتين من نواحي التنفيذ: تحرير الوقت أو استخدام الذاكرة أو مساحة القرص أو عرض نطاق الترددات أو استهلاك الطاقة أو أي مصدر آخر. وهذا سيتطلب في العادة مبادلة؛ حيث يتم تطوير عامل واحد على حساب الآخرين. على سبيل المثال: زيادة حجم الذاكرة المخبأة يحسن من أداء وقت التشغيل بل يساعد أيضًا في زيادة استهلاك الذاكرة. وتشمل المبادلات العامة الأخرى وضوح الكود وإيجازه.
وهناك حالات حيث المبرمج القائم بالتطوير عليه أن يقرر جعل البرنامج أفضل بالنسبة لبعض العمليات ولكن على حساب جعل العمليات الأخرى أقل كفاءة. وهذه المبادلات قد تكون في بعض الأوقات ذات طبيعة غير فنية- فعندما ينشر المنافس نتيجة معيارية بأنه لابد أن يُهزم لغرض تحسين النجاح الاقتصادي لكن قد يصبح تحمل عبء إيجاد الاستخدام السهل للبرنامج أقل فعالية. فمثل هذه التغييرات تشير أحيانًا بشكل مازح إلى التشاؤم.

معوقات

قد تشمل عملية التحسين وجود معوقات في النظام- المكون الذي يعد العامل المحدد في الأداء. فيما يتعلق بالتعليمات البرمجية، سيعد ذلك غالباً نقطة اتصال- جزء هام من التعليمات البرمجية التي هي المستهلك الأساسي للموارد المطلوبة- بالرغم من أنه يمكن أن يكون عامل آخر مثل الإدخال/الإخراج وقت الاستجابة أو شبكة اتصال النطاق الترددي.
في علم الحاسوب، غالباً ما يتبع استهلاك الموارد نموذج قانون توزيع الطاقة، ويمكن تطبيق مبدأ باريتو على تحسين الموارد عن طريق ملاحظة أن 80% من المصادر عادةً ما تستخدم بنسبة 20% في العمليات. في هندسة البرمجيات، غالباً يعد أفضل تقدير أن 90% من الوقت التنفيذي لبرمجة الحاسوب تستغرق 10% من تنفيذ التعليمات البرمجية( المعروفة بنظام 90/10 في هذا السياق).
تتشكل خوارزميات أكثر تعقيداً وهيكلة بيانات جيداً بالعديد من العناصر، في حين تعد اللوغاريتمات البسيطة أكثر ملائمة لكم صغير من البيانات-  حيث يمكن للإعداد والتهيئة والعوامل الثابتة في الخوارزميات الأكثر تعقيداُ أن تفاقم الفائدة، وبالتالي قد تكون الخوارزميات المختلطة أو التكيفية أسرع من أي خوارزمية مفردة. كما يمكن لمقياس الأداء حصر القرارات بشأن أي وظيفة تناسب أي حالة.
يمكن لإضافة المزيد من الذاكرة أن يساعد البرنامج على العمل أسرع، في بعض الحالات. على سبيل المثال، عادةً سيقوم برنامج التصفية بقراءة كل سطر والتصفية وإخراج هذا الخط فوراً. و يستخدم هذا فقط ذاكرة كافية لسطر واحد، لكن عادة ما يكون الأداء ضعيف، بسبب زمن الوصول لقراءة كل قرص. كما يمكن تحسين الأداء تحسناً كبيراً عن طرق قراءة الملف الداخلي ثم كتابة النتائج المصفاة،  بالرغم من أن ذلك يستخدم ذاكرة أكبر بكثير. حيث يعد تخزين النتائج فعال على نحو مماثل بالرغم من أنه يتطلب أيضاً ذاكرة كبيرة.

متى نصل إلى التحسين

يمكن أن يقلل التحسين من قابلية القراءة كما يضيف الشفرة المستخدمة في تحسين الأداء فقط. وبالتالي قد يؤدي ذلك إلى تعقيد البرامج أو الأنظمة مما يجعل من الصعب صيانتها أو تصحيحها. ونتيجة لذلك؛ غالبًا ما يُنفذ التحسين أو ضبط الأداء في نهاية مرحلة التطوير.
أعطى دونالد كنوث البيانين التاليين حول التحسين:
"علينا أن ننسي أوجه الكفاءة الصغيرة والتي يمكن القول بأنها حوالي 97% من الوقت: كما يعتبر التحسين المبكر أصل لكل الشرور. أيضًا؛ علينا ألا نفوت فرصنا في تلك النسبة الحرجة التي تمثل حوالي 3%.
(كما أنه نسب هذا الاقتباس إلى توني هور على الرغم من أن يكون ذلك خطأ حيث أن هواري أخفق في صياغة العبارة)
"في التخصصات الهندسية الثابتة؛ لا تعتبر نسبة 12% من التحسين المكتسب بسهولة هامشيًا وأعتقد أنه يجب أن تسود وجهة النظر ذاتها في هندسة البرمجيات".
تعد عبارة "التحسين المبكر" هي العبارة المستخدمة لوصف الحالة التي تجعل المبرمج يترك اعتبارات الأداء التي أثرت في تصميم جزء من الشفرة. حيث يمكن أن يؤدي ذلك إلى تصميم يحتوي على عوائق كما يمكن أن يكون التصميم أو الشفرة غير صحيحة لأن الشفرة معقدة بسبب التحسين كما أن المبرمج تشتت بسبب التحسين.
عند اتخاذ القرار بشأن تحسين جزء من البرنامج فعلينا أخذ قانون أمدال في اعتبارنا: حيث يعتمد التأثير على البرنامج بشكل كبير على مقدار الوقت المُستغرق في الجزء المحدد والذي لا يكون واضح دائمًا من خلال النظر إلى الشفرة دون تحليل الأداء.
لذلك؛ فإن الطريقة الأفضل هي التصميم أولاً ثم استنتاج الشفرة من التصميم ثم وضع صورة أو علامة مرجعية لناتج الشفرة لمعرفة الأجزاء التي يجب تحسينها. يكون التصميم البسيط والرائع الأسهل غالبًا في التحسين في هذه المرحلة وربما تكشف الأوصاف مشاكل الأداء غير المتوقعة التي لم يتم معالجتها بالتحسين المبكر.
من الناحية العملية؛ غالبًا ما يكون من الضروري الاحتفاظ بأهداف الأداء في العقل عند التصميم الأول للبرامج، لكن على المبرمج أن يرجح بين أهداف التصميم والتحسين.
تتسم البرامج المترجمة الحديثة وأنظمة التشغيل بالكفاءة حيث أن زيادة الأداء المرادة لم تتحقق. على سبيل المثال؛ لم تتحقق التحسينات الخاصة بالتخزين المؤقت في مستوي التطبيق الذي تم تخزينه مؤقتًا مرة أخرى في مستوي نظام التشغيل خلال التنفيذ. ومع ذلك؛ فإنها حالة نادرة عندما يزيل المبرمج التحسينات المُخفقة من شفرة الإنتاج. ومن الصحيح أيضًا؛ أن الأجزاء الإلكترونية لن تؤدي في الغالب إلى أي تحسينات محتملة، ومع ذلك فإن الشفرة الغير واضحة ستستمر في المستقبل لمدة طويلة بعد نفاذ غرضها.

وحدات المايكرو

يأخذ التحسين أثناء تطوير الشفرة باستخدام وحدات المايكرو أشكالاً مختلفة بلغات مختلفة.
في بعض اللغات الإجرائية مثلC وc++؛ تُنَفَذ وحدات المايكرو باستخدام الاستبدال الرمزي. في الوقت الحاضر؛ يمكن استخدام الوظائف المباشرة كنوع من الاستبدال الآمن في الكثير من الحالات. في كلتا الحالتين؛ يمكن أن يخضع هيكل الوظيفة المباشرة بعد ذلك إلى التحسينات الإضافية وقت الترجمة عن طريق البرنامج المُترجم مشتملاً على الطي الثابت الذي ربما ينقل بعض الحسابات إلى وقت الترجمة.
في العديد من لغات البرمجة الوظيفية؛ تُنًفذ وحدات المايكرو باستخدام الاستبدال في وقت التحليل لتحليل هياكل تركيب الجملة المجردة التي من المفترض أن تجعلها آمنة عند الاستخدام. منذ استخدام الترجمة الفورية في العديد من الحالات والتي تعتبر أحد الطرق لضمان إجراء هذه الحسابات أثناء وقت التحليل وتكون في بعض الأوقات هي الطريقة الوحيدة.
أنشأت لغة البرمجة ليسب "Lisp" هذا النمط من وحدات المايكرو والتي يطلق عليها "ليسب مثل وحدات المايكرو" ويمكن تحقيق ذلك التأثير باستخدام نموذج ميتابروجرامنج "metaprograming " في C++.
في كلا الحالتين يُنقل العمل إلى وقت التحليل. يكون الفرق بين وحدات المايكرو C في جانب واحد ووحدات المايكرو المشابهة للغة LISP ونموذج ميتابروجرامنج C++ في الجانب الأخر هي الأداة الأخيرة التي تسمح بإجراء الحسابات العشوائية في وقت الترجمة أو وقت التحليل، بينما لا يعمل توسيع وحدات المايكرو C على إجراء أي حساب والتي تعتمد على قدرة المُحسن على إجرائها، إضافة إلى ذلك؛ لا تدعم وحدات المايكرو C مباشرة عمليات الإعادة أو التكرار، لذا لا يتم إكمال دورة كاملة.
كما هو الحال في أي من عمليات التحسين؛ بالرغم من أنه يصعب غالبًا التنبؤ بالمكان التي ستعمل فيه تلك الأدوات بشكل أكثر كفاءة قبل إكمال المشروع.

التحسين الآلي واليدوي

يمكن أداء التحسن الآلي عن طريق برامج الترجمة أو المبرمجين. عادة ما تكون مكاسب التحسينات المحلي محدودة وتكون المكاسب أكبر في التحسينات العالمية. عادة؛ يكون التحسين الأقوى هو إيجاد الحلول الحسابية الفائقة.
يتولى المبرمج عملية تحسين النظام الكامل لأنها معقدة جدًا بالنسبة للمُحسن الآلي. في هذه الحالة؛ يقوم المبرمجين أو المسؤولين عن النظام بتغيير الشفرة بوضوح لكي يعمل النظام بصورة أفضل. بالرغم من أنه يمكن إنتاج ذلك بكفاءة أفضل لكنها أغلى بكثير من التحسينات الآلية. بما أن العديد من المعاملات تؤثر على أداء البرنامج فإن مساحة تحسين البرنامج تكون أكبر. تُستخدم الاستدلالات المتغيرة والتعلم الآلي لمعالجة تعقيد تحسن البرنامج.
يعد استخدام المحلل (أو محلل الأداء) لإيجاد أقسام البرنامج التي تأخذ أكبر قدر من الموارد هو سبب المشكلة. يعتقد المبرمجين أحيانًا أنهم لديهم فكرة واضحة حول سبب المشكلة ؛ لكن بديهيًا كثيرًا ما يكون خطأ. لن يؤدي تحسين الأجزاء غير المهم لجزء الشفرة عادةً إلى المساعدة القليلة للبرنامج بأكمله.
عندما يتم تحديد سبب المشكلة يمكن أن يبدأ التحسين بإعادة التفكير في الحلول الحسابية المستخدمة في البرنامج. في بعض الأحيان؛ يمكن عمل الحلول الحسابية المعينة المصممة خصيصًا لمشكلة محددة والتي تقدم أداء أفضل من الحلول الحسابية العامة. على سبيل المثال؛ عادة ما تتم مهمة فرز قائمة كبيرة من العناصر بواسطة الفرز السريع المعتاد والذي يعد أحد الحلول الحسابية الأكثر كفاءة. لكن إذا كانت بعض خصائص العناصر قابلة للاستغلال (على سبيل المثال؛ أن تم ترتيبها بنظام معين) فيمكن استخدام طريقة أخرى أو حتى الفرز المعتاد حسب الطلب.
بعد أن يتأكد المبرمج بشكل معقول أنه تم اختيار أفضل الحلول الحسابية فيمكن البدء في تحسين الشفرة. يمكن أن تكون الحلقات مفتوحة (للحلقة السفلية في الأعلى، على الرغم من أنه يمكن أن يؤدي غالبًا إلى انخفاض السرعة بالرغم من أنه يزيد من سعة التخزين المؤقت لوحدة المعالجة المركزية) ويمكن استخدام أنواع البيانات الصغيرة قدر الإمكان كما يمكن استخدام الحلول الحسابية الصحيحة بدلا من النقاط الزائفة وغير ذلك.
يمكن أن يكون سبب المشكلة بسبب قيود اللغة بدلا من الحلول الحسابية أو هياكل البيانات المستخدمة في البرنامج. في بعض الأحيان؛ يمكن إعادة كتابة الجزء المهم من البرنامج بلغة برمجة مختلفة والتي تؤدي إلى الوصول المباشر للألة الأساسية. على سبيل المثال؛ إنه من الشائع في اللغات العالية جدا في المستوي مثل Python أن تحتوي على وحدات مكتوبة في C للحصول على سرعة أكبر. يمكن للبرامج المكتوبة بالفعل في C أن يكون لها وحدات مكتوبة في لغة التجميع. يمكن للبرامج  المكتوبة في D استخدام المُجمع.
تُثمر أقسام إعادة الكتابة في هذه الظروف بسبب "الطريقة المجربة" العامة المعروفة بقانون 90/10 والذي ينص على أن 90% من الوقت يتم استغراقه في 10% من الشفرة و10% فقط من الوقت في 90% من الشفرة المتبقية. لذا فإن تركيز الجهد الفكري على تحسين جزء صغير من البرنامج يمكن أن يؤثر بصورة كبيرة على السرعة الكلية—إذا كان من الممكن تحديد الجزء (الأجزاء) الصحيحة.
يكون للتحسين اليدوي في بعض الأحيان أثار جانبية على إمكانية القراءة وبالتالي يجب أن تُوثق تحسينات الشفرة بعناية وتأثيرها على التطوير المستقبلي المُقَدر.
يسمي البرنامج الذي يقوم بالتحسين الآلي المُحسن. تُدمج المُحسنات مع المُحللات وتعمل أثناء التجميع. يمكن للمُحسنات غالبًا تصميم الشفرة التي تم إنشاؤها للمعالجات الخاصة.
اليوم؛ تقتصر التحسينات الآلية غالبًا على التحسين المُجمع وذلك بسبب أن التحسينات المُجمعة تقصر عادة على مجموعة ثابتة إلى حد ما من التحسينات العامة حيث يوجد طلب كبير على المُحسنات التي يمكنا قبول أوصاف المشكلة ولغة التحسينات المحددة والتي تسمح للمهندس بتعيين التحسينات المخصصة. تسمي الأدوات التي تقبل أوصاف التحسينات بأنظمة تحويل البرامج والتي بدأ تطبيقها في أنظمة البرمجيات الحقيقة مثل C++.
تُحسن بعض اللغات عالية المستوي (Eiffel، Esterel) برامجها باستخدام لغة وسيطة.
تهدف الحوسبة الشبكية أو الحوسبة الموزعة إلى تحسين النظام بأكمله، من خلال نقل المهام من أجهزة الكمبيوتر ذات الاستخدام العالي إلى أجهزة الكمبيوتر التي تعمل بوقت العطل.

الوقت المستغرق للتحسين

في بعض الأحيان؛ قد يكون الوقت المستغرق في التحسين هو المشكلة في حد ذاته.
لا يؤدي تحسين الشفرة الحالية إلى إضافة مميزات جديدة ولكنه ربما يضيف أخطاء جديدة إلى الشفرة التي كانت تعمل من قبل. وذلك لأن الشفرة المُحسنة يدويًا ربما تحتوي أحيانًا على "قابلية قراءة" أقل من الشفرة غير المُحسنة وبالتالي يؤثر التحسين على إمكانية الحفاظ عليها. يكون للتحسين سعر كما يجب التأكد من أن الاستثمار يستحق العناء.
ربما يكون المُحسن الآلي نفسه (أو برنامج الترجمة الخاص بالتحسين وهو البرنامج الذي يقوم بأداء تحسين الشفرة) تم تحسينه إما لزيادة تحسين الكفاءة المستهدفة أو زيادة السرعة الخاصة بالتشغيل. عادةً ما يستغرق الأداء التجميع مع التحسين وقتًا طويلا بالرغم من أنه المشكلة الوحيدة عادة عندما تكون البرامج كبيرة جدا.
على وجه الخصوص؛ بالنسبة لبرامج الترجمة المجمعة في الوقت المحدد يكون أداء مكون التجميع وقت التشغيل والذي يتم تنفيذه مع شفرته المستهدفة وهو أساس تحفيز سرعة التنفيذ الكلية .