Dejw'in cevabını genişletmek (edit2):
File.open(filename,'w'){ |f|
uri = URI.parse(url)
Net::HTTP.start(uri.host,uri.port){ |http|
http.request_get(uri.path){ |res|
res.read_body{ |seg|
f << seg
#hack -- adjust to suit:
sleep 0.005
}
}
}
}
dizeler nerede filenameve nerede url.
sleepKomut edebilir kesmek dramatik ağ sınırlayıcı faktör olduğu zaman CPU kullanımını azaltmak. Net :: HTTP, verimi vermeden önce arabelleğin (v1.9.2'de 16kB) dolmasını beklemez, bu nedenle CPU küçük parçaları hareket ettirerek meşgul olur. Bir anlığına uyumak, arabelleğe yazma işlemleri arasında dolma şansı verir ve CPU kullanımı, uygulamamdaki 4-5x fark olan curl çözümüyle karşılaştırılabilir. Daha sağlam bir çözüm ilerlemeyi inceleyebilir f.posve zaman aşımını hedeflemek için zaman aşımını ayarlayabilir, örneğin tampon boyutunun% 95'ini - aslında benim örneğimde 0.005 sayısını elde ettim.
Üzgünüm, ama Ruby'nin arabelleğin dolmasını beklemesinin daha zarif bir yolunu bilmiyorum.
Düzenle:
Bu, arabelleği tam kapasitede veya altında tutmak için kendini otomatik olarak ayarlayan bir versiyondur. Bu uygun olmayan bir çözüm, ancak aynı derecede hızlı ve kıvrılma çağrısı yaptığı kadar az CPU zamanı kullanıyor gibi görünüyor.
Üç aşamalı olarak çalışır. Kasıtlı olarak uzun bir uyku süresine sahip kısa bir öğrenme dönemi, tam bir arabellek boyutunu belirler. Düşme süresi, yetersiz doldurulmuş bir tampon bulana kadar daha büyük bir faktörle çarparak her yinelemede uyku süresini hızlı bir şekilde azaltır. Daha sonra normal dönemde daha küçük bir faktörle yukarı ve aşağı ayarlanır.
Benim Ruby'm biraz paslanmış, bu yüzden bunun iyileştirilebileceğinden eminim. Her şeyden önce, herhangi bir hata işleme yoktur. Ayrıca, belki indirmenin kendisinden uzakta bir nesneye ayrılabilir, böylece sadece döngünüzü çağırırsınız autosleep.sleep(f.pos)? Daha da iyisi, Net :: HTTP, vermeden önce tam bir arabellek bekleyecek şekilde değiştirilebilir :-)
def http_to_file(filename,url,opt={})
opt = {
:init_pause => 0.1, #start by waiting this long each time
# it's deliberately long so we can see
# what a full buffer looks like
:learn_period => 0.3, #keep the initial pause for at least this many seconds
:drop => 1.5, #fast reducing factor to find roughly optimized pause time
:adjust => 1.05 #during the normal period, adjust up or down by this factor
}.merge(opt)
pause = opt[:init_pause]
learn = 1 + (opt[:learn_period]/pause).to_i
drop_period = true
delta = 0
max_delta = 0
last_pos = 0
File.open(filename,'w'){ |f|
uri = URI.parse(url)
Net::HTTP.start(uri.host,uri.port){ |http|
http.request_get(uri.path){ |res|
res.read_body{ |seg|
f << seg
delta = f.pos - last_pos
last_pos += delta
if delta > max_delta then max_delta = delta end
if learn <= 0 then
learn -= 1
elsif delta == max_delta then
if drop_period then
pause /= opt[:drop_factor]
else
pause /= opt[:adjust]
end
elsif delta < max_delta then
drop_period = false
pause *= opt[:adjust]
end
sleep(pause)
}
}
}
}
end