SORU
17 EYLÜL 2008, ÇARŞAMBA


En verimli şekilde artış Java Göster bir değer

Bu soru bu forum için çok temel olarak kabul edilmez umarım, ama göreceğiz. Bir kaç kere çalıştırın oluyor ki daha iyi performans için bazı kod yeniden nasıl merak ediyorum.

Söyleyeceğim oluşturma Bir kelime frekans listesi, kullanarak bir Harita (muhtemelen bir HashMap), her bir anahtar bir Dize ile kelimenin tam sayılır ve bu değer bir Tamsayı bu artan her zaman bir belirteç kelimesi bulunamadı.

Perl, böyle bir değeri artan basit kolay olurdu:

$map{$word}  ;

Ama Java çok daha karmaşık. Burada şu anda bunu yapıyorum yolu:

int count = map.containsKey(word) ? map.get(word) : 0;
map.put(word, count   1);

Tabii ki yeni Java sürümlerinde autoboxing özelliği dayanıyor. Eğer böyle bir değer artırma için daha verimli bir yol önerebilir miyim, merak ediyorum. Hatta iyi performans Koleksiyonları çerçevesinde sakınarak ve bir şey kullanmak yerine başka sebep var mı?

Güncelleme: cevaplar birkaç test yaptım. Aşağıya bakın.

CEVAP
20 EYLÜL 2008, CUMARTESİ


Bazı test sonuçları

Bu soruya güzel bir cevap teşekkür ederim millet ... bir sürü aldım bazı testler ve gerçekten hızlı bir şekilde çözmeye karar verdim. Test ettim beş yöntemlerdir bunlar

  • "ContainsKey" the question sunulan bir yöntem
  • "TestForNull" yöntemi Aleksandar Dimitrov tarafından önerilen
  • "AtomicLong" yöntemi Hank Gay tarafından önerilen
  • "Hazinesi" yöntemi jrudolph tarafından önerilen
  • "Mutableİnt" yöntemi phax.myopenid.com tarafından önerilen

Yöntem

İşte yaptığım şey...

  1. farkları, aşağıda gösterildiği birbirinin aynı olan beş sınıf yarattı. Her sınıf bir çalışma sundum senaryo tipik gerçekleştirmek zorunda kaldı: 10MB bir dosya açma ve okuma, sonra dosyayı. tüm word simgeleri frekans sayım yapan Bu sadece 3 saniye, ortalama aldığına göre, bu frekans sayısı (I/O) gerçekleştirmek 10 kat vardı.
  2. 10 yineleme döngü zamanlı amadeğil, G/Ç işlemive toplam süre (saat saniye olarak) aslında Ian Darwin's method in the Java Cookbook kullanılarak kaydedildi.
  3. dizi beş testleri, ve sonra başka bir üç kez bunu yaptı.
  4. ortalama her dört yöntem için sonuçlar.

Sonuçları

Sonuçları ilk hediyesi ve ilgilenenler için aşağıda kodu vereceğim.

ContainsKeyYöntem Bu yöntem hızına göre her yöntemin hız vereceğim bu yüzden beklendiği gibi, yavaş.

  • ContainsKey:30.654 saniye (taban)
  • AtomicLong:29.780 saniye (1.03 kat daha hızlı)
  • TestForNull:28.804 saniye (1.06 kat daha hızlı)
  • Hazinesi:26.313 saniye (1.16 kat hızlı)
  • Mutableİnt:25.747 saniye (1.19 kat hızlı)

Sonuç

Sadece  Daha fazla performans artışı veriyorlar o Mutableİnt yöntemi ve Hazinesi yöntemi sadece önemli ölçüde daha hızlı açar. Eğer bir iş parçacığı bir sorun ise, AtomicLong diğerleri (tam emin değilim) daha çekici olabilir. Ben de final değişkenleri ile TestForNull koştu, ama fark yok denecek kadar azdı.

Farklı senaryolarda bellek kullanımı profilli alamadım unutmayın. Mutableİnt ve Hazinesi yöntemleri bellek kullanımı etkileyecek olurdu ne içine iyi anlayışlar olan herkes duymaktan mutlu olurum.

Şahsen, üçüncü sınıflar herhangi bir yükleme gerektirmez ama Mutableİnt yöntemi en çekici buluyorum. Yani sorun buldugum sürece, bu büyük ihtimalle ben orada değilim.

Kod

Burada her bir yöntem açısından çok önemli olan kod.

ContainsKey

import java.util.HashMap;
import java.util.Map;
...
Map<String, Integer> freq = new HashMap<String, Integer>();
...
int count = freq.containsKey(word) ? freq.get(word) : 0;
freq.put(word, count   1);

TestForNull

import java.util.HashMap;
import java.util.Map;
...
Map<String, Integer> freq = new HashMap<String, Integer>();
...
Integer count = freq.get(word);
if (count == null) {
    freq.put(word, 1);
}
else {
    freq.put(word, count   1);
}

AtomicLong

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicLong;
...
final ConcurrentMap<String, AtomicLong> map = 
    new ConcurrentHashMap<String, AtomicLong>();
...
map.putIfAbsent(word, new AtomicLong(0));
map.get(word).incrementAndGet();

Hazinesi

import gnu.trove.TObjectIntHashMap;
...
TObjectIntHashMap<String> freq = new TObjectIntHashMap<String>();
...
freq.adjustOrPutValue(word, 1, 1);

Mutableİnt

import java.util.HashMap;
import java.util.Map;
...
class MutableInt {
  int value = 1; // note that we start at 1 since we're counting
  public void increment () {   value;      }
  public int  get ()       { return value; }
}
...
Map<String, MutableInt> freq = new HashMap<String, MutableInt>();
...
MutableInt count = freq.get(word);
if (count == null) {
    freq.put(word, new MutableInt());
}
else {
    count.increment();
}

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • circuschina

    circuschina

    16 Mart 2007
  • DeAdPiXel6667

    DeAdPiXel666

    2 Ocak 2010
  • Thom Hall

    Thom Hall

    24 Kasım 2006