2010-09-02 65 views
25

Bạn có thể nhận được đầu ra tương tự với cho và vòng lặp while:Vòng lặp nào nhanh hơn, trong khi hoặc cho?

Trong khi:

$i = 0; 
while ($i <= 10){ 
    print $i."\n"; 
    $i++; 
}; 

Mục đích:

for ($i = 0; $i <= 10; $i++){ 
    print $i."\n"; 
} 

Nhưng cái nào là nhanh hơn?

+7

Đánh giá chúng nếu bạn muốn (nhưng chúng có thể bằng nhau). –

+3

Đặt cược cho bạn chúng tạo chính xác cùng một mã byte. – zwol

+5

'for' trong hầu hết các ngôn ngữ là cú pháp đường cho một vòng lặp tương đương' while', đó là lần lượt cú pháp đường cho một tập hợp các nhãn và 'gotos' xuống trong lắp ráp hoặc IL. Với việc thực hiện hiệu quả đặc tả ngôn ngữ, chúng sẽ gần bằng nhau. Một số ngôn ngữ bao gồm nội bộ "bình luận" đưa ra gợi ý để decompilers/phản xạ về những gì mã ban đầu như thế nào, mà sẽ có một hiệu ứng không đáng kể về hiệu suất. Tôi nghĩ rằng bạn sẽ thấy rằng sự khác biệt thời gian thực hiện lớn nhất giữa chúng là vốn có trong lập lịch hệ điều hành. – KeithS

Trả lời

20

Điều đó rõ ràng phụ thuộc vào việc triển khai cụ thể trình thông dịch/trình biên dịch của ngôn ngữ cụ thể.

Điều đó nói rằng, về mặt lý thuyết, bất kỳ triển khai lành mạnh nào cũng có khả năng thực hiện một điều khoản khác nếu nó nhanh hơn, vì vậy sự khác biệt sẽ không đáng kể nhiều nhất.

Tất nhiên, tôi giả định whilefor hoạt động giống như trong C và các ngôn ngữ tương tự. Bạn có thể tạo một ngôn ngữ có ngữ nghĩa hoàn toàn khác nhau cho whilefor

0

Phụ thuộc vào ngôn ngữ và rất có thể trình biên dịch, nhưng chúng phải tương đương với hầu hết các ngôn ngữ.

1

Chúng phải bằng nhau. Vòng lặp for bạn đã viết đang thực hiện chính xác điều tương tự mà vòng lặp while đang thực hiện: thiết lập $i=0, in $i và tăng $i ở cuối vòng lặp.

3

Nếu đó là chương trình C, tôi sẽ không nói. Trình biên dịch sẽ xuất ra chính xác cùng một mã. Vì nó không phải, tôi nói đo nó. Mặc dù vậy, nó không phải là về cấu trúc vòng lặp nào nhanh hơn, vì đó là một số tiền tiết kiệm thời gian nhỏ. Đó là về cấu trúc vòng lặp nào dễ bảo trì hơn. Trong trường hợp bạn cho thấy, một vòng lặp for là thích hợp hơn bởi vì đó là những gì các lập trình viên khác (bao gồm cả tương lai bạn, hy vọng) sẽ mong đợi để thấy ở đó.

0

Nó không quan trọng nhanh hơn. Nếu nó có vấn đề thì hãy chuẩn nó bằng cách sử dụng mã thực sự của bạn và xem cho chính mình.

Những câu trả lời cho câu hỏi này khác có thể có ích cũng như: How to write more efficient code

0

Điều đó sẽ phụ thuộc vào việc thực hiện ngôn ngữ của nói vòng lặp, biên dịch và những gì không.

Hầu hết trình biên dịch sẽ biên dịch thành mã thực thi giống hệt nhau, ví dụ như trong CIL (.NET) mà chắc chắn chúng thực hiện.

Nguồn: vcsjones @http://forums.asp.net/t/1041090.aspx

Dù bằng cách nào, cơ thể của vòng lặp là nơi mà thời gian xử lý sẽ được chi tiêu không phải là cách bạn lặp.

3

Đặt lặp vòng lặp thành 10.000.

Tìm thời gian bằng mili giây> Chạy vòng> tìm thời gian bằng mili giây và trừ bộ hẹn giờ đầu tiên.

Làm điều đó cho cả hai mã, những gì có bao giờ có một mili giây thấp nhất nó chạy nhanh hơn. Bạn có thể muốn chạy thử nghiệm nhiều lần và trung bình chúng ra để giảm khả năng của các quá trình nền ảnh hưởng đến thử nghiệm.

Bạn có khả năng nhận được thời gian thực sự tương tự trên cả hai người trong số họ, nhưng tôi quan tâm để xem nếu một trong những luôn luôn là chỉ nhanh hơn một chút.

+0

Đáng ngạc nhiên, đối với PHP, vòng lặp while là 0,08 giây nhanh hơn 10 triệu lần lặp. –

4

Như những người khác đã nói, bất kỳ trình biên dịch nào có giá trị muối của nó sẽ tạo ra mã thực tế giống hệt nhau. Bất kỳ sự khác biệt về hiệu suất là không đáng kể - bạn đang tối ưu hóa vi mô.

Câu hỏi thực sự là, điều gì dễ đọc hơn? Và đó là vòng lặp for (ít nhất là IMHO).

5

tôi thấy vòng nhanh nhất là một đảo ngược trong khi vòng lặp, ví dụ:

var i = myArray.length; 
while(i--){ 
    // Do something 
} 
12

Trong C#, các Đối với loop là nhanh hơn một chút.

Đối với vòng lặp trung bình khoảng 2,95 đến 3,02 ms.

Vòng lặp while tính trung bình khoảng 3,05 đến 3,37 ms.

nhanh chút giao diện điều khiển ứng dụng để chứng minh:

class Program 
    { 
     static void Main(string[] args) 
     { 
      int max = 1000000000; 
      Stopwatch stopWatch = new Stopwatch(); 

      if (args.Length == 1 && args[0].ToString() == "While") 
      { 
       Console.WriteLine("While Loop: "); 
       stopWatch.Start(); 
       WhileLoop(max); 
       stopWatch.Stop(); 
       DisplayElapsedTime(stopWatch.Elapsed); 
      } 
      else 
      { 
       Console.WriteLine("For Loop: "); 
       stopWatch.Start(); 
       ForLoop(max); 
       stopWatch.Stop(); 
       DisplayElapsedTime(stopWatch.Elapsed); 
      } 
     } 

     private static void WhileLoop(int max) 
     { 
      int i = 0; 
      while (i <= max) 
      { 
       //Console.WriteLine(i); 
       i++; 
      }; 
     } 

     private static void ForLoop(int max) 
     { 
      for (int i = 0; i <= max; i++) 
      { 
       //Console.WriteLine(i); 
      } 
     } 

     private static void DisplayElapsedTime(TimeSpan ts) 
     { 
      // Format and display the TimeSpan value. 
      string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}", 
       ts.Hours, ts.Minutes, ts.Seconds, 
       ts.Milliseconds/10); 
      Console.WriteLine(elapsedTime, "RunTime"); 
     } 
    } 
+1

Có thể là khi trình biên dịch chạy trong khi vòng lặp nó chạy một số tác vụ nền khác cũng bcz của nó mất lâu hơn một chút. Làm thế nào bạn chắc chắn về những điều đó ?? –

+0

Tôi thì không. Đây không phải là một số thử nghiệm phòng sạch. Tôi đã chạy quá trình tương tự này nhiều lần và nhất quán sẽ là kết quả tương tự. Vì vậy, điều đó sẽ cho tôi biết khả năng của một số tác vụ nền ngẫu nhiên ảnh hưởng đến thời gian chỉ cho vòng lặp trong khi là tối thiểu. – Shane

+1

Điều này nhanh hơn phụ thuộc vào những gì bạn đang lặp lại. [Đây là một so sánh blog mà lặp lại điểm chuẩn] (http://cc.davelozinski.com/c-sharp/for-vs-foreach-vs-while) trên nhiều loại đối tượng, chẳng hạn như DataRows và các đối tượng tùy chỉnh, cũng bao gồm hiệu suất của vòng lặp while xây dựng và không chỉ các cấu trúc for và foreach. –

1

Một số trình biên dịch tối ưu hóa sẽ có thể làm tốt hơn vòng lặp unrolling với một vòng lặp for, nhưng tỷ lệ cược là rằng nếu bạn đang làm một cái gì đó có thể được trải ra, một trình biên dịch đủ thông minh để unroll nó có lẽ cũng đủ thông minh để giải thích điều kiện vòng lặp của vòng lặp while của bạn như là một cái gì đó nó có thể unroll là tốt.

0

Không phải là một vòng lặp kỹ thuật một thời gian thực hiện?

Ví dụ:

for (int i = 0; i < length; ++i) 
{ 
    //Code Here. 
} 

sẽ ...

int i = 0; 
do 
{ 
    //Code Here. 
} while (++i < length); 

Tôi có thể sai mặc dù ...

Ngoài ra khi nói đến cho vòng lặp. Nếu bạn có kế hoạch để chỉ lấy dữ liệu và không bao giờ sửa đổi dữ liệu, bạn nên sử dụng một foreach. Nếu bạn yêu cầu các chỉ mục thực tế vì một số lý do bạn sẽ cần phải tăng thêm, do đó bạn nên sử dụng vòng lặp thông thường.

for (Data d : data) 
{ 
     d.doSomething(); 
} 

nên nhanh hơn ...

for (int i = 0; i < data.length; ++i) 
{ 
     data[i].doSomething(); 
} 
+0

Vòng lặp 'for' không phải là vòng lặp' do'. Một thử nghiệm trước khi thực hiện vòng lặp và các thử nghiệm khác sau đó. Sự khác biệt lớn. –

0

tôi đã tự hỏi điều tương tự vì vậy tôi googled và kết thúc ở đây. Tôi đã làm một thử nghiệm nhỏ trong python (rất đơn giản) chỉ để xem và đây là những gì tôi nhận:

Mục đích:

def for_func(n = 0): 
    for n in range(500): 
     n = n + 1 

python -m timeit "nhập khẩu for_func; for_func.for_func() "> for_func.txt

10000 vòng, tốt nhất là 3: 40.5 usec mỗi vòng lặp

Trong khi:

def while_func(n = 0): 
    while n < 500: 
     n = n + 1 

python -m timeit "nhập khẩu while_func; while_func.while_func()"> while_func.txt

10000 vòng, tốt nhất 3: 45 usec trên mỗi vòng

1

Tôi đã sử dụng vòng lặp đồng thời máy kiểm tra (không có quy trình nền bên thứ ba không chuẩn nào đang chạy). Tôi đã chạy số for loop so với while loop vì nó liên quan đến việc thay đổi thuộc tính kiểu của 10.000 <button> nút.

Xét nghiệm này được được chạy liên tục 10 lần, với 1 chạy timed out cho 1500 mili giây trước khi thực hiện:

Đây là javascript rất đơn giản tôi đã thực hiện cho mục đích này

function runPerfTest() { 
    "use strict"; 

    function perfTest(fn, ns) { 
     console.time(ns); 
     fn(); 
     console.timeEnd(ns); 
    } 

    var target = document.getElementsByTagName('button'); 

    function whileDisplayNone() { 
     var x = 0; 
     while (target.length > x) { 
      target[x].style.display = 'none'; 
      x++; 
     } 
    } 

    function forLoopDisplayNone() { 
     for (var i = 0; i < target.length; i++) { 
      target[i].style.display = 'none'; 
     } 
    } 

    function reset() { 
     for (var i = 0; i < target.length; i++) { 
      target[i].style.display = 'inline-block'; 
     } 
    } 

    perfTest(function() { 
     whileDisplayNone(); 
    }, 'whileDisplayNone'); 

    reset(); 

    perfTest(function() { 
     forLoopDisplayNone(); 
    }, 'forLoopDisplayNone'); 

    reset(); 
}; 

$(function(){ 
    runPerfTest(); 
    runPerfTest(); 
    runPerfTest(); 
    runPerfTest(); 
    runPerfTest(); 
    runPerfTest(); 
    runPerfTest(); 
    runPerfTest(); 
    runPerfTest(); 
    setTimeout(function(){ 
     console.log('cool run'); 
     runPerfTest(); 
    }, 1500); 
}); 

đây là kết quả tôi nhận được

pen.js:8 whileDisplayNone: 36.987ms 
pen.js:8 forLoopDisplayNone: 20.825ms 

pen.js:8 whileDisplayNone: 19.072ms 
pen.js:8 forLoopDisplayNone: 25.701ms 

pen.js:8 whileDisplayNone: 21.534ms 
pen.js:8 forLoopDisplayNone: 22.570ms 

pen.js:8 whileDisplayNone: 16.339ms 
pen.js:8 forLoopDisplayNone: 21.083ms 

pen.js:8 whileDisplayNone: 16.971ms 
pen.js:8 forLoopDisplayNone: 16.394ms 

pen.js:8 whileDisplayNone: 15.734ms 
pen.js:8 forLoopDisplayNone: 21.363ms 

pen.js:8 whileDisplayNone: 18.682ms 
pen.js:8 forLoopDisplayNone: 18.206ms 

pen.js:8 whileDisplayNone: 19.371ms 
pen.js:8 forLoopDisplayNone: 17.401ms 

pen.js:8 whileDisplayNone: 26.123ms 
pen.js:8 forLoopDisplayNone: 19.004ms 

pen.js:61 cool run 
pen.js:8 whileDisplayNone: 20.315ms 
pen.js:8 forLoopDisplayNone: 17.462ms 

Đây là demo link

Cập nhật

Một thử nghiệm riêng tôi đã tiến hành nằm bên dưới, mà thực hiện 2 thuật toán thừa khác bằng văn bản, 1 sử dụng một vòng lặp for, người kia sử dụng một vòng lặp while.

Đây là mã:

function runPerfTest() { 
    "use strict"; 

    function perfTest(fn, ns) { 
     console.time(ns); 
     fn(); 
     console.timeEnd(ns); 
    } 

    function whileFactorial(num) { 
     if (num < 0) { 
      return -1; 
     } 
     else if (num === 0) { 
      return 1; 
     } 
     var factl = num; 
     while (num-- > 2) { 
      factl *= num; 
     } 
     return factl; 
    } 

    function forFactorial(num) { 
     var factl = 1; 
     for (var cur = 1; cur <= num; cur++) { 
      factl *= cur; 
     } 
     return factl; 
    } 

    perfTest(function(){ 
     console.log('Result (100000):'+forFactorial(80)); 
    }, 'forFactorial100'); 

    perfTest(function(){ 
     console.log('Result (100000):'+whileFactorial(80)); 
    }, 'whileFactorial100'); 
}; 

(function(){ 
    runPerfTest(); 
    runPerfTest(); 
    runPerfTest(); 
    runPerfTest(); 
    runPerfTest(); 
    runPerfTest(); 
    runPerfTest(); 
    runPerfTest(); 
    runPerfTest(); 
    console.log('cold run @1500ms timeout:'); 
    setTimeout(runPerfTest, 1500); 
})(); 

Và kết quả cho điểm chuẩn thừa:

pen.js:41 Result (100000):7.15694570462638e+118 
pen.js:8 whileFactorial100: 0.280ms 
pen.js:38 Result (100000):7.156945704626378e+118 
pen.js:8 forFactorial100: 0.241ms 
pen.js:41 Result (100000):7.15694570462638e+118 
pen.js:8 whileFactorial100: 0.254ms 
pen.js:38 Result (100000):7.156945704626378e+118 
pen.js:8 forFactorial100: 0.254ms 
pen.js:41 Result (100000):7.15694570462638e+118 
pen.js:8 whileFactorial100: 0.285ms 
pen.js:38 Result (100000):7.156945704626378e+118 
pen.js:8 forFactorial100: 0.294ms 
pen.js:41 Result (100000):7.15694570462638e+118 
pen.js:8 whileFactorial100: 0.181ms 
pen.js:38 Result (100000):7.156945704626378e+118 
pen.js:8 forFactorial100: 0.172ms 
pen.js:41 Result (100000):7.15694570462638e+118 
pen.js:8 whileFactorial100: 0.195ms 
pen.js:38 Result (100000):7.156945704626378e+118 
pen.js:8 forFactorial100: 0.279ms 
pen.js:41 Result (100000):7.15694570462638e+118 
pen.js:8 whileFactorial100: 0.185ms 
pen.js:55 cold run @1500ms timeout: 
pen.js:38 Result (100000):7.156945704626378e+118 
pen.js:8 forFactorial100: 0.404ms 
pen.js:41 Result (100000):7.15694570462638e+118 
pen.js:8 whileFactorial100: 0.314ms 

Kết luận: Không có vấn đề kích thước mẫu hoặc loại công việc cụ thể được kiểm tra, không có chiến thắng rõ ràng về hiệu suất giữa một thời gian và vòng lặp. Thử nghiệm được thực hiện trên MacAir với OS X Mavericks trên Chrome thường xanh.

+0

Vì vậy, kết luận của bạn là gì? – Bergi

+0

Tôi sẽ tăng kích thước mẫu và sử dụng thuật toán để tải proc tiếp theo thay vì điều này. Hy vọng rằng kết quả sẽ được kết luận hơn sau đó. Chỉ cần tìm việc triển khai chính xác để mở rộng điều này đúng cách. –

+1

@Bergi Không có người chiến thắng rõ ràng sau khi thử nghiệm nhiều hơn –

0

Đối với vòng lặp vô hạn for(;;) vòng lặp tốt hơn while(1) từ while đánh giá mỗi lần điều kiện nhưng lại phụ thuộc vào trình biên dịch.

Các vấn đề liên quan