2011-05-25 140 views
0

我想對C#運行測試(我想比較它的運行速度與另一種語言)。
我想要做的是在鏈中創建100,000個線程,每個線程等待來自線程之前的值,當它獲得值add 1並將值傳遞給下一個線程時。 這個想法是看它可以創建這些線程的速度有多快,並且總計高達100,000。
我不知道如何編寫該代碼。我可以做它像線程和時間的部分,但我不知道如何將它們串在一起。C#多線程的速度測試

編輯
看來我也得了解我的不足之處的知識,當涉及到線程。所以我們假設線程池(或其他一些低級別的方法)是可比較的,任何人都可以向我展示這樣的例子嗎?

+6

創建100.000個線程......甚至不去那裏。 – 2011-05-25 18:11:26

+1

這聽起來像是你在生產代碼中永遠不會做的事......所以爲什麼要測試它? – 2011-05-25 18:12:04

+14

這是一個壞主意,你不應該這樣做。你永遠不想在靠近許多線程的地方創建任何線程。如果您需要一堆線程,則正確的做法是創建一個線程池並將線程拉出池。你已經知道創建線程是重量級的,那麼你將如何學習?只是爲這些線程分配和解除分配堆棧很昂貴,應該避免。如果你想測量不同線程技術的性能,你真正想測量的是Task Parallel Library的性能。 – 2011-05-25 18:12:22

回答

7

這個場景正是TPL的設計來實現,特別是ContinueWith,或await在C#5說法。注意異步!=線程(雖然它們是相關的),但重點是你實際上試圖執行100k 任務,而不是100k線程線程。這兩個概念是不同的。 TPL是做這件事的正確方法。始終使用適當的工具來完成這項工作。

我將愉快地掀起TPL例如,如果你想......事情不是太遠:

var root = new Task<int>(() => 0); 
var end = root; 
for(int i = 0 ; i < 100000 ; i++) 
{ 
    end = end.ContinueWith(last => last.Result + 1); 
} 
var watch = Stopwatch.StartNew(); 
root.Start(); 
end.Wait(); 
watch.Stop(); 
Console.WriteLine("{0} in {1}ms", end.Result, watch.ElapsedMilliseconds); 
+2

爲大家做,馬克。我知道你想要;) – jgauffin 2011-05-25 18:25:12

+0

@jgauffin的確我 - 但我現在在移動 - 沒有電腦。 Eric和Jon可能可以在文本框中編寫有效的異步代碼;我需要一個編譯器:) – 2011-05-25 18:30:20

+0

請做馬克(或任何其他人可以) – 2011-05-25 18:42:08

0

在您的主函數中,在循環中創建這些線程而不運行它們。在此期間,讓線程等待線程i-1退出。循環完成後,只需啓動您創建的第一個線程(例如線程1)(等待線程2等待)。他們將逐一開始。

0

您可能要崩潰Windows。

您需要創建一個具有Thread成員變量並使用Linked Lists的類。

在你的類的構造函數中,它應該取前一個線程的Thread.ID和你的Count索引。

當你的類被創建時,它的構造函數將需要檢查Count值,並創建另一個類,如果它低於100,000。

雖然這會很討厭。你可能會弄亂你的電腦。

+2

它不會崩潰窗口,你會得到一個內存不足的例外。 – 2011-05-25 18:29:14

+0

大聲笑。是啊。不過,我還在等待Gravell的回答。 – jp2code 2011-05-25 19:15:32

-1

using System;使用System.Threading的 ;

命名ConsoleApplication1 { 類節目 {

static int X; 
    static void Main(string[] args) 
    { 

     const int INT_Constant = 1000; 
     var threads = new Thread[INT_Constant]; 

     for (var i = 0; i < INT_Constant; i++) 
     { 
      threads[i] = new Thread(RunThread); 
     } 

     threads[0].Start(); 
     for (var i = 1; i < INT_Constant; i++) 
     { 
      threads[i].Start(threads[i - 1]); 
     } 

     threads[INT_Constant - 1].Join(); 

    } 

    static void RunThread(object state) 
    { 
     var previousThread = (Thread)state; 
     if (previousThread != null) 
      previousThread.Join(); 

     X += 1; 
     Console.WriteLine("Thread # " + Thread.CurrentThread.ManagedThreadId + " updated X to " + X); 

    } 

} 

}

+0

避免打印速度測試。 – 2011-05-25 18:24:44

+0

這可行,因爲線程完成速度比創建新線程要快。如果你想同時建立所有線程,請參閱我的其他答案。 – 2011-05-25 18:27:32

-1

使用系統; 使用系統。線程;

命名ConsoleApplication1 { 類節目 {

static int X; 
    static object SyncRoot = new object(); 
    static void Main(string[] args) 
    { 

     const int INT_Constant = 1000; 
     var threads = new Thread[INT_Constant]; 

     for (var i = 0; i < INT_Constant; i++) 
     { 
      threads[i] = new Thread(RunThread); 
     } 

     lock (SyncRoot) 
     { 
      threads[0].Start(); 
      for (var i = 1; i < INT_Constant; i++) 
      { 
       threads[i].Start(threads[i - 1]); 
      } 
     } 

     threads[INT_Constant - 1].Join(); 

    } 

    static void RunThread(object state) 
    { 
     var previousThread = (Thread)state; 
     if (previousThread != null) 
      previousThread.Join(); 
     else 
      lock (SyncRoot) 
      { 
       Console.WriteLine("Starting now"); 
      } 

     X += 1; 
     Console.WriteLine("Thread # " + Thread.CurrentThread.ManagedThreadId + " updated X to " + X); 

    } 

} 

}

+0

這一個會如果將該常量設置爲10,000個線程,則會在我的計算機上拋出「內存不足」異常。儘管如此, – 2011-05-25 18:28:37

3

OK,只是爲了討論的目的,而不是一個真正的基準都:

const int numberOfTasks = 100000; 
int total = 0; 
var watch = System.Diagnostics.Stopwatch.StartNew(); 
Parallel.For(0, numberOftasks, (i) => Interlocked.Increment(ref total)); 
var elapsed = watch.Elapsed; 

這包括加入所有任務和聚合例外。

在我的雙核筆記本電腦上,調試模式下需要0.004秒。

+0

並不完全衡量同一件事:「在一個鏈中,每個等待來自線程之前的值,當它獲得值加1並將該值傳遞給下一個線程時」 – 2011-05-25 19:41:29

+0

Marc,我知道那。但最後的號碼是一樣的:) – 2011-05-25 19:44:47

+1

同意;那裏沒有爭論。 – 2011-05-25 21:14:43

2

我不清楚你到底想要測量什麼。你可以很容易掀起一個使用Task s到做計算的代碼:

var initial = new Task<int>(() => 0); 

var task = initial; 
for (int i = 0; i < 100000; i++) 
    task = task.ContinueWith(t => t.Result + 1); 

var watch = new Stopwatch(); 

watch.Start(); 

initial.Start(); 

task.Wait(); 

watch.Stop(); 

Console.WriteLine(task.Result); 
Console.WriteLine(watch.Elapsed); 

此代碼看起來像一個你想要的和我的電腦上大約需要0.10秒至執行它。這幾乎是無用的數字,主要是因爲它根本不測試多線程。所有的任務都在同一個線程上一個接一個地運行,因爲在你的例子中絕對不需要並行。

當然,這並不表明C#是比Go更好的語言。所有這些都表明,你應該對這些例子進行測試,至少類似於某人會覺得有用的東西。