Hızlı bir HTML kazıyıcı yazmayı deniyorum ve bu noktada yalnızca ayrıştırma yapmadan verimimi en üst düzeye çıkarmaya odaklanıyorum. Ben URL'lerin IP adreslerini önbelleğe adres:Java'da birden çok web sayfası almanın en hızlı yolu
public class Data {
private static final ArrayList<String> sites = new ArrayList<String>();
public static final ArrayList<URL> URL_LIST = new ArrayList<URL>();
public static final ArrayList<InetAddress> ADDRESSES = new ArrayList<InetAddress>();
static{
/*
add all the URLs to the sites array list
*/
// Resolve the DNS prior to testing the throughput
for(int i = 0; i < sites.size(); i++){
try {
URL tmp = new URL(sites.get(i));
InetAddress address = InetAddress.getByName(tmp.getHost());
ADDRESSES.add(address);
URL_LIST.add(new URL("http", address.getHostAddress(), tmp.getPort(), tmp.getFile()));
System.out.println(tmp.getHost() + ": " + address.getHostAddress());
} catch (MalformedURLException e) {
} catch (UnknownHostException e) {
}
}
}
}
sonraki adımım, internetten şekilde almayı ilk 64KB okuma ve sonraki URL'ye hareket ettirerek 100 URL'yi hızını test etmekti. En iyi ihtimalle ben açabiliyorum
public class FetchTaskConsumer implements Runnable{
private final CountDownLatch latch;
private final int[] urlIndexes;
public FetchTaskConsumer (int[] urlIndexes, CountDownLatch latch){
this.urlIndexes = urlIndexes;
this.latch = latch;
}
@Override
public void run() {
URLConnection resource;
InputStream is = null;
for(int i = 0; i < urlIndexes.length; i++)
{
int numBytes = 0;
try {
resource = Data.URL_LIST.get(urlIndexes[i]).openConnection();
resource.setRequestProperty("User-Agent", "Mozilla/5.0");
is = resource.getInputStream();
while(is.read()!=-1 && numBytes < 65536)
{
numBytes++;
}
} catch (IOException e) {
System.out.println("Fetch Exception: " + e.getMessage());
} finally {
System.out.println(numBytes + " bytes for url index " + urlIndexes[i] + "; remaining: " + remaining.decrementAndGet());
if(is!=null){
try {
is.close();
} catch (IOException e1) {/*eat it*/}
}
}
}
latch.countDown();
}
}
: Her tüketici böyle görünüyor burada, ben FetchTaskConsumer
's bir iş parçacığı havuzu oluşturmak ve ben (bir i7 Dört Çekirdekli makinede 64'e 16), birden konuları çalıştıran denedim Yaklaşık 30 saniyede 100 URL'den geçmek, ancak literatür, saniyede 150 URL'sini kullanabilmem gerektiğini önerir. Gigabit Ethernet'e erişebileceğimi, ancak şu anda 20 Mbit bağlantımda evde testi çalıştırdığım halde, bağlantının hiçbir zaman tam olarak kullanılmadığını unutmayın.
Doğrudan Socket
bağlantılarını kullanarak denedim, ancak yanlış bir şeyler yapmalıyım, çünkü bu daha da yavaş! Verimi nasıl geliştirebileceğime dair herhangi bir öneriniz var mı?
P.S.
Yaklaşık 1 milyon popüler URL’den oluşan bir listeye sahibim. Bu nedenle, 100, ölçütleme için yeterli değilse daha fazla URL ekleyebilirim.
Güncelleme:
literature I'm referring Najork Web Paletli ilişkin belgeler olduğu, Najork devletler: ~ 606 indirme Saniyede [üzerinde] şeklindedir 17 Gün
yılında
İşlenmiş 891000000 URL'leri 4 Compaq DS20E Alpha Sunucular [with] 4 GB ana bellek [,] 650 GB disk alanı [ve] 100 MBit/sn.
Ethernet ISP hız limitleri bant genişliği için 160Mbits/sn
Demek ki 300. bilgisayarım 4 GB RAM ile Core i7 ve ben o hiçbir yerde yakın yakınım, aslında saniyede 150 sayfa. Özellikle ne kullandıklarını belirten bir şey görmedim.
Güncelleme:
Tamam, yukarı taksitli ... nihai sonuçları geldi! 100 URL’nin bir kıyaslama için biraz düşük olduğu ortaya çıkıyor. Ben 1024 URL, 64 iş parçacığı için çarptı, her getirme için 2 saniye bir zaman aşımı ayarladım ve saniyede 21 sayfaya varabildim (aslında benim bağlantım yaklaşık 10.5 Mbps, yani saniyede 21 sayfa * 64KB sayfa başına yaklaşık 10.5 Mbps'dir. Alıcının şu şekilde görünmesi:
public class FetchTask implements Runnable{
private final int timeoutMS = 2000;
private final CountDownLatch latch;
private final int[] urlIndexes;
public FetchTask(int[] urlIndexes, CountDownLatch latch){
this.urlIndexes = urlIndexes;
this.latch = latch;
}
@Override
public void run() {
URLConnection resource;
InputStream is = null;
for(int i = 0; i < urlIndexes.length; i++)
{
int numBytes = 0;
try {
resource = Data.URL_LIST.get(urlIndexes[i]).openConnection();
resource.setConnectTimeout(timeoutMS);
resource.setRequestProperty("User-Agent", "Mozilla/5.0");
is = resource.getInputStream();
while(is.read()!=-1 && numBytes < 65536)
{
numBytes++;
}
} catch (IOException e) {
System.out.println("Fetch Exception: " + e.getMessage());
} finally {
System.out.println(numBytes + "," + urlIndexes[i] + "," + remaining.decrementAndGet());
if(is!=null){
try {
is.close();
} catch (IOException e1) {/*eat it*/}
}
}
}
latch.countDown();
}
}
Bir kazıyıcı için bir tarayıcı ayarlayıcısı kurma ** iyi bir uygulama değildir. – Mat
Edebiyat? Javadocs demek mi istiyorsun? URLConnection ile ilgili saniyede 300 URL hakkında bir şey bulamıyorum. – Babar
URLConnection çoğunlukla 500ms başına bir sayfa alır, bu amaç için java oldukça yavaştır –