2012-10-29 32 views
24

Windows 7, Intel Core i3, 64 bit, RAM 4Gb, 2,27 GHz
.NET Framework 4.0
Tại sao có nhiều khác biệt về hiệu suất giữa Chủ đề và Tác vụ?

Tôi đã đoạn mã sau:

static void Main(string[] args) 
{ 
    var timer = new Stopwatch(); 
    timer.Start(); 

    for (int i = 0; i < 0xFFF; ++i) 
    { 
     // I use one of the following line at time 
     Task.Factory.StartNew(() => { }); 
     new Thread(() => { }).Start(); 
    } 

    timer.Stop(); 

    Console.WriteLine(timer.Elapsed.TotalSeconds); 
    Console.ReadLine(); 
} 

Nếu tôi sử dụng Task đầu ra luôn luôn là ít hơn 0,01 giây, nhưng nếu tôi sử dụng, đầu ra luôn lớn hơn 40 giây!
Làm cách nào có thể? Tại sao rất nhiều sự khác biệt?

+15

Bắt đầu 4096 chủ đề, hàng đợi khác 4096 nhiệm vụ trong hàng đợi .. bạn không đo bất kỳ thứ gì khác ngoài đó. Vô nghĩa .. –

Trả lời

30

Cả hai không giống nhau.

Khi bạn sử dụng Task.Factory.StartNew, bạn đang lập lịch một tác vụ để chạy trên ThreadPool. Khi bạn tạo một Thread mới, bạn phải tạo và bắt đầu một chuỗi mới.

Trong trường hợp đầu tiên, các chuỗi đã được tạo và được sử dụng lại. Điều này gây ra chi phí cho việc lên lịch các nhiệm vụ thấp hơn nhiều, vì các luồng không phải được tạo ra mỗi lần lặp.

Lưu ý rằng hành vi không giống nhau, tuy nhiên. Khi tạo một chuỗi riêng biệt, mỗi tác vụ sẽ nhận được chuỗi riêng của nó. Tất cả chúng sẽ bắt đầu ngay lập tức. Khi sử dụng Task.Factory.StartNew, chúng được đưa vào bộ lập lịch để chạy trên ThreadPool, mà sẽ (có khả năng) giới hạn số lượng các chuỗi đồng thời bắt đầu. Điều này thường là một điều tốt, vì nó ngăn cản việc phát hiện quá mức.

+0

Vì vậy, nếu tôi sử dụng Tác vụ có thể là nó chạy từng đại biểu được chỉ định; tức là chỉ khi trước đó được hoàn thành, lớp Task bắt đầu tiếp theo? – Nick

+0

[Task.ContinueWith] (http://msdn.microsoft.com/en-us/library/dd235663.aspx): 'var t = Task.Factory.StartNew (...). ContinueWith (...)' . – user7116

+0

@Nick Bạn có thể sử dụng một sự tiếp tục, hoặc, nếu bạn muốn chặn, hãy gọi '.Wait()' hoặc '.Result' trên' Task'/'Task '. Điều đó đang được nói, nếu bạn muốn xử lý các mục * theo thứ tự *, bạn có thể muốn xem xét 'BlockingCollection ' và tạo ra một kịch bản sản xuất/người tiêu dùng thay thế. –

0

Task.Factory.StartNew() không khởi động tác vụ ngay lập tức mà nó chỉ lên lịch để một TaskScheduled có thể bắt đầu sau một chút (phụ thuộc vào số lượng chủ đề/nhiệm vụ có sẵn).

MSDN nói rằng sau khi hệ điều hành Thread.Start() có thể lên lịch để thực thi, tương tác với hệ điều hành chậm hơn nhiều so với TaskScheduler của .NET Framework nhưng không ở mức độ như vậy.

Và quay lại ví dụ của bạn, 0xFFF == 4095, vì vậy bạn đang lên lịch 4095 luồng và quá trình này mất 40 giây. 102 chủ đề trong một giây là một thời gian khá tốt! :)

4

Mỗi khi bạn bắt đầu Task, nó sẽ được đưa vào một hồ bơi để phục vụ bởi một số chuỗi, nhiều chủ đề có thể được tạo trước. Có một tỷ lệ M:N của các tác vụ đối với các chủ đề trong hồ bơi.

Mỗi khi bạn bắt đầu Thread, nó sẽ tạo một chuỗi mới và tất cả chi phí liên quan đến tạo chuỗi. Vì bạn đang tạo một chủ đề rõ ràng, có một tỷ lệ 1: 1 của các luồng.

Tỷ lệ công việc càng gần với chủ đề đạt đến 1 thì việc khởi động tác vụ "chậm hơn" sẽ mất. Trong thực tế, các ThreadPool đảm bảo tỷ lệ vẫn cao hơn nhiều so với 1.

0

Gọi Task.Factory.StartNew không nhất thiết phải tạo một chủ đề mới, chúng được quản lý bởi TaskScheduler dựa trên bao nhiêu lõi vv máy có đang chạy mã.

Nếu bạn lên lịch (bằng cách gọi Task.Factory.StartNew) nhiều tác vụ hơn có thể chạy đồng thời, chúng sẽ được xếp hàng đợi và chạy khi có nhiều tài nguyên hơn.

1

Bạn gặp vấn đề với thử nghiệm của mình, trong đó bạn không đợi cho mỗi Chủ đề/Nhiệm vụ kết thúc.

Nhiệm vụ sử dụng hàng đợi, do đó việc tạo Nhiệm vụ nhanh hơn Chủ đề nhanh hơn rất nhiều.

Tôi sẽ đặt cược rằng ngay cả khi bạn đợi Công việc/Chủ đề kết thúc, việc sử dụng Tác vụ sẽ nhanh hơn. Chi phí tạo và sau đó phá hủy một Thread là cao. Đó là lý do tại sao Task.Factory được tạo ra!

0

Tạo chủ đề mới chậm nhưng không chậm. Nick đã báo cáo ~ 10 mili giây/luồng. Rất có thể nó đã xảy ra trong trình gỡ lỗi Visual Studio. Tôi nhận được ~ 3,9ms cho mỗi chủ đề mới trong trình gỡ lỗi Visual Studio. Tôi nhận được ~ 0.15ms mỗi chủ đề mới mà không cần trình gỡ lỗi.

http://dennisgorelik.livejournal.com/125269.html?thread=2238805#t2238805

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