2011-12-08 31 views
1

我已經寫了一個小小的Ruby腳本,它需要一個URL文件,檢查該URL網頁上是否存在指向網站的鏈接(指定爲命令行參數),並且如果鏈接未標記爲「 nofollow',它將URL打印到STDOUT。該計劃的目的是過濾掉鏈接到指定網站的網站,但不會傳遞鏈接汁。如何修改這個順序網絡程序以獲得更好的性能?

它可以正常工作,但腳本需要花費數小時檢查~3000個網頁。我想改善這一點,主要是爲了好玩,並學習一些技術來解決將來的這類問題。我的主要目標是重寫程序,使其能夠飽和網絡連接,因爲網絡I/O是當前的瓶頸。

現在,我不知道解決這個問題的最好方法是什麼。我知道以事件驅動的方式構建程序通常用於編寫高效的網絡代碼,而且似乎使用線程。不過,我的(不正確的)理解是,Ruby並不真正支持併發編程,因爲Ruby運行時使用全局鎖。我現在也知道C,但是,如果有一些其他語言特別適合這種事情(特別是在大規模的情況下,請考慮數百萬個URL而不是數千個URL),我可以花一些時間來學習因爲我計劃在未來建立一些類似的計劃。適合這項工作的所有工具。

所以,我的問題是,大致爲:

  • 是紅寶石或下以有效的方式解決這一問題的合適人選?
  • 我將如何構建這樣的程序?我應該使用哪些庫?

如果沒有的Ruby和C都適用:

  • 什麼語言將是一個非常適合這種類型的節目?
  • 我將如何構建這樣的程序?我應該使用哪些庫?

這裏是我的腳本看起來像現在:

(argument parsing code omitted) 

def dofollow?(link) 
    if not link.attr("rel").nil? 
    if link.attr("rel").include?("nofollow") 
     return false 
    end 
    end 
    return true 
end 

options = parse(ARGV) 

File.open(options.file, "r") do |file| 
file.each do |website| 
    begin 
     doc = Nokogiri::HTML(open(website)) 
     doc.css("a").each do |link| 
     if link.attr("href").include?(options.url) && dofollow?(link) 
      puts website 
      break 
     end 
     end 
    rescue 
    end 
    end 
end 
+2

儘管Ruby確實使用GIL,但我確信使用'file.each'的新線程可以提高性能,因爲每個線程都不需要訪問任何全局變量。它只處理初始化時給出的變量並輸出到STDOUT。我爲網站編寫了一個迷你壓力測試,並使用了線程,並且工作正常。 –

+0

有趣的是,使用'sh'('bash','zsh'或其他)可能是一個選項。 'sh'使用多進程範例,您只需要處理與每個網站有關的片段就可以實現良好的併發性。 – ninjalj

回答

0

你可能要考慮一個平行的HTTP庫像Typhoeus。這是一個ruby API,但它使用libcurl的C綁定進行快速並行讀取。

另一個優秀的庫是em-http-request,它在並行請求的eventmachine事件框架上運行。

相關問題