我已經寫了一個小小的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
儘管Ruby確實使用GIL,但我確信使用'file.each'的新線程可以提高性能,因爲每個線程都不需要訪問任何全局變量。它只處理初始化時給出的變量並輸出到STDOUT。我爲網站編寫了一個迷你壓力測試,並使用了線程,並且工作正常。 –
有趣的是,使用'sh'('bash','zsh'或其他)可能是一個選項。 'sh'使用多進程範例,您只需要處理與每個網站有關的片段就可以實現良好的併發性。 – ninjalj