Pengumpulan sampah Java G1 dalam produksi

91

Karena Java 7 akan menggunakan pengumpulan sampah G1 baru secara default, apakah Java akan mampu menangani urutan heap yang besarnya lebih besar tanpa waktu jeda GC yang seharusnya "menghancurkan"? Adakah yang benar-benar menerapkan G1 dalam produksi, apa pengalaman Anda?

Agar adil, satu-satunya saat saya melihat jeda GC yang sangat lama berada di tumpukan yang sangat besar, jauh lebih banyak daripada yang akan dimiliki workstation. Untuk memperjelas pertanyaan saya; akankah G1 membuka gateway ke tumpukan dalam ratusan GB? TB?

benstpierre
sumber
16
Meskipun bisa diutarakan secara lebih spesifik, ini bukanlah pertanyaan yang mengerikan. Saya sangat berharap orang-orang harus menjelaskan diri mereka lebih baik daripada "Bukan pertanyaan" saat pemungutan suara untuk menutup.
Bill K
Saya tidak memilih untuk menutup, tetapi saya berharap OP telah melakukan pekerjaan yang lebih obyektif dalam merinci keluhannya dengan GC saat ini. Juga, "Java" adalah bahasa saat dia berbicara tentang implementasi, dan saya tidak tahu apa arti "mengimplementasikan G1 dalam produksi", terutama dengan kalimat masa depan dari sisa pertanyaannya. Jika akan di Java 7, pasti belum ada yang menggunakannya dalam produksi?
Pascal Cuoq
6
@Pascal G1 telah menjadi fitur eksperimental yang tersedia di JDK sejak JDK 6 update 14. Dengan "mengimplementasikan G1 dalam produksi", saya pikir maksudnya benar-benar menggunakannya, tidak terlalu sulit untuk dipahami. Dan meskipun saya setuju bahwa G1 adalah bagian dari JDK 7, bukan Java, penelusuran untuk Java 7 di Google mengembalikan beranda JDK 7 sebagai hasil pertama, dan kedua istilah tersebut sering digunakan secara bergantian. @Benju Saya tidak akan mempercayai hasil yang diperoleh dengan G1 di JDK saat ini karena masih eksperimental, banyak hal dapat berubah dari sekarang ke rilis resmi.
teto
2
Sepertinya JDK 7 termasuk update 1,2 dan 3 tidak menggunakan G1 gc secara default. Anda dapat memeriksa dengan jinfo -flag UseG1GC pid
George

Jawaban:

34

Sepertinya titik G1 memiliki waktu jeda yang lebih kecil, bahkan pada titik di mana ia memiliki kemampuan untuk menentukan target waktu jeda maksimum.

Pengumpulan sampah tidak hanya sekadar "Hei, sudah penuh, mari kita pindahkan semuanya sekaligus dan mulai lagi" menangani lagi - ini sangat rumit, multi-level, sistem ulir latar belakang. Itu dapat melakukan banyak pemeliharaan di latar belakang tanpa jeda sama sekali, dan itu juga menggunakan pengetahuan tentang pola yang diharapkan sistem pada waktu proses untuk membantu - seperti mengasumsikan sebagian besar objek mati tepat setelah dibuat, dll.

Saya akan mengatakan waktu jeda GC akan terus meningkat, bukan memburuk, dengan rilis di masa mendatang.

EDIT:

dalam membaca ulang, terpikir oleh saya bahwa saya menggunakan Java setiap hari - Eclipse, Azureus, dan aplikasi yang saya kembangkan, dan sudah lama sekali sejak saya melihat jeda. Bukan jeda yang signifikan, tapi maksud saya jeda sama sekali.

Saya telah melihat jeda ketika saya mengklik kanan pada windows explorer atau (kadang-kadang) ketika saya menghubungkan perangkat keras USB tertentu, tetapi dengan Java --- tidak ada sama sekali.

Apakah GC masih menjadi masalah dengan siapa pun?

Bill K
sumber
Setuju - satu-satunya saat saya melihat jeda GC adalah ketika saya secara sengaja atau tidak sengaja memprovokasi mereka dengan kode pembuatan sampah paralel besar-besaran .....
mikera
28
Ya, GC masih menjadi masalah besar ketika Anda mulai berurusan dengan tumpukan besar (> 16 GB), terutama dengan generasi bertenor besar.
The Alchemist
2
@ the-alkemis wow, saya telah melihat komentar Anda lewat beberapa kali dan saya baru sadar bahwa Anda mengatakan 16 GB !! Meskipun saya benar-benar yakin Anda benar bahwa ini dapat menyebabkan penundaan besar, saya ingin memeriksa apakah Anda menonaktifkan SEMUA swapping. Pada sistem memori yang besar, setiap swapping java benar-benar akan mematikan sistem Anda (Karena GC sangat tidak bersahabat dengan swap). Saya yakin Anda telah melakukan ini, tetapi saya hanya ingin menyebutkannya - karena itu akan membuat perbedaan yang sangat besar. Saya belum pernah melihat PC dengan ram sebanyak itu - berapa banyak yang Anda miliki? 32g?
Bill K
8
Ya, GC bermasalah untuk layanan karena itulah yang membuatnya SANGAT sulit untuk meningkatkan batas TP99.9 (dan lebih tinggi). Secara spesifik, GC "generasi lama" bisa menjadi perangkap maut yang membekukan JVM (dan layanan) selama beberapa detik; dan untuk layanan yang biasanya melayani permintaan dalam mili detik satu digit (atau dua digit rendah), ini bermasalah. Untuk apa nilainya, ini adalah masalah praktis dengan penyimpanan backend yang digunakan oleh layanan Simple Queue Amazon (tidak dapat menjelaskan banyak detail karena ini internal AWS).
StaxMan
21
Hal yang menjengkelkan tentang GC adalah Azul menemukan beberapa tahun yang lalu algoritma GC yang cerdik (Azul C4) yang dapat dengan mudah mengatasi ratusan gigabyte tanpa waktu jeda yang nyata dengan memanfaatkan perangkat keras memori prosesor dengan sangat cerdas. Tetapi tidak ada yang mengetahui hal ini dan itu tidak akan segera diimplementasikan dalam versi Java utama karena membutuhkan dukungan dari sistem operasi. Dan vendor sistem operasi tidak akan melakukan apa-apa sampai orang-orang mengetahui tentang algoritme tersebut dan menekan vendor sistem operasi tersebut. Lihat azulsystems.com/zing/pgc , managedruntime.org
Hans-Peter Störr
58

Saya telah mengujinya dengan aplikasi yang berat: 60-70 GB dialokasikan ke heap, dengan 20-50 GB digunakan kapan saja. Dengan aplikasi semacam ini, sangat tidak pantas untuk mengatakan bahwa jarak tempuh Anda mungkin berbeda. Saya menjalankan JDK 1.6_22 di Linux. Versi minor itu penting-- sebelum sekitar 1.6_20, ada bug di G1 yang menyebabkan NullPointerExceptions acak.

Saya telah menemukan bahwa sangat bagus dalam menjaga target jeda yang Anda berikan sebagian besar waktu. Defaultnya tampaknya jeda 100ms (0,1 detik), dan saya telah menyuruhnya untuk melakukan setengahnya (-XX: MaxGCPauseMillis = 50). Namun, begitu memori benar-benar rendah, ia panik dan melakukan pengumpulan sampah di seluruh dunia. Dengan 65GB, itu membutuhkan waktu antara 30 detik dan 2 menit. (Jumlah CPU mungkin tidak membuat perbedaan; mungkin dibatasi oleh kecepatan bus.)

Dibandingkan dengan CMS (yang bukan GC server default, tetapi seharusnya untuk server web dan aplikasi real-time lainnya), jeda biasa jauh lebih dapat diprediksi dan dapat dibuat jauh lebih singkat. Sejauh ini saya lebih beruntung dengan CMS untuk jeda yang sangat lama, tapi itu mungkin acak; Saya melihat mereka hanya beberapa kali setiap 24 jam. Saya tidak yakin mana yang lebih cocok untuk lingkungan produksi saya saat ini, tapi mungkin G1. Jika Oracle terus menyetelnya, saya menduga G1 pada akhirnya akan menjadi pemenang yang jelas.

Jika Anda tidak mengalami masalah dengan pengumpul sampah yang ada, tidak ada alasan untuk mempertimbangkan G1 saat ini. Jika Anda menjalankan aplikasi latensi rendah, seperti aplikasi GUI, G1 mungkin adalah pilihan yang tepat, dengan MaxGCPauseMillis disetel sangat rendah. Jika Anda menjalankan aplikasi mode batch, G1 tidak akan membeli apa pun.

David Leppik
sumber
14

Meskipun saya belum menguji G1 dalam produksi, saya pikir saya akan berkomentar bahwa GC sudah bermasalah untuk kasus-kasus tanpa tumpukan yang "sangat besar". Khususnya layanan dengan, katakanlah, 2 atau 4 pertunjukan bisa sangat terpengaruh oleh GC. GC generasi muda biasanya tidak bermasalah karena mereka selesai dalam milidetik satu digit (atau paling banyak dua digit). Tetapi koleksi generasi lama jauh lebih bermasalah karena memerlukan beberapa detik dengan ukuran generasi lama 1 pertunjukan atau lebih.

Sekarang: dalam teori CMS dapat membantu banyak di sana, karena dapat menjalankan sebagian besar operasinya secara bersamaan. Namun, seiring waktu akan ada kasus di mana ia tidak dapat melakukan ini dan harus kembali ke koleksi "hentikan dunia". Dan ketika itu terjadi (setelah, katakanlah, 1 jam - tidak sering, tapi masih terlalu sering), pegang topi Anda. Ini bisa memakan waktu satu menit atau lebih. Ini khususnya bermasalah untuk layanan yang mencoba membatasi latensi maksimum; alih-alih membutuhkan, katakanlah, 25 milidetik untuk melayani permintaan, kini dibutuhkan sepuluh detik atau lebih. Untuk menambah cedera pada penghinaan, klien akan sering meminta waktu habis dan mencoba lagi, yang mengarah ke masalah lebih lanjut (alias "badai kotoran").

Ini adalah salah satu area di mana G1 diharapkan dapat banyak membantu. Saya bekerja untuk perusahaan besar yang menawarkan layanan cloud untuk penyimpanan dan pengiriman pesan; dan kami tidak dapat menggunakan CMS karena meskipun sebagian besar waktu CMS bekerja lebih baik daripada varietas paralel, CMS mengalami gangguan ini. Jadi selama sekitar satu jam semuanya menyenangkan; dan kemudian hal-hal menghantam kipas ... dan karena layanan didasarkan pada cluster, ketika satu node mendapat masalah, node lain biasanya mengikuti (karena waktu tunggu yang diinduksi GC mengarah ke node lain yang percaya node telah crash, mengarah ke perutean ulang).

Saya tidak berpikir GC adalah masalah besar bagi aplikasi, dan bahkan mungkin layanan non-cluster tidak terlalu sering terpengaruh. Tetapi semakin banyak sistem yang dikelompokkan (terutama berkat penyimpanan data NoSQL) dan ukuran heap bertambah. OldGen GC terkait secara super linier dengan ukuran heap (artinya menggandakan ukuran heap lebih dari dua kali lipat waktu GC, dengan asumsi ukuran kumpulan data langsung juga berlipat ganda).

StaxMan
sumber
13

CTO Azul, Gil Tene, memiliki gambaran bagus tentang masalah yang terkait dengan Pengumpulan Sampah dan ulasan tentang berbagai solusi dalam presentasinya Memahami Pengumpulan Sampah Jawa dan Apa yang Dapat Anda Lakukan tentangnya , dan ada detail tambahan dalam artikel ini: http: // www.infoq.com/articles/azul_gc_in_detail .

Pengumpul Sampah C4 Azul di Zing JVM kami paralel dan bersamaan, dan menggunakan mekanisme GC yang sama untuk generasi baru dan lama, bekerja secara bersamaan dan memadatkan di kedua kasus. Yang terpenting, C4 tidak memiliki stop-the-world fallback. Semua pemadatan dilakukan secara bersamaan dengan aplikasi yang berjalan. Kami memiliki pelanggan yang menjalankan sangat besar (ratusan GByte) dengan kasus waktu jeda GC yang lebih buruk <10 mdetk, dan bergantung pada aplikasi sering kali kurang dari 1-2 mdet.

Masalah dengan CMS dan G1 adalah bahwa pada titik tertentu memori heap Java harus dipadatkan, dan kedua pengumpul sampah tersebut stop-the-world / STW (yaitu menghentikan sementara aplikasi) untuk melakukan pemadatan. Jadi, meskipun CMS dan G1 dapat mengeluarkan jeda STW, mereka tidak menghilangkannya. C4 Azul, bagaimanapun, benar-benar menghilangkan jeda STW dan itulah mengapa Zing memiliki jeda GC yang rendah bahkan untuk ukuran tumpukan raksasa.

Dan untuk mengoreksi pernyataan yang dibuat dalam jawaban sebelumnya, Zing tidak memerlukan perubahan apa pun pada Sistem Operasi. Ini berjalan seperti JVM lainnya pada distro Linux yang tidak dimodifikasi.

Scott Sellers
sumber
3
Saya hanya ingin tahu bagaimana Azul C4 mencapai apa yang Anda katakan dan mengapa Sun atau Oracle tidak bisa. Apakah ada rahasia besar atau ini hanya semacam pertukaran?
George
5
C4 Azul memiliki teknologi yang sangat unik yang berasal dari peralatan komputasi perangkat keras Azul (yang menggunakan prosesor khusus yang dibuat untuk menjalankan aplikasi Java perusahaan) dan telah berevolusi untuk berjalan di server x86 biasa yang menjalankan Linux. Setiap pengumpul sampah kelas perusahaan lainnya (baik dari Oracle atau IBM) di beberapa titik harus melakukan jeda stop-the-world - atribut unik C4 Azul adalah bahwa ia tidak pernah melakukan jeda STW yang bermasalah ini. Jika Anda penasaran, penemu kolektor C4 menerbitkan makalah tentang cara kerjanya: dl.acm.org/citation.cfm?id=1064988 .
Scott Sellers
Scott, saya membaca di sini blog.mikemccandless.com/2012/07/… bahwa Azul mengirimkan modul kernel yang mengalokasikan memori untuk penggunaan JVM. Apa ini tidak benar? Jika benar, tidak banyak yang merupakan modifikasi kernel tetapi masih merupakan modifikasi.
Dan Pritts
4
George, dua kata: dilindungi paten. Dan, saat Anda membeli Zing, bagian dari apa yang Anda bayar adalah meminta dukungan mereka agar orang-orang menyetelnya untuk aplikasi Anda-- dan itu termasuk mengalokasikan penggunaan memori sistem secara keseluruhan. Modul kernel itu sendiri mencegah penulisan ke blok memori yang sedang dikumpulkan sampahnya. Itulah saus rahasia yang membuatnya "tanpa jeda": utas hanya akan berhenti jika mereka mencoba menulis ke salah satu blok itu, dan kemudian hanya cukup lama untuk memadatkan blok itu.
David Leppik
13

Kami sudah menggunakan G1GC, selama hampir dua tahun. Ini berfungsi dengan baik dalam sistem pemrosesan transaksi penting misi kami, dan terbukti menjadi dukungan yang hebat dengan throughput tinggi, jeda rendah, konkurensi, dan manajemen memori berat yang dioptimalkan.

Kami menggunakan pengaturan JVM berikut:

-server -Xms512m -Xmx3076m -XX:NewRatio=50 -XX:+HeapDumpOnOutOfMemoryError -XX:+UseG1GC -XX:+AggressiveOpts -XX:+UnlockExperimentalVMOptions -XX:MaxGCPauseMillis=400 -XX:GCPauseIntervalMillis=8000 -XX:+PrintGCTimeStamps -XX:+PrintGCApplicationStoppedTime -XX:+PrintGCApplicationConcurrentTime

Diperbarui

-d64 -server -Xss4m -Xms1024m -Xmx4096m -XX:NewRatio=50 -XX:+UseG1GC -XX:+UnlockExperimentalVMOptions -XX:+HeapDumpOnOutOfMemoryError -XX:-DisableExplicitGC -XX:+AggressiveOpts -Xnoclassgc -XX:+UseNUMA -XX:+UseFastAccessorMethods -XX:ReservedCodeCacheSize=48m -XX:+UseStringCache -XX:+UseStringDeduplication -XX:MaxGCPauseMillis=400 -XX:GCPauseIntervalMillis=8000
emkays
sumber
5
Di Java 8, Anda tidak perlu menyetel -XX: + UseCompressedOops atau -XX: + DoEscapeAnalysis, booth aktif sebagai default. Lihat: docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html
Mirko Ebert
8

Kolektor G1 mengurangi dampak koleksi lengkap. Jika Anda memiliki aplikasi di mana Anda telah mengurangi kebutuhan untuk koleksi lengkap, pengumpul Sapu peta Bersamaan sama baiknya dan menurut pengalaman saya memiliki waktu pengumpulan kecil yang lebih singkat.

Peter Lawrey
sumber
"perhatikan bahwa penggunaan produksi G1 hanya diizinkan jika kontrak dukungan Java telah dibeli.", groups.google.com/forum/#!topic/javaposse/Vm0a4H-QY54 , jadi apakah itu mitos atau bukan?
Christophe Roussy
1
@ChristopheRoussy Saya tidak tahu apakah ini benar lagi (atau memang memiliki bukti bahwa itu pernah benar) Itu tidak memerlukan -XX: + UnlockCommercialFeatures jadi saya curiga bahwa G1 tidak memerlukan lisensi.
Peter Lawrey
5

Baru-baru ini saya telah dipindahkan dari

CMS ke G1GC dengan prosesor heap 4G & 8 inti di server dengan JDK 1.7.45 .

(JDK 1.8.x G1GC lebih disukai daripada 1.7 tetapi karena beberapa batasan, saya harus tetap menggunakan versi 1.7.45)

Saya telah mengonfigurasi di bawah parameter kunci dan menyimpan semua parameter lainnya ke nilai default.

-XX:G1HeapRegionSize=n, XX:MaxGCPauseMillis=m, -XX:ParallelGCThreads=n, 
-XX:ConcGCThreads=n apart from -Xms and -Xmx

Jika Anda ingin menyempurnakan parameter ini, lihat artikel oracle ini.

Pengamatan kunci:

  1. Penggunaan memori konsisten dengan G1GC tidak seperti tinggi & terendah dengan CMS
  2. Waktu jeda GC maksimum lebih singkat dibandingkan dengan CMS
  3. Waktu yang dihabiskan dalam pengumpulan Sampah di G1GC sedikit lebih tinggi dibandingkan dengan CMS.
  4. Jumlah koleksi utama hampir dapat diabaikan dibandingkan dengan CMS
  5. Jumlah koleksi minor berada di ujung yang lebih tinggi dibandingkan dengan CMS

Tapi tetap saya senang bahwa waktu jeda Max GC kurang dari pada CMS. Saya telah menyetel waktu jeda Max GC sebagai 1,5 detik dan nilai ini belum terlampaui.

Pertanyaan SE terkait:

Pengumpulan dan dokumentasi sampah Java 7 (JDK 7) di G1

Ravindra babu
sumber
4

CMS dapat menyebabkan kinerja yang menurun secara perlahan meskipun Anda menjalankannya tanpa mengumpulkan objek bertenor. Ini karena fragmentasi memori yang seharusnya dihindari oleh G1.

Mitos tentang G1 yang hanya tersedia dengan dukungan berbayar hanyalah mitos. Sun dan sekarang Oracle telah mengklarifikasi hal ini di halaman JDK.

Ted Dunning
sumber
4

G1 GC seharusnya bekerja lebih baik. Namun jika menyetel -XX: MaxGCPauseMill terlalu agresif, sampah akan terkumpul terlalu lambat. Dan itulah mengapa GC penuh dipicu dalam contoh David Leppik.

tanda hubung
sumber
4

Saya baru saja menerapkan G1 Garbage Collector di proyek Terracotta Big Memory kami. Saat mengerjakan berbagai jenis kolektor, G1 memberi kami hasil terbaik dengan waktu respons kurang dari 600ms.

Anda dapat menemukan hasil tes (total 26) di sini

Semoga membantu.

Spanglish
sumber
3

Saya baru-baru ini memigrasikan bagian dari Twicsy ke server baru dengan RAM 128GB dan memutuskan untuk menggunakan 1.7. Saya mulai menggunakan semua pengaturan memori yang sama seperti yang saya gunakan dengan 1.6 (Saya memiliki beberapa contoh yang menjalankan berbagai hal, mulai dari tumpukan 500mb hingga 15GB, dan sekarang yang baru dengan 40GB) dan itu tidak berjalan dengan baik sama sekali . 1.7 tampaknya menggunakan lebih banyak heap daripada 1.6, dan saya mengalami banyak masalah selama beberapa hari pertama. Untungnya, saya memiliki banyak RAM untuk digunakan dan meningkatkan RAM untuk sebagian besar proses saya, tetapi masih mengalami beberapa masalah. MO normal saya adalah menggunakan ukuran heap minimum yang sangat kecil yaitu 16m, bahkan dengan heap maksimum beberapa gigabyte, lalu aktifkan GC tambahan. Ini meminimalkan jeda. Namun itu tidak berfungsi sekarang, dan saya harus meningkatkan ukuran minimum menjadi tentang apa yang saya harapkan untuk digunakan rata-rata di heap, dan itu berhasil dengan sangat baik. Saya masih mengaktifkan GC tambahan, tetapi saya akan mencobanya tanpa. Tidak ada jeda apa pun sekarang, dan segala sesuatunya tampak berjalan sangat cepat. Jadi, menurut saya pesan moral dari cerita ini adalah jangan berharap pengaturan memori Anda diterjemahkan dengan sempurna dari 1.6 ke 1.7.

Chris Seline
sumber
2

G1 membuat aplikasi jauh lebih gesit: kemunduran aplikasi akan meningkat - aplikasi dapat dinamai "soft-real-time". Ini dilakukan dengan mengganti dua jenis rangkaian GC (yang kecil kecil dan yang besar pada Gen Bertenur) menjadi yang berukuran sama kecil.

Untuk lebih jelasnya lihat ini: http://geekroom.de/java/java-expertise-g1-fur-java-7/

Daniel
sumber
1

Saya bekerja dengan Java, untuk Heap kecil dan besar, dan pertanyaan tentang GC dan GC Penuh muncul setiap hari, karena batasannya mungkin lebih ketat daripada yang lain: di lingkungan tertentu, 0,1 detik dari GC pemulung atau GC Penuh, matikan hanya analisis fonction, dan memiliki konfigurasi yang sangat baik dan kapabilitas yang penting (CMS, iCMS, lainnya ... target ada di sini untuk mendapatkan waktu respons terbaik dengan perlakuan hampir waktu nyata (di sini perlakuan waktu nyata sering kali 25 md) , jadi, pada dasarnya, setiap peningkatan dalam ergonomi dan heuristik GC dipersilakan!

Fuby
sumber
1

Saya menggunakan G1GC di Java 8 dan juga dengan Groovy (juga Java 8), dan saya melakukan berbagai jenis beban kerja, dan secara umum G1GC bekerja seperti ini:

  • Penggunaan memori sangat rendah, misalnya 100MB, bukan 500MB dibandingkan dengan pengaturan Java default

  • Waktu responsnya konsisten dan sangat rendah

  • Kinerja antara pengaturan default dan G1GC adalah 20% perlambatan saat menggunakan G1GC dalam skenario kasus terburuk (tanpa tuning, aplikasi single-threaded). Ini tidak banyak mempertimbangkan waktu respons yang baik dan penggunaan memori yang rendah.

  • Saat dijalankan dari Tomcat yang multi-threaded, performa keseluruhan 30% lebih baik dan penggunaan memori jauh lebih rendah serta waktu respons yang jauh lebih rendah.

Jadi secara keseluruhan, saat menggunakan beban kerja yang sangat beragam, G1GC adalah kolektor yang sangat baik untuk Java 8 untuk aplikasi multi-thread, dan bahkan untuk single-threaded ada beberapa keuntungan.

Andrew
sumber
0

Tidak disarankan untuk menggunakan java8 w / G1GC untuk penghitungan titik mengambang dengan JVM seperti hotspot. Berbahaya untuk integritas & akurasi aplikasi.

https://bugs.openjdk.java.net/browse/JDK-8148175

JDK-8165766

JDK-8186112

pengguna7796409
sumber