2010-05-19 27 views
7

Ben ısmarlama tel protokolü kullanılarak TCP üzerinden gönderilen iletileri işlemek için bir Codec yazıyorum. Kod çözme işlemi sırasında bir dizi String s, BigDecimal s ve tarihleri ​​oluşturuyorum. istemci-sunucu erişim desenler istemci isteği için ve sonra ben Dolayısıyla vbString s, BigDecimal s yinelenen çok sayıda sonuçlanır tepki mesajları binlerce,PermGen alanını mı yoksa kendi dahili yöntem mi kullanıyorsunuz?

deşifre için yaygın olduğu anlamına Nesnelerin her sınıfını tutmamı sağlayan bir InternPool<T> sınıfı oluşturduk. Dahili olarak, havuz bir WeakHashMap<T, WeakReference<T>> kullanır.

InternPool<BigDecimal> pool = new InternPool<BigDecimal>(); 

... 

// Read BigDecimal from in buffer and then intern. 
BigDecimal quantity = pool.intern(readBigDecimal(in)); 

Benim soru: Örneğin: Ben BigDecimal için InternPool kullanarak ama am Ben de inanıyorum ki, StringyerineString 'ın intern() yöntemi için kullanmaktan düşünmelisiniz PermGen boşluk kullanır? PermGen alanı kullanmanın avantajı nedir? Zaten böyle bir InternPool sınıf varsa

+1

Kts: Byte [] 'ı BigDecimal ile eşleştireceksem sorun şu ki, bu bilgi havuzunun oluşturduğu/BigDecimal'i döndürdüğü zaman, byte [] öğesinden herhangi biriyle başvurmayacaktır. Bayt [], alttaki WeakHashMap'teki anahtar olduğunu varsayarak, girdinin kullanımdaki ilgili BigDecimal'e rağmen kaldırılmasına neden olur. – Adamski

+1

"WeakReference" buna uygun mu, yoksa bir "SoftReference" kullanıyor muydunuz? GC, her ikisi için farklı davranır ve bu bir çeşit önbellek oluşturmaya çalıştığınız gibi geliyor; zayıf referanslar bu amaç için iyi bir kullanım değildir. Bazı nedenlerden dolayı cevabımı burada görebilirsiniz: http://stackoverflow.com/questions/2861410/weakhashmap-iteration-and-garbage-collection/2862174#2862174 –

+0

@Adamski Yalnızca bir BigRecence ile bir ReferenceQueue kullanırdım. BigDecimal bir kez basıldıktan sonra haritadan 'bayt []' ı kaldır. (Muhtemelen bir BiMap'e ihtiyaç var).Bu, bellek/gc çalışma zamanı ve yürütme süresinden tasarruf eden gereksiz BigDecimal nesnelerinin oluşturulmasını ortadan kaldırabilir (yalnızca bir kez oluşturmalıdır). – KitsuneYMG

cevap

2

Bu JVM String.intern() havuz hızlı olacaktır mümkündür. Teoride bu daha hızlı olmalı ve WeakHashMap ve WeakReference kullanılarak uygulanan bir havuz daha az yer kullanmak böylece AFAIK, bu, yerli kodda uygulanmaktadır. Bunu doğrulamak için dikkatli bir kıyaslama yapmanız gerekir. Eğer uzun ömürlü yinelenen nesnelerin büyük numaralarına sahip olmadıkça

Ancak, ben (PermGen veya kendi havuzlu ya) interning pek fark edeceğini sanmıyorum. Nesneleri çoğaltmak için benzersiz oranı çok düşükse, o zaman sadece bu yüzden canlı nesne sayısını (GC uzun sürer yapma) artırmak ve staj genel giderler nedeniyle performansını azaltır ve stajyerlik. Bu yüzden "stajyer" olmayanlara karşı "stajyer" yaklaşımları karşılaştırmayı da savunurum.

+0

Adamski'nin gerçekten çok sayıda uzun ömürlü, yinelenen nesnesi var :-) –

+0

@oxbow_lakes - çok zekice. Mesele şu ki, bu şeyleri ölçmek için (herhangi bir mekanizmaya göre) içselliğin performansı iyileştirip iyileştirmediğini ... veya daha da kötüleştirdiğini anlamanız gerekir. Ve sonuçların etkisi * çok * faktörler vardır. –

4

, bu Strings için farklı staj yöntemi seçmek için daha o kullanmak daha iyidir düşünüyorum. Özellikle String.intern()'dan beri ihtiyacınız olandan çok daha güçlü bir garanti veriyor gibi görünüyor. Amacınız bellek kullanımını azaltmak, böylece JVM'nin ömrü boyunca mükemmel bir şekilde internete girmek gerçekten gerekli değil.

Ayrıca, ben önlemek için bir InternPool oluşturmak için Google CollectionsMapMaker kullanmayı tercih ediyorum yeniden oluşturma tekerleği:

Map<BigDecimal,BigDecimal> bigDecimalPool = new MapMaker() 
    .weakKeys() 
    .weakValues() 
    .expiration(1, TimeUnits.MINUTES) 
    .makeComputingMap(
     new Function<BigDecimal, BigDecimal>() { 
     public BigDecimal apply(BigDecimal value) { 
      return value; 
     } 
     }); 

Bu sizi (doğru bir şekilde uygulandığında) zayıf anahtarlar ve değerler, iplik güvenlik verecekti, otomatik temizleme Eski girişler ve çok basit bir arayüz (basit, iyi bilinen bir Map). Kötü kodun karışmasını önlemek için Collections.immutableMap()'u kullanarak da sardığınızdan emin olmak için.

+0

Tamam Teşekkürler. String.intern() JVM'nin yaşam süresi için stajyer mi? PermGen'den toplanan modern VMs çöplerini düşündüğümden bunun doğru olduğuna emin değilim. – Adamski

+0

@Joachim - Bir dahili String'in JVM'nin ömrü boyunca yaşayacağını ima ediyor gibi görünüyorsunuz. Bu javadocs tarafından garanti edilmez ve aslında son JVM'ler için doğru olduğunu düşünmüyorum. –

+0

@Stephen: JavaDoc'un bunu belirtmediği için * bunu * denemedim. –

İlgili konular