6. JDK 9 のデフォルトGCが G1GC
スループットとポーズタイムを同時に実現
G1GC
Copyright 2017 FUJITSU LIMITED
https://docs.oracle.com/javase/9/gctuning/garbage-first-garbage-collector.htm
It attempts to meet garbage collection pause-time
goals with high probability while achieving high
throughput with little need for configuration.
HotSpot Virtual Machine Garbage Collection Tuning Guide
5
8. 大容量メモリ対応
Copyright 2017 FUJITSU LIMITED
The Garbage-First (G1) garbage collector is targeted for
multiprocessor machines with a large amount of
memory.
https://docs.oracle.com/javase/9/gctuning/garbage-first-garbage-collector.htm
HotSpot Virtual Machine Garbage Collection Tuning Guide
大容量メモリ搭載マシンをターゲット
ご希望に応えて、大容量メモリ搭載マシンで性能比較
7
9. 1 public class GCTest extends Thread
2 {
3 static final int N = 7000000;
4 static final int M = 4;
5 static GCTest[] g;
6 Object[] objs = new Object[N];
7
8 public static void main(String ... arg) throws Exception
9 {
10 g = new GCTest[M];
11 for (int i = 0 ; i < M ; ++i)
12 g[i] = new GCTest();
13
14 System.out.println("warm up ...");
15 for (int i = 0 ; i < N ; ++i)
16 for (int j = 0 ; j < M ; ++j)
17 g[j].doIt(i);
18
19 System.out.println("start");
20
21 for (int j = 0 ; j < M ; ++j)
22 g[j].start();
23 }
24 public void run() {
25 long start = System.currentTimeMillis();
26 for (int j = 0 ; j < 60 ; ++j)
27 for (int i = 0 ; i < N ; ++i)
28 doIt(i);
29 long end = System.currentTimeMillis();
30 System.out.println("time: " + (end-start) + "ms");
31 }
32
33 void doIt(int i) {
34 if (objs[i] == null)
35 objs[i] = new X();
36 else
37 objs[i] = g[i%M].objs[i];
38 }
39
40 static class X {
41 byte[] b = new byte[128];
42 }
ソース
Copyright 2017 FUJITSU LIMITED8
31. メモリバリア
Copyright 2017 FUJITSU LIMITED
http://gee.cs.oswego.edu/dl/jmm/cookbook.html
各CPUで微妙に違うが、大まかな概念はだいたい同じ
4種類のメモリバリア
JSR-133 Cookbook
LoadLoad/StoreStore/LoadStore/StoreLoad
CPUから見て、StoreLoadが最もコスト大
The sequence: Store1; StoreLoad; Load2
ensures that Store1's data are made visible to other
processors (i.e., flushed to main memory) before
data accessed by Load2 and all subsequent load
instructions are loaded.
30
39. HotSpot(JIT/G1GC)ソース
Copyright 2017 FUJITSU LIMITED
void GraphKit::g1_write_barrier_post(Node* oop_store,
・・・・
// Offsets into the thread
const int index_offset = in_bytes(JavaThread::dirty_card_queue_offset() +
DirtyCardQueue::byte_offset_of_index());
const int buffer_offset = in_bytes(JavaThread::dirty_card_queue_offset() +
DirtyCardQueue::byte_offset_of_buf());
// Pointers into the thread
Node* buffer_adr = __ AddP(no_base, tls, __ ConX(buffer_offset));
Node* index_adr = __ AddP(no_base, tls, __ ConX(index_offset));
// Now some values
// Use ctrl to avoid hoisting these values past a safepoint, which could
// potentially reset these fields in the JavaThread.
Node* index = __ load(__ ctrl(), index_adr, TypeX_X, TypeX_X->basic_type(), Compile::AliasIdxRaw);
Node* buffer = __ load(__ ctrl(), buffer_adr, TypeRawPtr::NOTNULL, T_ADDRESS, Compile::AliasIdxRaw);
// Convert the store obj pointer to an int prior to doing math on it
// Must use ctrl to prevent "integerized oop" existing across safepoint
Node* cast = __ CastPX(__ ctrl(), adr);
// Divide pointer by card size
Node* card_offset = __ URShiftX( cast, __ ConI(CardTableModRefBS::card_shift) );
// Combine card table base and card offset
Node* card_adr = __ AddP(no_base, byte_map_base_node(), card_offset );
__ if_then(card_val, BoolTest::ne, young_card); {
sync_kit(ideal);
// Use Op_MemBarVolatile to achieve the effect of a StoreLoad barrier.
insert_mem_bar(Op_MemBarVolatile, oop_store);
__ sync_kit(this);
share/vm/opto/graphKit.cpp
38
41. Mark & Evacuation
Copyright 2017 FUJITSU LIMITED
region 1 free region
root set
region 1
Mark Evacuation
garbage
コピー
40
42. コンカレントマーク
Copyright 2017 FUJITSU LIMITED
region 1 free region
root set
region 1
Mark Evacuation
region 1
Application
不当に
garbage扱い
コピー
region 2
41
43. ストアバリア
Copyright 2017 FUJITSU LIMITED
region 1 free region
root set
region 1
Mark Evacuation
region 1
root set扱い
Remember Set
コピー
Application
region 2
42