Hi, On Sun, 2017-08-20 at 08:57 +0000, Milan Mimica wrote: > Hello > > I'm (still) trying to figure our high memory usage by PRT. I have > studied heapRegionRemSet.cpp code and came up with a calculation I > need you to confirm. Given region size of 8M and default G1 settings: > * max number of PRT instances is 2^12 for each HR
Where did you get the 2^12 from? > * PRT size is 64MB Not completely following, where from do you understand that max prt size is 64MB? 8M region size implies a 2k PRT (bitmap) size (one bit per 512 bytes) > > I'm looking at the worst-case scenario and I don't dare to multiply > the tree numbers. The cap is just to high. Am I missing something? > Do only Young HR get a OtherRegionsTable? All regions get them. But there are no PRTs from young regions to old regions. Humongous continues regions don't have any remembered set. > Where can I find the number of regions per generation? I cannot spot > it in GC logs. -Xlog:gc+heap=info gives you the following kind of output: [15.369s][info ][gc,heap ] GC(0) Eden regions: 3->0(576) [15.369s][info ][gc,heap ] GC(0) Survivor regions: 0->0(0) [15.369s][info ][gc,heap ] GC(0) Old regions: 0->1 [15.369s][info ][gc,heap ] GC(0) Humongous regions: 0->0 Here is some rough calculation for remembered set size for jdk8 (copy&pasted from some other email from some time ago - I did not check it again, so there might be some omissions): "[...] for every region in #non-young-regions: e1) coarse table: one bit for every #regions + MAX( e2) sparse table: (2 * #regions) * (8 + #sparse-entries * 4) e3) fine table: MIN(#fine-entries, #non-young-regions - 1) * (bit per #cards-per-region + 8 + 56) ) where: #regions = maximum number of regions in heap = -Xmx / G1HeapRegionSize #cards-per-region = G1HeapRegionSize / 512 #non-young-regions = #regions - #minimum-number-of-young-regions #minimum-number-of-regions = #regions * G1NewSizePercent / 100 #sparse-entries = G1RSetSparseRegionEntries #fine-entries = MIN(G1RSetRegionEntries, #non-young-regions) Default values of options: G1NewSizePercent = 5 G1RSetSparseRegionEntries = G1RSetSparseRegionEntriesBase * (log2(#G1HeapRegionSize-in-MB) + 1) G1RSetSparseRegionEntriesBase = 4 This is I think a reasonably accurate worst case memory usage. [...] The remembered set holds the greatest potential (but also the largest risk to introduce performance issues) for savings. This is due to the fact that actually every entry in a remembered set (there, every region A stores for every other region x_0, ..., x_n the cards that contain references to A) can either take memory in e1, e2, or e3 (actually only the latter two for simplicity). I.e. G1 can represent such an x_i in one of the data structures of e1, e2, and e3, with different memory/performance characteristics. The direction of representation is e2, then e3 and finally e1 (unfortunately there is no way to go back; when a region is freed, its remembered set goes back to e2). So what could be tried is trying to keep x_i at e2 level - that can be controlled by G1RSetSparseRegionEntries. A given value of G1RSetSparseRegionEntries indicates how many cards it can store - if that is not enough, it expands to e3. (Just for reference: G1RSetRegionEntries determines how many of e3 a remembered set for a region A can hold - if more, it selects one to evict to e1; this is the dreaded "coarsening" if you ever heard of it. Setting G1RSetRegionEntries to something >= the number of regions avoids that coarsening) Since e2 is slightly more memory efficient, it might be worth trying to bump G1RSetSparseRegionEntries. If you think all what I explained above is gibberish to you, and you are still interested, I can try to explain it a bit better :) JDK9 made e2 more memory-efficient (only takes 1/4th of memory as before), and does not create e1 if not needed. [...]" Hth, Thomas _______________________________________________ hotspot-gc-use mailing list hotspot-gc-use@openjdk.java.net http://mail.openjdk.java.net/mailman/listinfo/hotspot-gc-use