Bu blog, Oracle G1 GC'ye yakın zamanda eklenen NUMA farkındalığı yeteneklerini test etme hikayemizi anlatıyor.
Tekdüzen Olmayan Bellek Erişimini (NUMA) test ederken yaptığımız yolculuk ve sonuçları aşağıda açıklanmıştır:
NUMA veya Tekdüzen Olmayan Bellek Erişimi, CPU'ların N UMA düğümleri adı verilen gruplara ayrıldığı bir mimaridir .
Bu tasarımın dezavantajlarından biri, CPU'nun belleğin farklı bölgelerine erişim hızının, esas olarak CPU ile eriştiği bellek bölgesi arasındaki mesafeye bağlı olmasıdır.
Bir CPU aynı NUMA düğümündeki belleğe eriştiğinde, yerel bellek erişimi olarak kabul edilir ve bu işlem nispeten düşük gecikme süresine sahip olur.
Bir CPU başka bir NUMA düğümündeki belleğe eriştiğinde, bu bir uzak bellek erişimi olarak kabul edilir ve bu işlem, NUMA düğümünün CPU'nun NUMA düğümünden ne kadar uzakta olduğuna bağlı olarak genellikle daha yüksek bir gecikme süresine sahip olur. Ne kadar uzak olursa, gecikme o kadar yüksek olur.
JDK14'ten önce, Parallel GC ve ZGC, NUMA farkındalığını destekleyen tek GC'lerdi. Ancak JDK14'ün piyasaya sürülmesiyle birlikte, Oracle G1 GC tahsislerini NUMA-Aware yapan JEP-345 geldi .
JVM'nin NUMA kullanıp kullanmayacağının kontrolü XX:+UseNUMA VM seçeneği kullanılarak yapılır .
JVM başladığında ile UseNUMA bayrak, numa düğümleri boyunca eşit yığın yayılır. Örneğin, dört NUMA düğümü olan bir makine kullanırsak, her düğüm yığının %25'ini tutar.
JVM çalışırken ve bir iş parçacığı yeni nesneler oluşturmaya çalışırken, JVM, o anda o iş parçacığını çalıştıran CPU ile aynı NUMA düğümünde bulunan bölgelerdeki nesneler için gerekli belleği ayırmaya çalışacaktır.
Örneğimizde, JVM 4 NUMA düğümlü makinede çalışıyorsa ve iş parçacığının düğüm #3'teki bir CPU üzerinde çalıştığını varsayarsak, JVM NUMA düğümü #3'ten bellek ayırmaya çalışır.
Aynı iş parçacığının o belleği okuyan kişi olacağını varsayarsak, bu mantık, yerel olan bellek tahsislerinin sayısını, uzak olanlar pahasına artırmalı ve bu sayede belleğe erişmenin ortalama gecikmesini azaltmalı ve iyileştirmelidir. genel performans.
Karşılaştırma yapmak gerekirse, JVM UseNUMA bayrağı olmadan başladığında , yığın, NUMA düğümleri ve hangi bölgenin nerede olduğuna dair herhangi bir değerlendirme veya farkındalık olmaksızın NUMA düğümleri arasında herhangi bir olası şekilde yayılabilir.
Dört NUMA düğümlü örneğimizde, tüm yığının diğer üçünü kullanmadan düğümlerden yalnızca birinde oluşturulma şansı vardır. Böyle bir durumda, tüm iş parçacıkları o düğümde çalışıyorsa, tüm bellek erişimleri yerel olacaktır, bu da UseNUMA seçeneğini kullanıyor olsaydık görebildiğimizden çok daha iyi performansa yol açardı .
Bu nedenle, tamamen bir düğüme sığacak kadar küçük bir yığınımız varsa ve tüm iş parçacıklarının aynı düğümden (örneğin numactl kullanarak) çalıştığından emin olabiliriz, o zaman bu şekilde ve UseNUMA olmadan çalışır. bayrak her şey yerel olacağından optimal olacaktır.
Akılda tutulması gereken bir şey, eski neslin NUMA'nın farkında olmadığıdır. Bu, G1'in ayırma iş parçacığıyla aynı NUMA düğümünde bulunan eski nesil bölgelerden bellek ayırmaya çalışmadığı anlamına gelir.
Outbrain'de saniyede yüz binlerce istekle ilgileniyoruz. Her istek, binlerce fiziksel sunucu üzerinde Kubernetes (K8s) üzerinde çalışan bir mikro hizmet mimarisine yayılmış düzinelerce hizmet kullanılarak işlenir.
Donanım kullanımımızı azaltmak için yeni XX:+UseNUMA bayrağını kullanmak gibi çok az çaba gerektiren düşük asılı meyveler bulmak bize fayda sağlayacaktır. Teorik olarak, NUMA aynı miktarda trafiğe daha az donanımla hizmet vermemize yardımcı olabilir ve bu da bize para tasarrufu sağlar.
Yüzlerce hizmet için yapılandırmaları değiştirmeden önce, genel performanslarını iyileştirip iyileştirmeyeceğini bilmeden, XX:+UseNUMA kullanmanın etkilerini küçük bir ölçekte test etmek istedik .
İki bölümden oluşan ve aşağıdaki özellikleri kullanan bir deney tasarladık (aksi belirtilmedikçe):
Hardware…………: Supermicro SYS-2027TR-HTRF+ CPU……………..: Intel(R) Xeon(R) CPU E5–2630L v2 @2.40GHz CPUs…………….: 2 CPU Cores………..: 12 Memory…………..: 63627 MB
numastat -p <JVM_PROCESS_ID>
-XX:+PerfDisableSharedMem -Xmx8g -Xms8g -XX:+DisableExplicitGC -XX:-OmitStackTraceInFastThrow -XX:+AlwaysPreTouch -XX:+UnlockDiagnosticVMOptions -XX:+DebugNonSafepoints -XX:+ParallelRefProcEnabled -XX:+UnlockExperimentalVMOptions -XX:G1MaxNewSizePercent=90 -XX:InitiatingHeapOccupancyPercent=35 -XX:-G1UseAdaptiveIHOP -XX:ActiveProcessorCount=2 -XX:+UseNUMA -Xlog:os*,gc*=trace:file=/logs/fulllog.log:hostname,time,level,tags
Deneyin bu kısmı, NUMA'nın uzak bellek tahsislerini sıfıra indirebileceği ihtimaline karşı, elde edebileceğimiz en iyi sonuçları ölçmeyi amaçlıyordu.
Tüm bellek erişimlerinin yerel olduğu böyle bir durumda, belirli bir CPU kullanımı için verim üzerindeki etkisinin ne olacağını da ölçmek istedik.
%100 yerel bellek erişim oranı elde etmek için birkaç yaklaşım düşündük. Bunlardan biri, biri hariç tüm NUMA düğümlerini doğrudan test edilen makinenin BIOS'undan devre dışı bırakmayı içeriyordu.
Sonunda, en kolay yaklaşımın JVM'yi başlatmak için numactl kullanmak ve onu yalnızca NUMA düğümü #0 ile sınırlamak olduğu sonucuna vardık . Bu, JVM'yi makinede başka NUMA düğümleri olduğu gerçeğinden habersiz tuttu, bu nedenle kullanılan tüm çekirdekler ve bellek yalnızca düğüm #0'da bulunanlardı.
numactl — membind=0 — cpunodebind=0 java
Her iki dağıtımın da birkaç saat çalışmasına izin verdikten sonra aşağıdakileri gördük:
Bir şey bulmuş olabileceğimizden deneylere devam etmeliyiz.
Bu bölümde, aynı hizmeti çalıştıran ve tamamen aynı konfigürasyona sahip iki dağıtımı karşılaştırmak istedik ( birinde etkin olan XX:+UseNUMA bayrağı dışında ).
1. tur
Test başarısız oldu!
Araştırıp çok sayıda googling yaptıktan sonra, NUMA'nın aslında +UseNUMA bayrağına sahip NUMA dağıtımında çalışmadığını gördük .
Biz bulduk G1 GC numa modunda başlatıldığında, aşağıdakine benzer bir ileti GC günlüklerde görünmesi gerektiğini:
ls.print(“UseNUMA is enabled and invoked in ‘%s’ mode.”” Heap will be configured using NUMA memory nodes:”, numa_mode);
Ek araştırma bizi kapsayıcıya aşağıdaki iki kitaplığı eklememiz gerektiği sonucuna götürdü:
apk add numactl apk add numactl-tools
Yukarıdaki kitaplıkları ekledikten ve deneyi yeniden denedikten sonra, NUMA dağıtımının GC günlüklerinde aşağıdaki satırı gördük:
[0.021s][info ][os ] UseNUMA is enabled and invoked in ‘membind’ mode. Heap will be configured using NUMA memory nodes: 0 1Photo by Japheth Mast on Unsplash
Bir sonraki adım, farklı yükler altında bir süre çalışmasına izin vermekti.
Sonuçlar şaşırtıcıydı… Ama daha iyisi için değil.
Aşağıdaki ortalama sonuçları ölçtük:
NUMA olmayan dağıtımda yerel bellek oranının çok daha yüksek olduğunu unutmayın; bu, görmeyi beklediğimizin tam tersidir.
3. tur
Önceki yinelemenin başarısızlığından sonra, yığının boyutunu değiştirmemiz ve daha özel olarak onu bir NUMA düğümüne sığmayacak şekilde artırmamız önerildi .
Test makinesi iki NUMA düğümü ile 64 GB belleğe sahip olduğundan, her düğümde yaklaşık 32 GB vardı. Yığın boyutunu 8 GB⇒ 40 GB'den ve kapsayıcının istenen belleğini 10 GB⇒ 50 GB'den artırmaya karar verdik.
Birkaç gün boyunca yeni yapılandırmayla iki dağıtımı çalıştırdıktan sonra aşağıdaki kalıbı görebildik:
Verimliliğin maksimumda olduğu günün en yoğun zamanlarında, NUMA dağıtımının yerel bellek erişim oranı, NUMA olmayan dağıtımdan çok daha iyiydi (%5-%6 fark).
Bu, aşağıdaki çizelgelerde görülebilir:
1. Dağıtım Başına Verim (NUMA dağıtımı ve NUMA olmayan dağıtım):
2. Dağıtım başına yerel bellek oranı yüzdesi:
Sonuçların Analizi:
Sonuçlar, makinelerdeki stres seviyeleri belirli bir eşiğe ulaştığında (maksimum çıktıya sahip olduğumuzda), NUMA dağıtımının daha iyi performans gösterdiğini gösterdi. Ancak makineler üzerinde yeterli stres olmadığında, dağıtımlar yaklaşık olarak aynı performansı gösterir.
Bu turdan çıkan sonuçlar:
Bu kullanarak benziyor XX: + UseNUMA stres düzeyleri yeterince yüksek olduğunda, daha iyi performans yol açacak.
Bu turda bizi rahatsız eden bir şey olduğu için bu sonuçların hala yetersiz olduğunu düşündük: Yukarıda açıklanan model gerçekten ilk iki günde gerçekleşmedi (bkz. grafik #2). O günlerde, NUMA olmayan dağıtım aslında NUMA dağıtımından daha iyi bir yerel/uzaktan erişim oranına sahipti.
4. tur
Önceki testlerin tümünde, bu NUMA deneyi için uygun olabilecek veya olmayabilecek gerçek dünya hizmetlerini kullandık. Bu nedenle, NUMA uyumlu G1'e en uygun olacak şekilde özel olarak uyarladığımız bir kıyaslama oluşturduk.
Beklentimiz, bu kıyaslamayı -XX:+UseNUMA bayrağıyla çalıştırmanın çok yüksek bir yerel bellek erişim oranı üretmesiydi.
Kullandığımız kıyaslamanın çok basit bir mantığı vardı:
Aşağıdaki kodu 12 saat çalıştıran bir iş parçacığı başlattı. Her yinelemede, her biri 1000 bayt boyutunda bir milyon küçük dizi oluşturarak 1 GB bellek ayırdı.
Bu deney için yığını 40 GB boyutuna ayarladık.
Bu yığın ve dizi boyutlarını çeşitli nedenlerle seçtik:
class MemoryTest implements Runnable { @Override public void run() { long timeToStop = System.currentTimeMillis() + TIME_TO_RUN; int sum = 0; while(System.currentTimeMillis() < timeToStop) { final byte[][] arrays = new byte[1_000_000][]; for (int i = 0; i < arrays.length; i++) { arrays[i] = new byte[1000]; ThreadLocalRandom.current().nextBytes(arrays[i]); } for (long l = 0; l < 1_000_000_000L; l++) { final byte[] array = arrays[ThreadLocalRandom.current(). nextInt(arrays.length)]; sum += array[ThreadLocalRandom.current(). nextInt(array.length)]; } } System.out.println(sum); } }
Durum buysa, G1 NUMA'nın farkında olduğundan, bellek ayırmaları yerel olacaktır ve iş parçacığı başka bir NUMA düğümüne taşınmadığından, ayrılan belleğe erişim (okuma sırasında) da yerel olacaktır.
Böylece %100'e çok yakın bir yerel bellek erişim oranına sahip olmamızı bekliyorduk.
Ama Yanlış Düşündük
Aşağıdaki sonuçlar, 30 saniyedeki uzak ve yerel erişimlerin sayısını gösterir (son 30 saniyenin toplamı olarak):
9,4 milyon erişim yereldi, 8,8 milyon erişim uzaktı, yani tüm bellek erişimlerinin yalnızca %51,6'sı yereldi.
Sonuç
Beklediğimizden daha uzak olmayan sonuçlar aldığımız için bu tur tam bir başarısızlıktı (~%100 yerine %51 yerel erişim oranı).
Tüm Deney Setini Sonuçlandırmak İçin
G1 NUMA'nın güçlü yanlarını göstermesi için ideal ortamı yaratmak için birkaç girişimde bulunduk.
Gerçekten çalışmasını sağlamak önemsiz değildi (hangi kitaplıkların eklenmesi gerektiğini bulmamız gerekiyordu), ancak yaptığımızda bile, NUMA dağıtımları yalnızca çok az özel durumda daha iyi sonuçlar gösterdi. Diğer tüm durumlarda, onu kullanmanın önemli bir avantajı yoktu.
Bu nedenle, çıktıları ölçme aşamasına bile ulaşamadık (aslında umursadığımız şey buydu).
Bu nedenle, bizim durumumuzda bu bayrağı açmanın gerçek bir katma değeri olmadığı sonucuna vardık ve kullanmamaya karar verdik.
Bahsetmeye değer bir ayrıntı daha , bu özelliğin yaratıcısı Sangheon Kim'in UseNUMA bayrağını kullanırken iyileştirmeler gördüğüdür . Ancak bu testler çok daha güçlü makinelerde yapıldı (dört NUMA düğümü ve 512 GB'lık bir yığın). Onun metodoloji hakkında daha fazla bilgi bulabilirsiniz burada . Burası ayrıca testlerimiz sırasında verdiği tavsiyeler ve açıklamalar için Sangheon Kim'e teşekkür etmek için iyi bir yer.
Sonraki Adımlarımızı Planlama
K8s üzerinde çalıştığımız için kaynaklarımızı daha iyi kullanmak için k8s Topoloji Yöneticisini kullanmayı denemek istiyoruz .
Örneğin, çok fazla kaynak kullanmayan kapsayıcıları nasıl ele aldığını görmek ilginç olurdu - özellikle de tüm kaynaklar aynı NUMA düğümünden ayrılabiliyorsa, yani kapsayıcı için tüm bellek erişimleri yerel kalabilir.
Bu, tek bir gönderide ele alınabilecek büyük bir konudur. Bu nedenle, uygulamaya daha yakından odaklanmak niyetindeyken, sinir ağlarına, çok temel genetik algoritmalara ve nesne yönelimli bir dil olarak Java'ya aşinalık varsaymalıyım.
Bugün, Biyolojik olarak adlandırdığım, biyolojik olarak büyük ölçüde ilham alan bir sinir ağı paradigmasının yaratılması ve kullanılması konusunda size yol göstermek benim için büyük bir zevk. Bu, dendritlerden aksonlara ve daha fazlasına kadar her nesne hakkında ayrıntılar içeren oldukça uzun bir yazı olacak.
Biliyoruz ki antik tarihte insanlar gaddarlık, adaletsizlik, sahtekârlık konusunda oldukça yetenekliydiler… aslında bu okuma yazma bilmemekti. İyi ve kötü insanlar her devirde toplumlarda hep var olmuştur.
Yıl 2021. Sen bir yazarsın.
Daha önce gördüğüne neredeyse %100 eminim. İster Facebook'ta, ister Twitter'da veya Instagram'da, ister istemez beğenmediğimiz gönderiler ve bilgilerle karşılaşıyoruz.
“Büyük Diktatör” filmi, başrolü de oynayan Charles Chaplin tarafından yazılıp yönetildi. 15 Ekim 1940'ta beyaz perdede vizyona giren film, Adolf Hitler ve Nazi rejimi üzerine bir hicivdir.
'1000-lb Sisters' grubundan Tammy Slaton, dağılmasından bu yana işleri değiştiriyor. Son zamanlarda takipçilerine yepyeni bir görünüm kazandırdı.
Steven Spielberg ve George Lucas, onlarca yıldır yakın arkadaşlardır. Ama Spielberg bir keresinde Lucas'a en büyük iltifatı ödemişti.
'Loki' yönetmeni Kate Herron, diziyi tamamlamak için 'duygusal bir İncil' de dahil olmak üzere çeşitli kaynaklara güvendi.
Kate Herron, Marvel'in hit dizisi 'Loki'nin 1. sezonunda ustaca bir iş çıkardı, ancak 2. sezonun neler getireceğini görmek için heyecanlı.
Çoğu ABD kıyı şeridinde halk, plajlara "yanal" erişim hakkına sahip olmuştur. Ancak bu kumlu alan ateşli bir şekilde tartışılıyor.
Bir yıllık gecikme ve hala devam eden küresel bir salgın arasında, Tokyo 2020 (veya tercih ederseniz 2021), kimsenin beklediği Olimpiyatlar değil. Ama asla unutamayacağımız biri olacağı kesin.
Nature dergisinde yayınlanan 10 yıllık benzeri görülmemiş bir araştırma, ormansızlaşma ve yangınların Amazon yağmur ormanlarının atmosferden karbon emisyonlarını emme kabiliyetini büyük ölçüde azalttığını buldu.
Bugün, Blue Origin milyarder kurucusu Jeff Bezos ve diğer üç kişiyi, Virgin Galactic'in milyarder kurucusu Richard Branson'ı aynı görevde uçurmasından bir hafta sonra uzaya uçtu. Uzay turizmi bir milyonerin hobisinden fazlası mı olacak?
Güney Carolina'da siyahi bir adam Rock Hill şehrine, polis departmanına ve ABD'ye dava açıyor
Alaska'nın başsavcısının başsavcısı, araştırmacıların, onun Yahudi karşıtı propagandayı yaymak için kullandığı gizli bir sağcı Twitter hesabını işlettiği ve Kara Hayat Önemlidir hareketini kınadığı iddiasının ortaya çıkmasından sonra, şimdi eyaletin hukuk departmanı tarafından bir soruşturmanın konusu. , beyazlık karşıtı diye sızlanmak ve translara karşı bağnaz olmak. Deseret milliyetçileri olarak bilinen aşırılık yanlısı bir Mormon grubunun sözde destekçisi olarak (“Mormon” ve “Deseret” yerine “beyaz” okursanız, görünüşe göre çok uzakta değilsiniz), yetkili nefretini arkasına saklamakla suçlanıyor. bir takma ad.
Kuşları beslemek eğlenceli olabilir - sorun şu ki gölette ördek ve kaz beslemek çoğumuzun düşündüğünden çok daha zararlı. Kilerinizden yerel sudaki vahşi yaşam yiyeceklerini vermek sadece onların diyetini değiştirmekle kalmaz, aynı zamanda çevreyi de değiştirir.
Adam Driver (Le Gris) Ridley Scott'ın yakında çıkacak olan tarihi destanının fragmanı, pek çok şıngırdayan zırhı, suçlamaları ve Adam Driver'ın iyi bir eski haykırışını içeriyor. 2 dakika boyunca, güçlü bir oyuncu kadrosuyla desteklenen büyük görüntülerle, bir kadına karşı işlenen bir suç, The Last Duel'de kılıçlarla savaşan iki adam arasındaki bir çatışmanın çerçevesi haline gelir.
24 yaşındaki Juan Miranda-Jara, bebeği dünyaya getirmek için Oklahoma hastanesine 12 yaşındaki bir kızı getirdikten sonra tutuklandı ve tecavüzle suçlandı.
Kim Kardashian West, eski Kanye West ile dört çocuğu paylaşıyor: kızları North, 8 ve Chicago, 3, artı oğulları Saint, 5½ ve Psalm, 2
Lindsey Vonn ve Diego Osorio birlikte spor salonuna gittiler, Anna Kendrick yeni filmi Larsa Pippen'ın Miami sahiline vurduğu sette görüldü. Yıldızların ne yaptığını görün.
Dünyada neredeyse hiç kimse yedi kez Olimposlu olmadı. Kim Rhode değil