সি # তে 'কাঠামো' এবং 'ফরচ' নিয়ন্ত্রণের কাঠামোর পারফরম্যান্স পার্থক্য


105

কোন কোড স্নিপেট আরও ভাল পারফরম্যান্স দেবে? নীচের কোড বিভাগগুলি সি # তে লেখা ছিল।

1।

for(int counter=0; counter<list.Count; counter++)
{
    list[counter].DoSomething();
}

2।

foreach(MyType current in list)
{
    current.DoSomething();
}

31
আমি কল্পনা করি যে এটি আসলে কোনও ব্যাপার নয়। আপনার যদি পারফরম্যান্সে সমস্যা হয় তবে এটি অবশ্যই এটির কারণে নয়। আপনি প্রশ্ন জিজ্ঞাসা করা উচিত নয় যে ...
darasd

2
আপনার অ্যাপটি যদি খুব কার্য সম্পাদন না করে সমালোচনা না করে তবে আমি এই বিষয়ে চিন্তা করব না। পরিষ্কার এবং সহজে বোধগম্য কোড থাকা আরও ভাল।
ফরটিআরুনার

2
এটি আমার উদ্বেগজনক যে এখানে কিছু উত্তর এমন লোকদের দ্বারা পোস্ট করা হয়েছে যা তাদের মস্তিস্কের কোথাও কেবল পুনরাবৃত্তির ধারণা নেই, এবং সেইজন্য গণক বা পয়েন্টারগুলির কোনও ধারণা নেই।
এড জেমস

3
২ য় কোডটি সংকলন করবে না। সিস্টেম.অজেক্টের 'মান' নামে কোনও সদস্য নেই (যদি আপনি সত্যই দুষ্ট না হন তবে এটি একটি এক্সটেনশন পদ্ধতি হিসাবে সংজ্ঞায়িত করেছেন এবং প্রতিনিধিদের তুলনা করছেন)। দৃ fore়ভাবে আপনার ভবিষ্যদ্বাণী টাইপ করুন।
ট্রিলিয়ান

1
প্রথম কোডটি কোনওটিই সংকলন করবে না, যদি না ধরণের listপ্রকৃতপক্ষে এর countপরিবর্তে সদস্য থাকে Count
জন স্কিটি

উত্তর:


130

ঠিক আছে, এটি আংশিকভাবে সঠিক ধরণের উপর নির্ভর করে list। এটি আপনি যে সঠিক সিএলআর ব্যবহার করছেন তার উপরও নির্ভর করবে।

এটি কোনওভাবেই তাৎপর্যপূর্ণ কিনা তা নির্ভর করে আপনি লুপটিতে কোনও আসল কাজ করছেন কিনা তার উপর নির্ভর করবে। প্রায় সব ক্ষেত্রেই পারফরম্যান্সের পার্থক্যটি তাৎপর্যপূর্ণ হবে না, তবে পঠনযোগ্যতার পার্থক্য foreachলুপের পক্ষে ।

আমি "যদি" এড়াতে ব্যক্তিগতভাবে লিনকিউ ব্যবহার করতাম:

foreach (var item in list.Where(condition))
{
}

সম্পাদনা: আপনারা যারা দাবি করছেন যে একটি List<T>দিয়ে পুনরাবৃত্তি করা লুপের foreachমতো একই কোড তৈরি করে for, এখানে তার প্রমাণ রয়েছে যে এটি নেই:

static void IterateOverList(List<object> list)
{
    foreach (object o in list)
    {
        Console.WriteLine(o);
    }
}

এর আইএল উত্পাদন করে:

.method private hidebysig static void  IterateOverList(class [mscorlib]System.Collections.Generic.List`1<object> list) cil managed
{
  // Code size       49 (0x31)
  .maxstack  1
  .locals init (object V_0,
           valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<object> V_1)
  IL_0000:  ldarg.0
  IL_0001:  callvirt   instance valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<!0> class [mscorlib]System.Collections.Generic.List`1<object>::GetEnumerator()
  IL_0006:  stloc.1
  .try
  {
    IL_0007:  br.s       IL_0017
    IL_0009:  ldloca.s   V_1
    IL_000b:  call       instance !0 valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<object>::get_Current()
    IL_0010:  stloc.0
    IL_0011:  ldloc.0
    IL_0012:  call       void [mscorlib]System.Console::WriteLine(object)
    IL_0017:  ldloca.s   V_1
    IL_0019:  call       instance bool valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<object>::MoveNext()
    IL_001e:  brtrue.s   IL_0009
    IL_0020:  leave.s    IL_0030
  }  // end .try
  finally
  {
    IL_0022:  ldloca.s   V_1
    IL_0024:  constrained. valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<object>
    IL_002a:  callvirt   instance void [mscorlib]System.IDisposable::Dispose()
    IL_002f:  endfinally
  }  // end handler
  IL_0030:  ret
} // end of method Test::IterateOverList

সংকলকটি অ্যারেগুলি আলাদাভাবে আচরণ করে , একটি foreachলুপকে মূলত একটি লুপে রূপান্তরিত করে for, তবে তা নয় List<T>। এখানে অ্যারের সমতুল্য কোড:

static void IterateOverArray(object[] array)
{
    foreach (object o in array)
    {
        Console.WriteLine(o);
    }
}

// Compiles into...

.method private hidebysig static void  IterateOverArray(object[] 'array') cil managed
{
  // Code size       27 (0x1b)
  .maxstack  2
  .locals init (object V_0,
           object[] V_1,
           int32 V_2)
  IL_0000:  ldarg.0
  IL_0001:  stloc.1
  IL_0002:  ldc.i4.0
  IL_0003:  stloc.2
  IL_0004:  br.s       IL_0014
  IL_0006:  ldloc.1
  IL_0007:  ldloc.2
  IL_0008:  ldelem.ref
  IL_0009:  stloc.0
  IL_000a:  ldloc.0
  IL_000b:  call       void [mscorlib]System.Console::WriteLine(object)
  IL_0010:  ldloc.2
  IL_0011:  ldc.i4.1
  IL_0012:  add
  IL_0013:  stloc.2
  IL_0014:  ldloc.2
  IL_0015:  ldloc.1
  IL_0016:  ldlen
  IL_0017:  conv.i4
  IL_0018:  blt.s      IL_0006
  IL_001a:  ret
} // end of method Test::IterateOverArray

মজার বিষয় হচ্ছে, আমি এই নথিটি কোথাও C # 3 টিপিতে খুঁজে পাচ্ছি না ...


আগ্রহের বাইরে জোন, উপরে <T> তালিকার পরিস্থিতি ... এটি কি অন্যান্য সংগ্রহের ক্ষেত্রেও প্রযোজ্য? এছাড়াও, আপনি কীভাবে এটি জানতেন (কোনও বিদ্বেষ ছাড়া কোনও উদ্দেশ্য নেই) ... যেমনটি .. কিছুকাল আগে এই প্রশ্নের উত্তর দেওয়ার চেষ্টা করার সময় আপনি কি আক্ষরিক অর্থে হোঁচট খেয়েছিলেন? এটি এতটা ... এলোমেলো / গোপন :)
শুদ্ধ। ক্রোম

5
আমি কিছুক্ষণ অ্যারে অপটিমাইজেশন সম্পর্কে সচেতন ছিলাম - অ্যারেগুলি "কোর" ধরণের সংগ্রহ; সি # সংকলক ইতিমধ্যে তাদের সম্পর্কে গভীরভাবে সচেতন, সুতরাং তাদের সাথে অন্যরকম আচরণ করা বোধগম্য। সংকলকটির কোনও বিশেষ জ্ঞান নেই (এবং হওয়া উচিত নয়) List<T>
জন স্কিটি

চিয়ার্স :) এবং হ্যাঁ ... অ্যারে হ'ল প্রথম সংগ্রহের ধারণা যা আমি বহু বছর আগে এবং বহু বছর আগে ইউনিতে শিখিয়েছিলাম .. সুতরাং এটি অনুভূতি তৈরি করবে যে সংকলকটি সবচেয়ে আদিম ধরণের (যদি না হয়) এর সাথে মোকাবিলা করার জন্য যথেষ্ট স্মার্ট is সংগ্রহ। আবার চিয়ার্স!
বিশুদ্ধ.ক্রোম

3
@ জোনস্কিট তালিকার পুনরাবৃত্তির সময় অপরিবর্তনকারী আচরণটি পরিবর্তন করে যখন পুনরাবৃত্তির সময় তালিকাটি পরিবর্তন করা হয়। আপনি ব্যতিক্রম হারান - যদি-সংশোধিত হয়। এটি এখনও অপ্টিমাইজ করা সম্ভব, তবে এটি পরীক্ষা করা দরকার যে কোনও পরিবর্তন ঘটে না (অন্যান্য থ্রেড সহ আমি ধরে নিই)।
ক্রেগ গিডনি

5
@ উইকিবিবি: ২০০৪ সালে মাইক্রোসফ্ট বলেছিল a ক) বিষয়গুলি পরিবর্তিত হয়; খ) কাজটি উল্লেখযোগ্য হওয়ার জন্য প্রতিটি পুনরাবৃত্তির উপর ক্ষুদ্র পরিমাণে কাজ করতে হবে। নোট করুন যে foreachকোনও অ্যারের উপরে যে forকোনওভাবেই সমান । সর্বদা পঠনযোগ্যতার জন্য কোড আগে, তারপরে কেবল মাইক্রো অপ্টিমাইজ করুন যখন আপনার কাছে প্রমাণ রয়েছে যে এটি একটি পরিমাপযোগ্য পারফরম্যান্স সুবিধা দেয়।
জন স্কিটি

15

একটি forলুপ প্রায় এর সমান কোডে সংকলিত হয়:

int tempCount = 0;
while (tempCount < list.Count)
{
    if (list[tempCount].value == value)
    {
        // Do something
    }
    tempCount++;
}

যেখানে foreachলুপটি প্রায় সমতুল্য কোডটিতে সংকলিত হয়:

using (IEnumerator<T> e = list.GetEnumerator())
{
    while (e.MoveNext())
    {
        T o = (MyClass)e.Current;
        if (row.value == value)
        {
            // Do something
        }
    }
}

সুতরাং আপনি যেমন দেখতে পাচ্ছেন, এটি সমস্ত তালিকাভুক্তকারীকে কীভাবে তালিকাভুক্ত করা হয় তার বিপরীতে কীভাবে গণক কার্যকর করা হয় তার উপর নির্ভর করে। এটি অ্যারে উপর ভিত্তি করে প্রকারের জন্য সাধারণ হিসাবে সাধারণত কিছু লেখা হয়:

private static IEnumerable<T> MyEnum(List<T> list)
{
    for (int i = 0; i < list.Count; i++)
    {
        yield return list[i];
    }
}

আপনি যেমন দেখতে পাচ্ছেন, এই উদাহরণে এটি খুব বেশি পার্থক্য করবে না, তবে একটি লিঙ্কযুক্ত তালিকার গণক সম্ভবত এটির মতো দেখতে পাবেন:

private static IEnumerable<T> MyEnum(LinkedList<T> list)
{
    LinkedListNode<T> current = list.First;
    do
    {
        yield return current.Value;
        current = current.Next;
    }
    while (current != null);
}

ইন .NET আপনি যে LinkedList <টি> বর্গ এমনকি একটি indexer, নেই তাই আপনি একটি লিঙ্ক তালিকায় লুপ জন্য আপনার কাজ করতে সক্ষম হবে না পাবেন; তবে আপনি যদি পারতেন তবে সূচকটি এমনভাবে লিখতে হবে:

public T this[int index]
{
       LinkedListNode<T> current = this.First;
       for (int i = 1; i <= index; i++)
       {
            current = current.Next;
       }
       return current.value;
}

আপনি দেখতে পাচ্ছেন, লুপে এই একাধিকবার কল করা একটি এনুমিউরেটর ব্যবহারের চেয়ে ধীর গতিতে চলেছে যা তালিকায় এটি কোথায় রয়েছে তা মনে রাখতে পারে।


12

আধা-বৈধকরণের জন্য একটি সহজ পরীক্ষা। আমি একটি ছোট পরীক্ষা করেছি, শুধু দেখতে। কোডটি এখানে:

static void Main(string[] args)
{
    List<int> intList = new List<int>();

    for (int i = 0; i < 10000000; i++)
    {
        intList.Add(i);
    }

    DateTime timeStarted = DateTime.Now;
    for (int i = 0; i < intList.Count; i++)
    {
        int foo = intList[i] * 2;
        if (foo % 2 == 0)
        {
        }
    }

    TimeSpan finished = DateTime.Now - timeStarted;

    Console.WriteLine(finished.TotalMilliseconds.ToString());
    Console.Read();

}

এবং এখানে ভবিষ্যদ্বাণী বিভাগ:

foreach (int i in intList)
{
    int foo = i * 2;
    if (foo % 2 == 0)
    {
    }
}

আমি যখন ফরচটি প্রতিস্থাপন করলাম - ধারাবাহিকভাবে ফোরচটি 20 মিলিসেকেন্ডে দ্রুত ছিল । এর জন্য 135-139 মিমি ছিল, যখন পূর্বাঞ্চটি ছিল 113-119 মিমি। আমি বেশ কয়েকবার পিছনে ফিরে এসেছি এবং নিশ্চিত হয়েছি যে এটি এমন কোনও প্রক্রিয়া নয় যা কেবল লাথি মেরেছিল।

যাইহোক, যখন আমি foo এবং if স্টেটমেন্টটি সরিয়ে ফেললাম তখন এর জন্য 30 এমএস দ্রুত ছিল (অগ্রণীতাটি ছিল 88 মিমি এবং এর জন্য 59 মিমি)। তারা উভয় খালি খোল ছিল। আমি ধরে নিচ্ছি ভবিষ্যদ্বাণীটি আসলে একটি ভেরিয়েবল পাস করেছে যেখানে কেবল ভেরিয়েবলকে বাড়িয়ে দেওয়া হয়েছিল। আমি যদি যোগ করা হয়

int foo = intList[i];

তারপরে প্রায় 30 মিমি ধীরে ধীরে হয়ে যায়। আমি ধরে নিচ্ছি এটির সাথে foo তৈরি করা এবং অ্যারেতে ভেরিয়েবলটি দখল করা এবং এফওকে নির্ধারণ করার সাথে এটি করার ছিল। যদি আপনি কেবল ইনটলিস্ট অ্যাক্সেস করেন [i] তবে আপনার কাছে সেই দণ্ড নেই।

সমস্ত সততার সাথে .. আমি ভবিষ্যদ্বাণীটি সকল পরিস্থিতিতে সামান্য ধীর হওয়ার প্রত্যাশা করেছিল, তবে বেশিরভাগ অ্যাপ্লিকেশনে বিষয়টি যথেষ্ট নয়।

সম্পাদনা করুন: এখানে জোনস পরামর্শ ব্যবহার করে নতুন কোডটি দেওয়া হয়েছে (134217728 সিস্টেমের আগে আপনার কাছে থাকা সবচেয়ে বড় অন্তর্নিহিত .আউটআফ মেমরি ব্যতিক্রম ছুঁড়ে দেওয়া):

static void Main(string[] args)
{
    List<int> intList = new List<int>();

    Console.WriteLine("Generating data.");
    for (int i = 0; i < 134217728 ; i++)
    {
        intList.Add(i);
    }

    Console.Write("Calculating for loop:\t\t");

    Stopwatch time = new Stopwatch();
    time.Start();
    for (int i = 0; i < intList.Count; i++)
    {
        int foo = intList[i] * 2;
        if (foo % 2 == 0)
        {
        }
    }

    time.Stop();
    Console.WriteLine(time.ElapsedMilliseconds.ToString() + "ms");
    Console.Write("Calculating foreach loop:\t");
    time.Reset();
    time.Start();

    foreach (int i in intList)
    {
        int foo = i * 2;
        if (foo % 2 == 0)
        {
        }
    }

    time.Stop();

    Console.WriteLine(time.ElapsedMilliseconds.ToString() + "ms");
    Console.Read();
}

এবং ফলাফল এখানে:

ডেটা তৈরি হচ্ছে। লুপের জন্য গণনা করা হচ্ছে: 2458 মিমি ফরেনচ লুপ গণনা করছে: 2005 মিমি

এগুলির চারপাশে অদলবদল করে এটি দেখুন যাতে এটি ক্রমের সাথে একই ফলাফল দেয় (প্রায়)।


6
ডেটটাইম-এর চেয়ে এখন স্টপওয়াচ ব্যবহার করা ভাল honest সত্যবাদী হওয়ার জন্য আমি কোনও দ্রুত রান চালাতে বিশ্বাস করব না।
জন স্কিটি

8
আপনার ফোরচ লুপগুলি দ্রুত চলছে কারণ একটি 'for' প্রতিটি পুনরাবৃত্তির শর্তটি মূল্যায়ন করে। আপনার উদাহরণের ক্ষেত্রে, এটি একটি অতিরিক্ত পদ্ধতি কল করার জন্য তালিকা তৈরি করে (list.count পেতে) সংক্ষেপে, আপনি কোডের দুটি ভিন্ন টুকরা বেঞ্চমার্ক করছেন, সুতরাং আপনার অদ্ভুত ফলাফল। 'ইনট ম্যাক্স = ইন্টলিস্ট' চেষ্টা করুন ount (int i = 0; i <সর্বোচ্চ; i ++) এর জন্য ... 'এবং' ফর 'লুপটি সর্বদা দ্রুত প্রত্যাশিতভাবে চলবে!
এআর

1
সংকলনের পরে, প্রিমিটিভগুলির সাথে কাজ করার সময় ঠিক একই জিনিসটির জন্য এবং পূর্বাভাসটি অনুকূল করে তোলে। আপনি তালিকার <T> পরিচয় করিয়ে দেওয়া অবধি এই নয় যে তারা গতিতে পৃথক (ব্যাপকভাবে)।
অ্যান্টনি রাসেল

9

দ্রষ্টব্য: এই উত্তরটি জাভাতে C # এর চেয়ে বেশি প্রযোজ্য, যেহেতু সি # তে কোনও সূচক নেই LinkedLists, তবে আমি মনে করি সাধারণ পয়েন্টটি এখনও ধরে আছে।

তাহলে listআপনার সাথে কাজ থাকা একটি হতে হবে LinkedList, indexer-কোড (কর্মক্ষমতা অ্যারে-শৈলী অ্যাক্সেস করছেন) ব্যবহার তুলনায় অনেক খারাপ IEnumeratorথেকে foreach, বড় তালিকার জন্য।

যখন আপনি সূচক LinkedListসিনট্যাক্স ব্যবহার করে 10.000 উপাদানটি অ্যাক্সেস করেন : list[10000]লিঙ্কযুক্ত তালিকাটি মাথা নোড থেকে শুরু হবে এবং Nextদশমিক বার-পয়েন্টারটি অতিক্রম করবে , যতক্ষণ না এটি সঠিক অবজেক্টে পৌঁছে যায়। স্পষ্টতই, আপনি যদি লুপটিতে এটি করেন তবে আপনি পাবেন:

list[0]; // head
list[1]; // head.Next
list[2]; // head.Next.Next
// etc.

আপনি যখন কল করবেন GetEnumerator( forachস্পষ্টভাবে - সিনট্যাক্স ব্যবহার করে ), আপনি এমন একটি IEnumeratorবস্তু পাবেন যাটির প্রধান নোডের একটি পয়েন্টার রয়েছে। যতবার আপনি কল করবেন MoveNext, সেই পয়েন্টারটি পরবর্তী নোডে সরানো হবে, এর মতো:

IEnumerator em = list.GetEnumerator();  // Current points at head
em.MoveNext(); // Update Current to .Next
em.MoveNext(); // Update Current to .Next
em.MoveNext(); // Update Current to .Next
// etc.

যেমন আপনি দেখতে পাচ্ছেন, এর ক্ষেত্রে LinkedListঅ্যারের সূচক পদ্ধতিটি ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে বেড়ে যায় ( যেখানে ন্যায়বিচার IEnumerableস্থির সময়ে পরিচালনা করে।

অবশ্যই, জোন যেমন বলেছিলেন এটি সত্যিকারের ধরণের উপর নির্ভর করে list, যদি এটি listএকটি নয় LinkedListতবে অ্যারে হয় তবে আচরণটি সম্পূর্ণ আলাদা different


4
.NET- এ লিঙ্কডলিস্টে কোনও সূচক নেই, সুতরাং এটি আসলে কোনও বিকল্প নয়।
জন স্কিটি

ওহ, ভাল যে সমস্যাটি সমাধান করে, তারপরে :-) আমি কেবল LinkedList<T>এমএসডিএন-তে ডক্সটি সন্ধান করছি এবং এটির একটি সুন্দর শালীন এপিআই রয়েছে। সর্বাধিক গুরুত্বপূর্ণ, get(int index)জাভা যেমন এর কোন পদ্ধতি নেই। তবুও, আমি অনুমান করি যে পয়েন্টটি এখনও অন্য কোনও তালিকার মতো ডেটা কাঠামোর জন্য ধারণ করে যা একটি সূচককে নির্দিষ্ট থেকে ধীর করে দেয় IEnumerator
টম লোকহর্স্ট

2

অন্যান্য লোকেরা যেমন উল্লেখ করেছেন যদিও পারফরম্যান্সটি আসলে খুব বেশি গুরুত্ব দেয় না, লুপের IEnumerable/ IEnumeratorব্যবহারের কারণে ভবিষ্যদ্বাণীটি সর্বদা কিছুটা ধীর হবে । সংকলকটি সেই ইন্টারফেসে কনস্ট্রাক্টটিকে কলগুলিতে অনুবাদ করে এবং প্রতিটি পদক্ষেপের জন্য ফোরচ কনস্ট্রাক্টে একটি ফাংশন + একটি সম্পত্তি কল করা হয়।

IEnumerator iterator = ((IEnumerable)list).GetEnumerator();
while (iterator.MoveNext()) {
  var item = iterator.Current;
  // do stuff
}

এটি সি # তে কনস্ট্রাক্টের সমতুল্য সম্প্রসারণ। মুভনেক্সট এবং কারেন্টের প্রয়োগের ভিত্তিতে পারফরম্যান্সের প্রভাব কীভাবে পরিবর্তিত হতে পারে তা আপনি কল্পনা করতে পারেন। অ্যারে অ্যাক্সেসের ক্ষেত্রে আপনার সেই নির্ভরতা নেই।


4
অ্যারে অ্যাক্সেস এবং একটি সূচক অ্যাক্সেসের মধ্যে পার্থক্যটি ভুলে যাবেন না। যদি তালিকাটি List<T>এখানে থাকে তবে সূচককে কল করার এখনও হিট (সম্ভবত ইনলাইনড) রয়েছে। এটি খালি ধাতব অ্যারে অ্যাক্সেসের মতো নয়।
জন স্কিটি

খুবই সত্য! এটি আরও একটি সম্পত্তি কার্যকরকরণ এবং আমরা বাস্তবায়নের করুণায় আছি।
চার্লস প্রকাশ দাশারি

1

"ফোরচ লুপটি পাঠযোগ্যতার জন্য পছন্দ করা উচিত" পর্যাপ্ত যুক্তি পড়ার পরে, আমি বলতে পারি যে আমার প্রথম প্রতিক্রিয়াটি "কী" ছিল? পাঠযোগ্যতা, সাধারণভাবে, বিষয়গত এবং এই বিশেষ পরিস্থিতিতে আরও বেশি, প্রোগ্রামিংয়ের ব্যাকগ্রাউন্ডવાળા কারও জন্য (কার্যত জাভা আগে প্রতিটি ভাষা), লুপের জন্য ফোরচ লুপগুলির চেয়ে পড়া অনেক সহজ। এছাড়াও, একই লোকেরা দাবি করছে যে ফোরচ লুপগুলি আরও পঠনযোগ্য, তারা লিনাক এবং অন্যান্য "বৈশিষ্ট্যগুলি" এর সমর্থক যা কোড পড়া এবং বজায় রাখা শক্ত করে তোলে, এটি উপরের বিষয়টি প্রমাণ করে।

কর্মক্ষমতা উপর প্রভাব সম্পর্কে, এই প্রশ্নের উত্তর দেখুন ।

সম্পাদনা: সি # তে (হ্যাশসেটের মতো) সংগ্রহ রয়েছে যার কোনও সূচক নেই। এই সংগ্রহগুলিতে, অগ্রণীতা পুনরাবৃত্তি করার একমাত্র উপায় এবং এটি কেবলমাত্র মনে হয় এটির জন্য এটি ব্যবহার করা উচিত ।


0

আরও একটি আকর্ষণীয় তথ্য আছে যা উভয় লুপের গতি পরীক্ষা করার সময় সহজেই মিস করা যেতে পারে: ডিবাগ মোড ব্যবহার করে সংকলকটি ডিফল্ট সেটিংস ব্যবহার করে কোডটিকে অনুকূলিত করতে দেয় না।

এটি আমাকে আকর্ষণীয় ফলাফলের দিকে নিয়ে গেছে যে ডিবাগ মোডের চেয়ে পূর্ববর্তীটি দ্রুত। রিলিজ মোডে ফরচ করার চেয়ে ফর ইস্ট দ্রুততর। স্পষ্টতই সংকলকটির ফোরচ লুপের চেয়ে লুপের জন্য অনুকূলকরণের আরও ভাল উপায় রয়েছে যা বেশ কয়েকটি পদ্ধতি কলকে আপস করে। লুপের জন্য একটি এ জাতীয় মৌলিক যে এটি সম্ভব যে এটি এমনকি সিপিইউ দ্বারা অনুকূলিত করা সম্ভব।


0

আপনি যে উদাহরণ সরবরাহ করেছেন তাতে অবশ্যই foreachলুপের পরিবর্তে লুপটি ব্যবহার করা ভাল for

লুপটি নিবন্ধভুক্ত না করা হলে (স্টেপ প্রতি ১.০ চক্র) foreachসরল for-loop(স্টেপ প্রতি ২ টি চক্র ) তুলনায় স্ট্যান্ডার্ড কনস্ট্রাক্ট দ্রুত (ধাপে প্রতি 1,5 চক্র ) হতে পারে।

সুতরাং প্রতিদিনের কোডের জন্য, কার্যকারিতা আরও জটিল for, whileবা নির্মাণগুলি ব্যবহার করার কারণ নয় do-while

এই লিঙ্কটি দেখুন: http://www.codeproject.com/Articles/146797/Fast-and-Less-Fast-Looops-in-C


╔══════════════════════╦═══════════╦═══════╦════════════════════════╦═════════════════════╗
        Method         List<int>  int[]  Ilist<int> onList<Int>  Ilist<int> on int[] 
╠══════════════════════╬═══════════╬═══════╬════════════════════════╬═════════════════════╣
 Time (ms)             23,80      17,56  92,33                   86,90               
 Transfer rate (GB/s)  2,82       3,82   0,73                    0,77                
 % Max                 25,2%      34,1%  6,5%                    6,9%                
 Cycles / read         3,97       2,93   15,41                   14,50               
 Reads / iteration     16         16     16                      16                  
 Cycles / iteration    63,5       46,9   246,5                   232,0               
╚══════════════════════╩═══════════╩═══════╩════════════════════════╩═════════════════════╝


4
আপনি লিঙ্কিত কোড প্রকল্প নিবন্ধটি পুনরায় পড়তে পারেন। এটি একটি আকর্ষণীয় নিবন্ধ, তবে এটি আপনার পোস্টের ঠিক বিপরীত বলে। এছাড়াও, আপনি যে টেবিলটি পুনরায় তৈরি করেছেন তা কোনও অ্যারে এবং তালিকা সরাসরি অ্যাক্সেস করার পারফরম্যান্স বা তাদের আইলিস্ট ইন্টারফেসের মাধ্যমে পরিমাপ করছে। প্রশ্নের সাথে কিছু করার নেই। :)
পল ওয়ালস

0

আপনি ডিপ। নেট - অংশ 1 ইটারেশন সম্পর্কে এটি সম্পর্কে পড়তে পারেন

এটি NET উত্স কোড থেকে বিচ্ছিন্ন হয়ে যাওয়ার সমস্ত দিক থেকে ফলাফলগুলি (প্রথম সূচনা ছাড়াই) কভার করে cover

উদাহরণস্বরূপ - ফোরচ লুপের সাথে অ্যারে আইট্রেশন: এখানে চিত্র বর্ণনা লিখুন

এবং - ফোরচ লুপের সাথে তালিকা পুনরাবৃত্তি: এখানে চিত্র বর্ণনা লিখুন

এবং শেষ ফলাফল: এখানে চিত্র বর্ণনা লিখুন

এখানে চিত্র বর্ণনা লিখুন

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.