2009-02-14 112 views
6

我試圖運行500個客戶端,同時向服務器發送一些請求以用於負載測試目的。客戶端又是一個紅寶石程序。聽起來微不足道。但是我正面臨奇怪的ruby線程問題。我的代碼看起來像這樣 -Ruby一次只創建3個線程

n = 10 

n.times do 
    Thread.new do 
    `calc` 
    end 
end 

該代碼是一個示例。我只是試圖從命令行運行calc命令(如果您在Windows以外的平臺上嘗試此代碼,請將其替換爲可在您的命令行或shell中運行的一些命令)。這將被'ruby my_client.rb'取代,n的值也將被設置爲500(或其他)。

我在這裏面臨的問題是,無論我想要創建的線程數量是多少,一次只能創建線程數量爲。這只是3個計算窗口同時打開。其餘的線程只是在隊列中等待,等待這3個線程的終止。可能與阻塞和非阻塞呼叫有關。但是我嘗試了與Java相同的程序,並且工作得很完美。它是一個古老的說法,不建議使用紅寶石線程。這是真的,這是Ruby的線程問題還是我做錯了什麼?

+0

對我來說很好,在Debian GNU/Linux上的版本是1.8.7.72-2。我在想,有特定於Windows的事情正在發生。 – womble 2009-02-14 05:00:08

+0

這是可能的,但Java程序在相同的平臺,同一臺機器上完美工作。 – Chirantan 2009-02-14 05:07:38

+0

在Windows XP SP3下使用ruby 1.8.7工作得很好。 – Lolindrath 2009-02-17 13:32:44

回答

3

Ruby(MRI)的「Matz」C實現不會使用直到1.8.6的本地線程。我相信這在Ruby 1.9中有所改變,但我知道由於Global Interpreter Lock的緣故,我們可能仍然不會看到出色的多線程性能。

如果您確實需要良好的多線程支持,並且您的軟件要用Ruby編寫,那麼可以嘗試在JRuby上運行它。一個快速的完整性測試表明,使用你的例子,我將在MRI上獲得2個操作系統線程,而在JRuby下運行同樣的東西時,會得到12個操作系統線程這是在OS X上使用「MRI」1.8.6和JRuby 1.1.6。

另一種選擇,因爲它看起來像是爲產生一個新進程而產生一個線程,可能是利用DRb來代替。

+0

感謝DRb指針。 Jruby應該解決問題。對DRb沒有任何經驗,也會學習並投入。謝謝:) – Chirantan 2009-02-14 04:51:13

0

這對os x和textmate完美地工作。

n = 10 

threads = [] 
n.times do |i| 
    threads << Thread.new do 
    `mate test#{i}.txt` 
    end 
end 

threads.each { |t| t.join } 
4

您正在觀察的問題是針對GUI應用程序的。當你在工作人員內部運行命令行時,它會變得更好。

在下面的例子中,我可以運行200個wget實例,這可能足以滿足您的負載測試目標。

n = 200 

threads = [] 
(1..n).each do |i| 
    threads << Thread.new do 
    puts `wget google.com` # forgive me google 
    sleep 10 
    puts "#{i} done" 
    end 
end 

threads.each do |t| # wait until all workers are done 
    t.join 
end 

如果您從wget切換到用於提取網頁的Ruby代碼,您可能會獲得更多的工作人員。而且,你應該記住,Ruby線程只能擴展到那麼遠。不要指望成千上萬或並行線程正常工作 - 請嘗試使用子進程或基於延續的方法。

0

您可能想生成單獨的進程。 Kernel::fork在Windows下無法使用,因此您必須使用舊的Kernel::systemKernel::popen,併爲其創建單獨的腳本或使用特殊的命令行參數。

雖然Ruby 1.9幾乎在那裏,如果你可以打開它,它確實有本地操作系統線程和類似的東西不會發生。