Trang 1 / 2 12 LastLast
Hiển thị kết quả từ 1 đến 10 / 13
  1. #1
    Tham gia
    11-02-2006
    Location
    Nông thôn
    Bài viết
    1,345
    Like
    13
    Thanked 35 Times in 27 Posts

    Tệ thật ! So sánh vòng lặp for() và foreach() trong C# !

    Các bạn chịu khó đọc tiếng Anh nhé:
    Introduction
    In my experience, there are two kinds of programmers. Those who write something to get the work done and those who want to write good code. But, here we get a big question. What is good code? Good code comes from good programming practices. What are good programming practices? Actually, my aim here is not to talk about good programming practices (I’m planning to write something related to that in future!), rather to talk more about writing something which will be more effective. I'm only going to look more deeper of two loops which are commonly used nowadays, and their differences in the aspect of performance.

    Background
    Must be familiar with IL and assembly code. Also, better to have a good knowledge on how .NET framework works. Some knowledge of JIT is also needed to understand what is exactly happening.

    Using the code
    I’m going to take a very small piece of code for two popular looping statements for and foreach. We will look some code and will see what it does, more in detail about the functionality.

    FOR
    int[] myInterger = new int[1];
    int total = 0;
    for(int i = 0; i < myInterger.Length; i++)
    {
    total += myInterger[i];
    }foreach
    int[] myInterger = new int[1];
    int total = 0;
    foreach(int i in myInterger)
    {
    total += i;
    }Both codes will produce the same result. foreach is used on top of collections to traverse through while for can be used on anything for the same purpose. I’m not going to explain whatsoever about the code. Before going in more deeper, I think all of you are familiar with ILDasm which is used to generate IL code, and CorDbg tool which is normally used to generate JIT compiled code.

    The IL code produced by C# compiler is optimized up to certain extend, while leaving some part to JIT. Anyway, this is not really what matters to us. So, when we talk about the optimization, two things we must consider. First is C# compiler and the second is JIT.

    So, rather than looking more deep into IL code, we will see more about the code which is emitted by JIT. That is the code which will run on our machine. I’m now using AMD Athlon 1900+. The code highly depends on our hardware. Therefore, what you may get from your machine may differ from mine up to a certain extend. Anyway, the algorithms wont change that much.

    In variable declaration, foreach has five variable declarations (three Int32 integers and two arrays of Int32) while for has only three (two Int32 integers and one Int32 array). When it goes to loop through, foreach copies the current array to a new one for the operation. While for doesn't care of that part.

    Here, I’m going into the exact difference between the codes.

    FOR
    Instruction Effectcmp dword ptr [eax+4],0 i<;myInterger.Length
    jle 0000000F
    mov ecx,dword ptr [eax+edx*4+8] total += myInterger[i]
    inc edx ++i
    cmp esi,dword ptr [eax+4] i<;myInterger.Length
    jl FFFFFFF8I’ll explain what is happening here. The esi register which holds the value of i and the length of myInteger array are compared at two stages. The first one is done only once to check the condition and if the loop can continue, the value is added. For the loop, it is done at the second stage. Inside the loop, it is well optimized and as explained, the work is done with perfect optimization.

    foreach
    Instruction Effectcmp esi,dword ptr [ebx+4] i<;myInterger.Length
    jl FFFFFFE3
    cmp esi,dword ptr [ebx+4] i<;myInterger.Length
    jb 00000009
    mov eax,dword ptr [ebx+esi*4+8]
    mov dword ptr [ebp-0Ch],eax
    mov eax,dword ptr [ebp-0Ch]
    add dword ptr [ebp-8],eax total += i
    inc esi ++i
    cmp esi,dword ptr [ebx+4] i<;myInterger.Length
    jl FFFFFFE3Anyone will say that both are not the same. But we will look why it differs from the for loop. The main reason for the difference is that both of them are differently understood by the compiler. The algorithm they are using is different. Two compare statements one after the other is unnecessary. It is doing the same thing again and again for no reason!

    cmp esi,dword ptr [ebx+4]
    jl FFFFFFE3
    cmp esi,dword ptr [ebx+4]It also uses some unnecessary move statements which also may (not always, but depends) reduce the performance of the code. foreach is thinking everything as a collection and treating them as a collection. I feel, that will also reduce the performance of the work.

    Therefore, I strongly feel if you are planning to write high performance code that is not for collections, use for loop. Even for collections, foreach may look handy when using, but it's not that efficient. Therefore, I strongly recommend everyone to use for loop rather than foreach at any stage.

    Points of Interest
    Actually, I did a small research on the performance issue of codes mainly on .NET languages. While I was testing, I found that it was really a must to know how JIT works and to debug the code generated by JIT compiler. It took some time to understand the code.

    History
    This is submitted on 19th of April 2004.
    Nguồn: http://netcode.ru/dotnet/?lang=&katI...261&artID=6974
    Quote Quote

  2. #2
    Tham gia
    25-02-2008
    Bài viết
    1,050
    Like
    0
    Thanked 3 Times in 3 Posts
    bác dịch ra tiếng Việt luôn thì hay biết mấy

  3. #3
    Tham gia
    26-08-2007
    Bài viết
    87
    Like
    0
    Thanked 0 Times in 0 Posts
    bài viết khá hay,nhưng muốn hiểu kỷ hơn thì phải rành hơn về hợp ngữ.
    Nhưng kết luận chung theo mình hiễu :
    For thi không dùng cho kiểu tập hợp, và chỉ hỗ trợ 3 kiểu biến còn Foreach thì dùng cho kiểu tập hợp ,hổ trợ 5 kiểu biến.
    Bài viết trên người ta có khuyên thế này : khi viết code a không dùng kiểu tập hợp thì nên dùng For,kô nên dùng Foreach,.(Tất nhiên nếu là kiểu tập hợp thì chúng ta dùng Foreach)
    Kết lưận chung người ta khuyên chúng ta nên sử dụng vòng lặp for hơn là foreach trong mọi trường hợp
    Có gì sau xót anh em góp y thêm để bài viết tôt hơn

  4. #4
    Tham gia
    07-10-2007
    Bài viết
    42
    Like
    0
    Thanked 0 Times in 0 Posts
    int i, n, s;
    if (n==0)
    {
    s=1;
    textBox2.Text="gia thua bang: 1";
    }

    else
    n= Convert.ToString(textBox1.Text);
    for(int i; i<=n; i=++;
    s= i*s;
    i=i++;
    textBox2.Text=Convert.ToString(textBox1.Text);
    tại sao cái for của tớ sai?
    Ai biết trả lời dùm với

  5. #5
    Tham gia
    24-11-2007
    Bài viết
    111
    Like
    0
    Thanked 1 Time in 1 Post
    Quote Được gửi bởi tesulakata View Post
    int i, n, s;
    if (n==0)
    {
    s=1;
    textBox2.Text="gia thua bang: 1";
    }

    else
    n= Convert.ToString(textBox1.Text);
    for(int i; i<=n; i=++;
    s= i*s;
    i=i++;
    textBox2.Text=Convert.ToString(textBox1.Text);
    tại sao cái for của tớ sai?
    Ai biết trả lời dùm với
    Bạn nên khởi tạo giá trị cho biến

  6. #6
    Tham gia
    07-10-2007
    Bài viết
    42
    Like
    0
    Thanked 0 Times in 0 Posts
    Thank! quên thật
    giờ thì mình còn gà hơn mấy năm trước nữa
    :d

  7. #7
    Tham gia
    05-06-2009
    Location
    Tuyên Quang
    Bài viết
    656
    Like
    0
    Thanked 4 Times in 3 Posts
    Foreach dùng được cho cả Object. For làm sao được

  8. #8
    Tham gia
    07-08-2009
    Bài viết
    2
    Like
    0
    Thanked 0 Times in 0 Posts
    int i, n, s;
    sai chỗ này vì n là biến kiểu integer, nên sửa thành Convert.ToInt32:
    n= Convert.ToString(textBox1.Text);

    s= i*s; ==> biến s chưa khởi tạo nên có giá trị default = 0 ==> kết quả luôn = 0 với mọi n > 0:


    textBox2.Text=Convert.ToString(textBox1.Text); ==>câu lệnh này ngộ nghĩnh thật ^.^, sao khong phải là: textBox2.Text = Convert.ToString(s);

  9. #9
    Tham gia
    20-02-2009
    Location
    Ninh Bình
    Bài viết
    567
    Like
    0
    Thanked 34 Times in 31 Posts
    Bài viết này hay. Không phải hay vì luận lý, mà hay ở cách dùng cú pháp để diễn đạt tư tưởng. Nếu chấm điểm trong một lớp học văn chương, thì 9 điểm (trừ một điểm cho văn phạm). Còn chấm điểm kỹ thuật, thì chỉ được 7 điểm là tối đa.

    Đây là câu kết luận của tác giả:
    Therefore, I strongly feel if you are planning to write high performance code that is not for collections, use for loop. Even for collections, foreach may look handy when using, but it's not that efficient. Therefore, I strongly recommend everyone to use for loop rather than foreach at any stage.
    Tạm dịch:
    Bởi thế, tôi mạnh dạn nghĩ rằng, nếu các bạn muốn viết code có tốc độ xử lý tốt cho những cấu trúc không phải là ...collections, hãy dùng vòng lặp "for", và ngay cả cho những cấu trúc thuộc về collections. (câu này nghe mâu thuẫn quá). Foreach có thể tiện lợi hơn khi dùng, nhưng nó không có tốc độ xử lý tối ưu. Bởi thế (lại bởi thế), tôi mạnh dạn góp ý (lại mạnh dạn - strongly) với tất cả các bạn, nên dùng vòng lặp "for" thay vì "foreach" trong bất cứ trường hợp nào.

    Tôi cũng xin "mạnh dạn" góp ý với tác giả rằng, để có một tốc độ xử lý tối ưu, tác giả nên ném tất cả những vòng lặp "for" và cả C#, C/C++ code vào thùng rác. Hãy viết bằng ngôn ngữ assembly cho có tốc độ tối ưu...

    Và cuối cùng, tôi cũng xin "mạnh dạn" đưa ra đây một thí dụ, mà cái vòng lặp "for" yêu mến của tác giả sẽ thật sự rơi vào thùng rác của Windows vì không thể dùng được:

    Code:
    for (int i = 0; i < someobject.count; i ++)
    {
        if (someobject[i].somenumber = -1)
        {
            someobject.RemoveAt(i);
        }
    }
    SomeObject là một lớp collection nào đó, và nó có hàm RemoveAt(n) để xóa bỏ một instance của nó. Khi xóa bỏ đi rồi, thì nó tự động...dàn xếp lại, và cái vòng lặp "for" yêu mến mà tác giả đã mạnh dạn khuyên độc giả nên dùng trong "bất cứ trường hợp nào", có phải chăng, trong trường hợp này, không thể hoạt động theo ý muốn?

    Ngược lại, nếu dùng foreach trong trường hợp này thì hoàn toàn không sao.

    Code:
    foreach (object curObject in someObject)
    {
        if(curObject.someNumber = -1)
        {
            someObject.RemoveAt(curObject.index);
        }
    }
    Tác giả đã đúng khi nói rằng (và có chứng minh bằng cách lấy assembly code ra để so sánh) vòng lặp "for" có tốc độ xử lý tốt hơn.

    Nhưng tác giả đã sai bét bè be khi "mạnh dạn" cố vấn rằng, hãy dùng vòng lặp "for" trong bất cứ một trường hợp nào.

    Được cái này, phải mất cái khác. Chúng ta đang sống trong một thế giới mà thuyết tương đối luôn luôn có một vị thế vững chắc. Theo thiển ý của tôi, hãy dùng "for" khi nào cần dùng, và hãy dùng "foreach" khi cần dùng. Dùng hay không dùng, tất cả đều nên cân nhắc cho kỹ lưỡng và thận trọng.
    Được sửa bởi dq_ninh lúc 13:03 ngày 13-08-2009

  10. #10
    Tham gia
    17-06-2007
    Bài viết
    1
    Like
    0
    Thanked 0 Times in 0 Posts
    Bởi thế, tôi mạnh dạn nghĩ rằng, nếu các bạn muốn viết code có tốc độ xử lý tốt cho những cấu trúc không phải là ...collections, hãy dùng vòng lặp "for", và ngay cả cho những cấu trúc thuộc về collections. (câu này nghe mâu thuẫn quá). Foreach có thể tiện lợi hơn khi dùng, nhưng nó không có tốc độ xử lý tối ưu. Bởi thế (lại bởi thế), tôi mạnh dạn góp ý (lại mạnh dạn - strongly) với tất cả các bạn, nên dùng vòng lặp "for" thay vì "foreach" trong bất cứ trường hợp nào.

    --> bác này dịch sai hết cả ý tác giả! Bác nên để ý dấu chấm câu, và cả dấu phẩy của tác giả nữa. Bác thử đọc lại xem ý tác giả có còn mâu thuẫn không nào.
    p/s: "strongly recommend" không có nghĩa là "mạnh dạn" đưa ý kiến bác nhé!

    Thân.

Trang 1 / 2 12 LastLast

Bookmarks

Quy định

  • Bạn không thể tạo chủ đề mới
  • Bạn không thể trả lời bài viết
  • Bạn không thể gửi file đính kèm
  • Bạn không thể sửa bài viết của mình
  •