تقييم الموضوع :
  • 0 أصوات - بمعدل 0
  • 1
  • 2
  • 3
  • 4
  • 5
تحسين الأداء-أفكـــار و تلميحات
#1
كاتب الموضوع : Marwan




السلام عليكم و رحمة الله وبركاته

هذا المقال عبارة عن ترجمة غير حرفية لهذا المقال http://msdn.microsoft.com/en-us/library/ms973839.aspx

ما أخذته من المقال هو الأفكار الرئيسية و الأمثلة ثم قمت بشرحها بطريقتي



1-أفكار عامة لتحسين الأداء لكل البرامج
2-أفكار لتحسين الأداء عند التعامل مع قواعد البيانات
3-أفكار لمبرمجي vb.net


1-أفكار لكل البرامج

  • لا تكثر من رمي الاستثناءات (Throwing Exeptions)
رمي الاستثناءات يستهلك الكثير من موارد النظام لذا تأكد دوما من عدم رمي الكثير من الاستثناءات.
يمكنك التأكد من هذا الأمر باستخدام الكود التالي:
أنشئ مشروعا جديدا من نوع Console Application
في الإجراء Main اكتب الكود التالي:


كود :
Console.WriteLine(Date.Now.ToString)
Dim j As Integer = 0

For i As Integer = 0 To 5000
Try
j = i

Throw New Exception
Catch ex As Exception

End Try
Next
Console.WriteLine(j.ToString)
Console.WriteLine(Date.Now.ToString)
Console.Read()
المثال بسيط: قمنا برمي 5000 استثناء عبر حلقة For Next و قمنا بتسجيل الوقت قبل بداية الحلقة و بعد
نهايتها.
الآن احسب الفرق بين الوقتين لتعرف كم استغرق تنفيذ الكود.
بالنسبة لي استغرق 19 ثانية(قد تختلف النتيجة حسب سرعة المعالج).

الآن احذف السطر Throw New Exception ثم أعد تشغيل البرنامج.
هل لاحظت الفرق؟ لقد استغرق تنفيذ الحلقة(5000 دورة) أقل من ثانية.
لذلك في مشاريعك الحقيقة تأكد دوما من الفئات التي تستخدمها عن ما هي الاستثناءت التي ترميها فان كان
عددها قليلا فعندئذ يمكنك السيطرة على الاستثناءات و التأكد من أنها لن ترمى بحال من الأحوال (باستخدام
جمل الشرط أو غيرها)،أما ان كان عدد الاستثناءات كبيرا فليس لك مخرج الا استعمال التركيب Try و الذي
لن يحول دون رمي الاستثناءات من الكود الذي يحمله لكنه سيمكنك من قنص هذه الاسنثناءات لتتمكن
من معالجهتها في الجزء Catch من التركيب Try.


  • استخدم المتغيرات ذات القيمة(Value Types
حاول دائما استخدام السجلات(structures) كل ما أمكن فهي من الأنواع ذات القيمة، أي أن قيم أعضاء هذه الأنواع تخزن في قسم Stack من الذاكرة و الذي يعتبر أسرع في التعامل معه من القسم Heap.بينما الأنواع المرجعية تخزن قيم أعضائها في القسم Stack إلاّ أن الـCLR يتعامل معها من خلال مؤشر الكائن الموجود في القسم Heap من الذاكرة.
للتأكد من الفرق في السرعة بين استخدام الانواع ذات القيمة و الأنواع المرجعية أنشئ مشروعا جديدا
من نوع Console Application ثم أضف الكود التالي:


كود :
Sub Main()
Console.WriteLine("class loop begun" & Date.Now.ToString)
For i = 0 To 50000000
Dim test As New cls(3.14)
Next
Console.WriteLine("class loop completed" & Date.Now.ToString)

Console.WriteLine("structure loop begun" & Date.Now.ToString)
For i = 0 To 50000000
Dim test As New struct(3.14)
Next
Console.WriteLine("structure loop completed" & Date.Now.ToString)
Console.Read()
End Sub

Class cls
Public y As Double


Private newPropertyValue As String
Sub New(ByVal value As Double)
Me.y = value
End Sub


End Class
Structure struct
Public y As Double

Sub New(ByVal value As Double)
Me.y = value
End Sub

End Structure
الكود عبارة عن حلقة بـ50 مليون دورةفي الحلقة الأولى قمنا بتعريف متغير من النوع المرجعي و سجلنا الوقت قبل بداية الحلقة و بعد نهايتها.في الحلقة الثانية قمنا بتعريف متغير من النوع ذي القيمة و سجلنا الوقت قبل بداية الحلقة و بعد نهايتها.

بعد حساب الوقت المستغرق لكل دورةتحصلت على النتيجة التالية:



بهذا يتبين لك الفرق الشاسع بين الأنواع ذات القيمة و الأنواع المرجعية من ناحية السرعة في التعامل معها.
ضع في عين الاعتبار أن الكائنات التي تحتوي على حقول و خصائص(Fields and Properties) أكثر فان التعامل معها يصبح أبطأ ليس مثل هذاالبرنامج البسيط حيث أن كل كائن يحتوي على حقل واحد.
لكن هنا يجب التنبيه على نقطة مهمة و التي قد تقلب الموازين: وهي سوء استخدام الأنواع ذات القيمة مما قد يؤدي إلى بطئ في الأداء بحيث لو أننا استخدمنا الأنواع المرجعية لكان الاداء أسرع، وهي قضية الصندقة و اللاصندقة(Boxing,Unboxing).

-الصندقة: و هي عملية اسناد متغير من النوع ذو القيمة الى متغير من النوع المرجعي.
-اللاصندقة: و هي تحدث عند استخدام المتغير بعد عملية الصندقة أو عملية اسناد متغير من النوع المرجعيالى متغير من النوع ذو القيمة.

تحدث عملية الصندقة مثلا في الحالات التالية:
-ارسال متغير من النوع ذو القيمة الى اجراء يستقبل وسيطة من النوع Object
-اضافة متغير من النوع ذو القيمة الى مجموعة Collection (الا اذا قمت باستغلال الـGenerics)

عملية الصندقة و اللاصندقة تؤدي الى استهلاك كبير من موارد النظام.
4 ثواني للحلقة الأولى 1 ثانية للحلقة الثانية


  • استخدم AddRange بدلا من Add عند اضافة عدّة عناصر الى مجموعة
عندما تريذ اضافة عناصر الى مجموعة ما استخدم دوما الطريقة AddRange الموجودة في الكثير من الفئات بدلا من استخدام الطريقة Add داخل حلقة تكرارية.فهذه الأخيرة مفيدة عندما تريد اضافة عنصر واحد للمجموعة بينما الأولى أفضل أداءا لإضافة عدة عناصر الى مجموعة في خطوة واحدة.


  • استخدم StringBuilder عند اجراء عمليات كثيرة على النصوص
يمكنك الاطلاع على درس الأخ أحمد جمال هنا http://vb4arb.com/vb/showthread.php?729


  • حول البرنامج الى لغة الآلة قبل توزيعه
طبعا كلنا نعرف أن البرنامج المبرمج باحدى لغات الدوت نت يحول الى لغة ميكروسوفت الوسيطة(MSIL).ثم عند تشغيل البرنامج فان الـJIT Compiler يقوم بتحويل هذا الكود الى لغة الآلة،لكنه لا يقوم بترجمة كامل البرنامج إنما عند كل استدعاء لأي طريقة فان الـJIT Compiler يقوم بترجمتها الى لغة الآلة(لهذا سميJust In Time Compiler --->الترجمة الفورية).طبعا هذا سيؤدي الى بطئ عند أول استدعاء للطريقة، ثم تخيل أن برنامجك يقوم باستدعاء العديد من الدوال عند بداية التشغيل،هذا سيؤدي الى بطئ شديد عند أول تشغيل للبرنامج.

توفر ميكروسوفت تطبيقا يمكنك من ترجمة برنامجك إلى لغة الآلة كاملا و هو التطبيق ngen.exe(Native Image Generator)
ملاحظة:هذا لا يعني عدم الحاجة الى الدوت نت فريمورك على الحهاز لكي يعمل التطبيق.
يمكنك استخدام هذا التطبيق عن طريق سطر الأوامر Command Line و هو موجود على المسار C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727

لتحويل مجمع الى كود الآلة استخدم سطر الأوامر التالي:

كود :
install [assembly Name or assembly Path]

لارجاع المجمع الى حالته الأصلية:

كود :
uinstall [assembly Name or assembly Path]

لعرض حالة المجمع

كود :
display [assembly Name or assembly Path]

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



  • استخدم التنفيذ اللامتزامن(Asynchronous Execution) للعمليات الطويلة على وحدات التخزين(Steams)
التنفيذ المتزامن (Synchronous Execution) هو التنفيذ سطر بسطر يعني أن المعالج لا ينتقل الى العملية التالية الا عند انتهاء العملية الحالية.
التنفيذ اللامتزامن يعني أنه من الممكن تنفيذ الكود الحالي في خلفية البرنامج(في مسار جديد) بينما يواصل البرنامج تنفيذ الكود التالي في نفس الوقت.

تحتاج الى التنفيذ اللامتزامن كثيرا عندما تعمل على قراءة و نقل وحدات تخزين بشكل كبير(مثل قراءة و نقل الملفات الكبيرة الحجم سواء على نفس الجهاز أو عبر الشبكة).لذلك فان كل الفئات التي تجري عمليات على وحدات التخزين(مثلا:FileStream,WebRequest,NetworkStream.. .) تدعم كلا النوعين المتزامن و اللامتزامن عبر الطرق:
التنفيذ المتزامن التنفيذ اللامتزامن
BeginRead Read
BeginWrite Write

طبعا في التنفيذ اللامتزامن يجب عليك كتابة الكود المناسب يدويا لاعلامك بانتهاء التنفيذ و يتم ذلك من خلال ارسال مفوض(Delegate) إلى الاجراء الذي سيتم استذعائه عند انتهاء التنفيذ، كوسيطة للطريقةBeginRead مثلا.ويمكنك أن تضع في هذا الاجراء الكود المناسب لاعلامك بانتهاء التنفيذ كأن تظهر رسالة مثلا.
في المثال التالي استخدمت التنفيذ اللامتزامن لاستخراج كود HTML للصفحة الرئيسية للمنتدى،طبعا لو استخدمت التنفيذ اللامتزان لاستغرق هذ و قتا و لأدى الى تجمد الفورم في البرنامج.
قم بانشاء مشروع جديد من نوع Windows Form ثم أضف
TextBox
Button
RichtextBox

الآن أضف الكود التالي ثم شغل البرنامج و اكتب في مربع النص http://www.vb4arb.com
ٌBeginRead Read

كود :
Imports System.IO
Imports System.Net
Imports System.Text

Public Class Form1

Dim wr As HttpWebRequest
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Control.CheckForIllegalCrossThreadCalls = False

wr = HttpWebRequest.Create(TextBox1.Text)

Dim delg As AsyncCallback = AddressOf callback

wr.BeginGetResponse(delg, Nothing)

End Sub

Sub callback(ByVal i As IAsyncResult)
Dim resp As HttpWebResponse = CType(wr.EndGetResponse(i), HttpWebResponse)

Dim sr As New StreamReader(resp.GetResponseStream, Encoding.GetEncoding(1256))
RichTextBox1.Text = sr.ReadToEnd

End Sub
سأقوم بكتابة بقية الدرس غدا أو بعد غد ان شاء الله
}}}}
تم الشكر بواسطة:


المواضيع المحتمل أن تكون متشابهة .
الموضوع : الكاتب الردود : المشاهدات : آخر رد
  تلميحات بدرميديا RaggiTech 0 203 03-10-12, 11:04 AM
آخر رد: RaggiTech
  افتراضي linQ to sql data الأستعلام من خلال لينك. وروعتها فى الأداء RaggiTech 0 813 02-10-12, 08:14 AM
آخر رد: RaggiTech
  سلسلة تقنيات تحسين واجهات البرامج - النوافذ الطبقية RaggiTech 1 562 01-10-12, 04:55 PM
آخر رد: RaggiTech

التنقل السريع :


يقوم بقرائة الموضوع: بالاضافة الى ( 1 ) ضيف كريم