سؤال

أنا أشير إلى هذه المناقشة. لم أكتب أي رمز في C أو في C ++. ليس لدي أي خلفية CS. ومع ذلك ، كنت أعمل كمطور Java لمدة 5 سنوات ، والآن قررت معرفة المزيد عن CS والقيام ببعض اللحاق بالركب.

هل كانت مفيدة؟

المحلول

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

inlining يحل مشكلة الأداء والصيانة من خلال السماح لك بتصريح الوظيفة كـ في النسق (على الأقل في C ++) ، بحيث عند استدعاء هذه الوظيفة - بدلاً من أن يقفز التطبيق الخاص بك في وقت التشغيل - يتم حقن الكود في الوظيفة المضمنة في وقت الترجمة في كل مرة يتم فيها استدعاء الوظيفة المعطاة.

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

نصائح أخرى

http://en.wikipedia.org/wiki/inlining

في الحوسبة ، يعد التوسع المضمّن ، أو الإطار ، تحسين برنامج التحويل البرمجي الذي يحل محل موقع استدعاء الوظيفة بجسم Callee. قد يحسن هذا التحسين استخدام الوقت والمساحة في وقت التشغيل ، بتكلفة محتملة لزيادة حجم البرنامج النهائي.

كمطور Java ، لا داعي للقلق عمومًا بشأن تحديد الطريقة. يمكن لجولر جافا في الوقت المناسب أن يفعل ذلك تلقائيًا في معظم الأماكن التي من المنطقي.

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

نورمان مورير يشرح في له مقالات JVM و JIT وظيفية مضمنة من هذا القبيل

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

أيضا مع تحذير

ولكن حتى لو اعتبر JVM أن الطريقة "ساخنة" قد لا تضمنها. لكن لماذا؟ أحد الأسباب الأكثر ترجيحًا هو أنه كذلك فقط إلى كبيرة للحصول على inline.

ويمكنك العثور على مثال رمز بسيط للغاية لتحديد رمز Java على إيفا أندرياسسونبوست جافا وورلد. يمكنك العثور على الجزء ذي الصلة من المنشور في أدناه.

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

قائمة 3. طريقة المتصل

int whenToEvaluateZing(int y) {
   return daysLeft(y) + daysLeft(0) + daysLeft(y+1);
}

قائمة 4. تسمى الطريقة

int daysLeft(int x){
   if (x == 0)
      return 0;
   else
      return x - 1;
}

قائمة 5. طريقة مضمونة

int whenToEvaluateZing(int y){
   int temp = 0;

   if(y == 0) temp += 0; else temp += y - 1;
   if(0 == 0) temp += 0; else temp += 0 - 1;
   if(y+1 == 0) temp += 0; else temp += (y + 1) - 1;

   return temp; 
}

في القوائم من 3 إلى 5 ، تقوم طريقة الاتصال بثلاث مكالمات إلى طريقة صغيرة ، والتي نفترضها من أجل هذا المثال أكثر فائدة للمضمنة من القفز إلى ثلاث مرات.

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

الإدراج 6. بعد التحضير ، يمكن تطبيق المزيد من التحسينات

int whenToEvaluateZing(int y){
   if(y == 0) return y;
   else if (y == -1) return y - 1;
   else return y + y - 1;
}

كما ذكرنا سابقًا في إجابات أخرى ، يأتي الإطار بتكلفة. عادةً ما يعتبر هذا صغيرًا ، ولكن عند القياس فعليًا قد تفاجأ وتعلم أنه قد يكون أكبر مما تكسبه (هكذا ماذا يقول الآخرون صحيح: لا تحسن إلا إذا كنت قد تم قياسها).

تجدر الإشارة إلى أنه في kernel في Linux ، بدأوا في التخصيص في الأصل وظائف مضمّنة في الأصل منذ بعض الوقت لأن التكلفة كانت مرتفعة للغاية (كانت الوظائف الكبيرة تستهلك أكثر من ذاكرة التخزين المؤقت لذاكرة وحدة المعالجة المركزية ، وكانت أخطاء ذاكرة التخزين المؤقت الناتجة أكثر تكلفة من مجرد تسمية الوظيفة التي كانت تهدف إلى أن تكون مضمون). انظر "الفصل 15: مرض مضمّن" في Doc/Documentation/Process/Coding-style.rst لمزيد من التفاصيل.

في الأساس ، في C/C ++ ، يمكن للمترجم وظائف ، مما يعني أنه بدلاً من إجراء استدعاء دالة للقيام بهذه العملية ، سيتم إضافة الكود إلى كتلة وظيفة الاتصال ، لذلك سيكون كما لو أنه لم يكن أبدًا منفصلًا استدعاء وظيفة.

هذا سوف يذهب إلى مزيد من التفاصيل:http://www.codersource.net/cpp_tutorial_inline_functions.html

يشير Inlining إلى تحسين وقت التجميع حيث سيتم حقن وظيفة صغيرة من التعليمات البرمجية في وظيفة الاتصال بدلاً من طلب مكالمة منفصلة.

إجابات التحسين المترجم صحيحة. هناك استخدام آخر ، على الرغم من - في إعادة بناء التعليمات البرمجية, ، يشير Inlining إلى استبدال استدعاء الطريقة بجسم الطريقة ثم إزالة الطريقة. يرى طريقة مضمنة. هناك refactors مماثلة ، مثل فئة مضمنة.

تحرير: لاحظ أن إعادة التجديد تتم يدويًا أو بأداة ؛ في كلتا الحالتين ، يتضمن تغيير رمز المصدر.

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

في هذه المناقشة ، يذكر Jon Skeet Client JVM (نقطة Hotspot) V Server JVM مع تحسينات الأداء المتاحة في وقت التشغيل إذا سمح لمترد JIT (في الوقت المناسب) بإحضار التحسينات القائمة على الوقت. هذا هو "كيف يتم ذلك" في جافا.

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

اليوم ، تتم إزالة Singleton موضوع مناقشات متعددة الصفحات وتجميع الحلقة وكذلك شيء مثل الإضفاء يمكنك قراءة عمل DOV Bulka المستنيرة للغاية في هذا الشأن للحصول على C/C ++ في الأمر. بالنسبة إلى Java ، فإن دراسة LIB الغنية في Java.Util من شأنها أن تخدم احتياجاتك بشكل أفضل من دراسة القضايا المبرممة والمترجم العميق - يمكنك التعليق في الحرب الداخلية المحاصرة الراسخة على هياكل البيانات ، التي تتلألأ على المكالمات إلى رمز 16 بت ، و لا تنتهي من منحنى التعلم الخاص بك.

يمكنك القيام بمثابرة في Java ، والتي تشبه جدول VF (لا يوجد أشخاص حرارة ، من فضلك) ولكن فكر في الأمر كما كنت تكتب بلغة مكتوبة بقوة - والآن ستنكيد بلغة حيث يمكن للسلسلة أن تهرب بسهولة حيث ليس لديها عمل. لقد حاولت مؤخرًا كتابة التعليمات البرمجية التي صممت صورة في Java ، وأقوم بذلك من رمز C. سرعان ما وجدت نفسي أبحث عن جدول Oxr للتشفير القوي - وهذا لا علاقة له بالرمز الذي كنت أكتبه.

كيف يمكنك كتابة فئة سلسلة في C/C ++ تحتوي على مخزن مؤقت صغير للسلاسل تحت 32 بايت ومؤشرات الفخاخ بحيث تعمل فقط على السلسلة؟

لا تحاول مضايقتك أو أي شيء ، إنه مجرد مكان جيد للبدء بدلاً من التحضير والعلوم المترجم.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top