Slide 1

Slide 1 text

2018年12月15日 数村 憲治 GCを発生させない コーディングパターン Copyright 2018 FUJITSU LIMITED 0 JJUG CCC 2018 Fall

Slide 2

Slide 2 text

.setName(“数村憲治”) .setDirectorOf(“Eclipse Foundation Board”) .setMemberOf(“Jakarta EE Committee”) .setMemberOf(“JCP Executive Committee”) .setTwitter(“@kkzr”) .setResponsibleFor(“Launcher”) .build(); スピーカー Copyright 2018 FUJITSU LIMITED Speaker me = SpeakerBuilder 1

Slide 3

Slide 3 text

アジェンダ Copyright 2018 FUJITSU LIMITED GC問題 アプリケーションによる対処 コンパイラによる対処 サマリ 2

Slide 4

Slide 4 text

アジェンダ Copyright 2018 FUJITSU LIMITED GC問題 アプリケーションによる対処 コンパイラによる対処 サマリ 3

Slide 5

Slide 5 text

何が問題か Copyright 2018 FUJITSU LIMITED 健康診断シンドローム アプリケーションの実行が止まる アプリケーションに割り当てられるCPU時間が減る 実は何も問題ない 4

Slide 6

Slide 6 text

なぜ問題か Copyright 2018 FUJITSU LIMITED (Cでは、malloc/free回数に依存) チューニングがたいへん 最適解をみつけるのが難しい 環境が変わるとやりなおし 見積もりができない GC時間は残存オブジェクトに依存 5

Slide 7

Slide 7 text

問題の対処方法 Copyright 2018 FUJITSU LIMITED あきらめる SLAの妥協 Javaを使わない オブジェクトの 生成数・量を減らす アプリケーションで頑張る GCで頑張る コンパイラで頑張る 優秀なGCを作る オブジェクトの 生成を最適化 6

Slide 8

Slide 8 text

デモ Copyright 2018 FUJITSU LIMITED 7 Node.js

Slide 9

Slide 9 text

アジェンダ Copyright 2018 FUJITSU LIMITED GC問題 アプリケーションによる対処 コンパイラによる対処 サマリ 8

Slide 10

Slide 10 text

アプリケーションで頑張る Copyright 2018 FUJITSU LIMITED オブジェクトプール スレッドプール コネクションプール 小ネタ HashMap 拡張 String.intern() Boxing/Unboxing 9

Slide 11

Slide 11 text

Integer AutoBoxing Copyright 2018 FUJITSU LIMITED 10 public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); } キャッシュの範囲はプロパティで指定可能 java.lang.Integer.IntegerCache.high よく使われる範囲はIntegerオブジェクトの使いまわし Integer.java

Slide 12

Slide 12 text

プーリングコスト Copyright 2018 FUJITSU LIMITED 1*(メモリ割当+初期化) + p*GCp n*(メモリ割当+初期化) + u*GCu プーリング使用時 プーリング不使用時 n: トランザクション回数 p: プーリング使用時のGC回数 u: プーリング不使用時のGC回数 GCp: プーリング使用時の1回のGC時間 GCu: プーリング不使用時の1回のGC時間 p < u GCp > GCu 初期化 < n*初期化 メモリ割当は問題にならない 11 一般的な傾向

Slide 13

Slide 13 text

Edenからのアロケーション Copyright 2018 FUJITSU LIMITED o = new Object(); bottom top end lock(Eden); top = top + size; unlock(Eden); Bump The Pointer bottom top end 12

Slide 14

Slide 14 text

TLAB Copyright 2018 FUJITSU LIMITED (*1)https://www.oracle.com/technetwork/java/javase/memorymanagement-whitepaper-150215.pdf only requiring around 10 native instructions Memory Management in the Java HotSpot Virtual Machine (*1) TLAB + Bump the Pointer で実現 Edenをスレッドごとに分割して割当て スレッド1スレッド2 Thread-Local Allocation Buffer Fast Allocation 13

Slide 15

Slide 15 text

デモ Copyright 2018 FUJITSU LIMITED 14 Bump The Pointer

Slide 16

Slide 16 text

TLABが向かないケース Copyright 2018 FUJITSU LIMITED スレッド N+1 用のTLABが割当てられない スレッド1スレッド2 スレッドN ・・・ スレッド数が多く、かつ、オブジェクト生成量が少ない場合 15

Slide 17

Slide 17 text

デモ Copyright 2018 FUJITSU LIMITED 16 Thread-Local Allocation Buffer

Slide 18

Slide 18 text

アジェンダ Copyright 2018 FUJITSU LIMITED GC問題 アプリケーションによる対処 コンパイラによる対処 サマリ 17

Slide 19

Slide 19 text

デモ Copyright 2018 FUJITSU LIMITED 18 メモリアロケーション量とGC頻度

Slide 20

Slide 20 text

Escape Analysis (EA) Copyright 2018 FUJITSU LIMITED https://docs.oracle.com/javase/8/docs/technotes/guides/vm/performance- enhancements-7.html JDK 6 (HotSpot C2) から採用 JITによる最適化 Scalar Replacement Stack Allocation Lock Elision 19

Slide 21

Slide 21 text

Escapeとは Copyright 2018 FUJITSU LIMITED メソッドからの脱出 オブジェクトがアロケートされたメソッドの外で 使用されているかもしれない オブジェクトはメソッドローカルでない スレッドからの脱出 オブジェクトがアロケートされたスレッドの外で 使用されているかもしれない 他のスレッドがそのオブジェクトにアクセスするかもしれない 20

Slide 22

Slide 22 text

Escapeの種類 Copyright 2018 FUJITSU LIMITED オブジェクトはグローバルに脱出する オブジェクトは作成したメソッドを脱出しない オブジェクトは引数経由でメソッドを脱出するが、 スレッドは脱出しない NoEscape ArgEscape GlobalEscape 21

Slide 23

Slide 23 text

Escapeの例 Copyright 2018 FUJITSU LIMITED int foo(String name) { Person person = new Person(name); return person.id(); } void foo(String name) { Person person = new Person(name); register(person); } NoEscape ArgEscape 22

Slide 24

Slide 24 text

Escapeの例 Copyright 2018 FUJITSU LIMITED class bar { Person person; void foo(String name) { person = new Person(name); } } GlobalEscape 23

Slide 25

Slide 25 text

最適化の組み合わせ Copyright 2018 FUJITSU LIMITED Scalar Replacement Stack Allocation Lock Elision No Escape 〇 〇 〇 Arg Escape - - 〇 Global Escape - - - 24

Slide 26

Slide 26 text

Stack Allocation Copyright 2018 FUJITSU LIMITED オブジェクトをヒープではなくスタックにアロケートする メソッド終了と同時にオブジェクトは解放 HotSpotでは不採用 25

Slide 27

Slide 27 text

Stack Allocation Copyright 2018 FUJITSU LIMITED 32 山田 太郎 SP メソッド 開始時 new Person() 実行後 メソッド 終了時 残骸 SP SP 26 void foo { Person person = new Person(32, “山田太郎”); ・・・ スタック

Slide 28

Slide 28 text

Scalar Replacement Copyright 2018 FUJITSU LIMITED オブジェクトフィールドへのアクセスを、 スタックまたはレジスターアクセスにする Stack Allocationとは異なり、 オブジェクトヘッダー等はアロケートされない 27

Slide 29

Slide 29 text

Scalar Replacement 例 Copyright 2018 FUJITSU LIMITED int foo(String name, int age) { Person person = new Person(name, age); return person.getAge(); } class Person { String name; int age; Person(String name, int age) { this.name = name; this.age = age; } } 28

Slide 30

Slide 30 text

デモ Copyright 2018 FUJITSU LIMITED 29 Scalar Replacement

Slide 31

Slide 31 text

Lock Elision Copyright 2018 FUJITSU LIMITED スレッドローカルなオブジェクトに対するロックを削除 30 void foo() { Object lock = new Ojbect(); synchronized (lock) { doSomething }; }

Slide 32

Slide 32 text

アジェンダ Copyright 2018 FUJITSU LIMITED GC問題 アプリケーションによる対処 コンパイラによる対処 サマリ 31

Slide 33

Slide 33 text

サマリ Copyright 2018 FUJITSU LIMITED GCの問題と対処 JVMの種類やインライン状況によっては、 GCが発生したり、しなかったり 32 まずは、見やすいコードを GCは日々改善されている Javaのアロケーションコストは低い EAによるメモリ最適化もあり

Slide 34

Slide 34 text

Copyright 2018 FUJITSU LIMITED Q/A 33

Slide 35

Slide 35 text

No content