درخواست های ارتباط
جستجو
لیست دوستان من
صندوق پیام
همه را دیدم
  • در حال دریافت لیست پیام ها
صندوق پیام
رویدادها
همه را دیدم
  • در حال دریافت لیست رویدادها
همه رویدادهای من
دوره های مرتبط
دوره آموزشی ساخت ربات تلگرام
مدرس: taghandiki
این دوره را در 8 قسط خریداری کنید
ساخت و مدیریت ربات تلگرام از صفر با زبان سی شارپ
مدرس: مهدی عادلی
این دوره را در 2 قسط خریداری کنید
دوره آموزشی مقدماتی برنامه نویسی به زبان سی شارپ
مدرس: حسین احمدی
این دوره را در 17 قسط خریداری کنید
دوره آموزشی پردازش متن با زبان برنامه نویسی پایتون
مدرس: taghandiki
این دوره را در 20 قسط خریداری کنید
دوره آموزشی برنامه نویسی حرفه ای پایتون به زبان ساده
مدرس: حسین احمدی
این دوره را در 23 قسط خریداری کنید
دوره آموزشی برنامه نویسی اندروید با زبان جاوا به زبان ساده
مدرس: مهدی عادلی
این دوره را در 27 قسط خریداری کنید
دوره آموزشی طراحی رابط کاربری با JavaFX
مدرس: hharddy
این دوره را در 13 قسط خریداری کنید
دوره آموزشی برنامه نویسی به زبان پرل بصورت پروژه محور
مدرس: dr-iman
این دوره را در 13 قسط خریداری کنید
دوره آموزشی مقدماتی برنامه نویسی جاوا به زبان ساده
مدرس: مهدی عادلی
این دوره را در 17 قسط خریداری کنید
دوره آموزشی Exploit نویسی به زبان Perl
مدرس: dr-iman
این دوره را در 7 قسط خریداری کنید

مقایسه حلقه های For ، Foreach و Lambda Foreach

0 نظرات
103 بازدیدها
For و Foreach تفاوت کمی در Performance دارند و سرعت آنها تقریبا برابر است. اما حلقه Foreach از فضای پشته بیشتری برای متغیرهای محلی استفاده می کند. در این مقایسه سعی میکنیم تفاوت دقیق این دوحلقه را بفهمیم.
مقایسه
ابتدا نگاهی به حلقه For (متد1) می اندازیم و پس از آن حلقه Foreach (متد2)
هر دو متد مجموع یک آرایه را بر می گردانند.

For loop version: Method1
static int Method1(int[] array)
{
    int a = 0;
    for (int i = 0; i < array.Length; i++)
    {
	a += array[i];
    }
    return a;
}



Foreach loop version: Method2

static int Method2(int[] array)
{
    int a = 0;
    foreach (int value in array)
    {
	a += value;
    }
    return a;
}


تفاوت
در دات نت 4 یک تفاوت بین این دو در IL (Intermediate Language) وجود دارد. در Method1 از فضای پشته کافی برای دو متغیر استفاده شده است. (متغیر a و i). Method2 فضای پشته برای چهار متغیر استفاده می کند (a، value و دو متغیر موقت ساخته شده توسط کامپایلر)
وقتی یک متد در CLR (Common Language Runtime) فراخوانی می شود تمام حافظه مورد نیاز متغیرهای محلی بر روی پشته اختصاص داده می شود و به این دلیل که این اختصاص فضا داخل پشته انجام میگیرد سریعتر می باشد اما این عمل بدون هزینه نیست.
بنابراین حلقه Foreach فضایی بیش از دو متغیر در نمونه یاد شده اشغال می کند.
حالا این دو متد را آزمایش می کنیم.

کد 1:
using System;
using System.Diagnostics;

class Program
{
    static void Main()
    {
	int[] array = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	Method1(array);
	Method2(array);

	var s1 = Stopwatch.StartNew();
	const int m = 100000000;
	for (int i = 0; i < m; i++)
	{
	    Method1(array);
	}
	s1.Stop();
	var s2 = Stopwatch.StartNew();
	for (int i = 0; i < m; i++)
	{
	    Method2(array);
	}
	s2.Stop();
	Console.WriteLine(((double)(s1.Elapsed.TotalMilliseconds *
	    1000000) / m).ToString("0.00 ns"));
	Console.WriteLine(((double)(s2.Elapsed.TotalMilliseconds *
	    1000000) / m).ToString("0.00 ns"));
	Console.Read();
    }
}


*خروجی
7.37 ns
8.04 ns*


نتیجه حلقه for سریعتر از حلقه Foreach می باشد.
کد 2:
متغیرهای محلی اضافی موجود در حلقه Foreach باعث کند شدن این حلقه در حالت ساده آن می شوند. هر چند که این امکان وجود دارد تا از این متغیرهای اضافی به سود خودمان استفاده کنیم.
حالا متدهای بالا را را تغییر می دهیم و به جای دسترسی به آرایه ازطریق یک عبارت، یک بار دیگر آن عبارت را تکرار میکنیم. در حقیقت ما دوبار در حلقه به آرایه دسترسی پیدا میکنیم.
متد 1
static int Method1(int[] array)
{
    int a = 0;
    for (int i = 0; i < array.Length; i++)
    {
	a += array[i];
	a += array[i];
    }
    return a;
}



متد 2
static int Method2(int[] array)
{
    int a = 0;
    foreach (int value in array)
    {
	a += value;
	a += value;
    }
    return a;
}


کد اصلی را دوباره با متدهای جدید اجرا میکنیم.
*خروجی
7.71 ns
7.69 ns*


نتیجه جدید
حلقه for به میزان کمی از حلقه foreach کندتر عمل کرد. این بدین خاطر است که متغیرهای محلی که مقادیر عناصر آرایه را در خود ذخیره میکنند سریعتر از دسترسی به مقادیر ازطریق اندیس ها می باشند.
جمع بندی
معرفی متغیرهای اضافی در حلقه های foreach می تونه performance رو تحت تاثیر قرار بده. هر چند اگر از این متغیر ها به دفعات در یک حلقه استفاده شود می تواند عاملی برای بهبود performance باشد.
بنابراین حلقه for در زمانی که فقط یک بار به یک آرایه از طریق اندیس آن دسترسی داسته باشیم سریعتر می باشد.

استفاده از Lambda Foreach

Lambda Foreach عمکردی بسیار بهتری نسبت به Foreach معمولی دارد.
در مثال زیر ما لیستی از اعداد را با استفاده از سه روش پیاده سازی می کنیم:

روش اول: استفاده از دستور Foreach
var ListOfNumber = new List<int>() { 100, 200, 300, 400, 500 };
foreach (var number in ListOfNumber)
{
       Console.WriteLine(number);
}


روش دوم: استفاده از Lambda ForEach (تولید شده برای IEnumeratorها)
var ListOfNumber = new List<int>() { 100, 200, 300, 400, 500 };
ListOfNumber.ForEach(number => 
{ 
       Console.WriteLine(number); 
}
);


روش سوم : استفاده از متد ForEach در آرایه
int[] arrayOfNumbers = new int[] { 100, 200, 300, 400, 500 };
Array.ForEach<int>(arrayOfNumbers, (int counter) => 
{ 
       Console.WriteLine(counter); 
}
);


نتیجه اجرای دستورات بالا نشون میده که بیشترین سرعت رو روش دوم داره و در کل استفاده از Lambda Foreach از دستور Foreach سرعت بالاتری دارد.
روش سوم و استفاده از Array.Foreach سرعت کمتری نسبت به List.Foreach دارد و دلیل آن هم اینه که کامپایلر هنگام کار با آرایه‌ها و اجرای اون‌ها به صورت حلقه، کد IL خاصی رو تولید می‌کنه که مخصوص کار با آرایه هاست و سرعت اون به مراتب از سرعت کد IL تولید شده برای IEnumeratorها پایین تره.

موفق باشید

منابع:
MSDN
DotNetPerls
برچسب ها
مطالب مرتبط

در حال دریافت اطلاعات

نظرات
هیچ نظری ارسال نشده است

    برای ارسال نظر ابتدا به سایت وارد شوید

    arrow