SlideShare a Scribd company logo
1 of 46
Download to read offline
Deep Dive into
instanceof
2018-12-15
JJUG CCC 2018 Fall
In od on
Hiroshi Saito @saidie
➔ SmartNews 1.5yrs
広告配信プラットフォーム (Java)
➔ DeNA 3yrs
Web サーバサイド (Perl, Ruby on Rails)
➔ Ph.D Student 5yrs
理論神経科学
Java 初心者!!
Sma w
世界中の良質な情報を必要な人に送り届ける /
Delivering the world’s quality information to the
people who need it
SmartNews Ads
”Ads as Content”
In od on
Performance is important
● 大量の広告リクエスト、ビーコン
● ハイパフォーマンスを求められる配信システム
In od on
Java 初心者が通る道(?)
instanceof を使ってレビューで指摘される
OOP 的に良くないだけでなくパフォーマンス的にも
良くない
In od on
Why?
一見難しそうに見えるが Set などを使えばいいのでは?
E
N
R
S
M
T
W
A
Z
Research
Res h
Java コンパイラによる変換
.java .class JVM
javac execute
Res h
classの中身
ConstantPool Field Attribute
+
Res h
JVMはスタックマシン
● 命令の引数はスタックに積んである
● 結果はスタックに入る
“Hello,
world!”
Stack
instanceof String
1
Stack
コンパイル時に決まっている
ConstantPoolから表引き
pop push
Res h
classの中身 (再掲)
1. ldc: stack に “Hello, world!” を push
2. instanceof を実行
3. jump (空の if 文)
4. return
Res h
JVM
● Oracle HotSpot JVM
● Eclipse OpenJ9
今日見ていくのは HotSpot JVM
バージョン: jdk-11.0.1+13
Res h
ソースコード
hg clone https://hg.openjdk.java.net/jdk-updates/jdk11u
Res h
interpreter を探せ
share/interpreter
● TemplateInterpreter: CPU依存
○ 普段使われてるもの
● CppInterpreter: CPU非依存
○ 今日は主にこっちの話
JVM internals
share/oops/ にある C++ の class
● Klass ⇐ Java のクラス/interface
○ ex) Object クラスの Klass, Integer クラスの Klass
● ConstantPool
○ ある Klass から参照される定数のルックアップテーブル
○ Klass*の配列を持っている
Div I J
基本的なデータ構造
Div I J
バイトコードインタプリタ概要
1. pc の位置にある命令を読む
2. バイトコードに応じて処理を行う
○ 巨大な switch 文
3. pc を更新する
4. 1 に戻る
(実際にはスレッデッドコード)
概念図
pc next pc
bytecode
Div I J
BytecodeInterpreter::runWithCheck:L2266
Div I J
instanceof の処理
oop*
“Hello,world!”
Stack
SP
pc
bytecode 0xc1 index
ConstantPool
Klass*
String
Klass*が得られる
Div I J
ConstantPoolのindex
ConstantPoolからKlass*
StackからKlass*
subtype check
Div I J
Klass::is_subtype_of(Klass*)
Div I J
Fast and Decisive Class Checking in the Hotspot VM
John Rose & Cliff Click, 2001
以下のような思想の下で考案された
● CPU のオペレーションを少なくしたい
● Memory access を少なくしたい
● VM call をなくしたい
Klass.hpp にあるとあるコメント
Div I J
subtype check 継承の場合
単純にsuper classを一つ一つチェックする場合
深さに応じた時間がかかる
Div I J
継承ツリー
Object
Number
ArrayList
Integer AbstractList
AbstractCollection
0
2
1
3
Double AbstractSet
HashSet
Div I J
primary supers では super depth が重複しない
Primary supers: super class のリスト
● Integer: [Object, Number]
● ArrayList: [Object, AbstractCollection, AbstractList]
Super depth: 継承の深さ
● Object: 0
● Number: 1
● AbstractCollection: 1
● AbstractList: 2
super depth の位置を調べるだけで良い
Div I J
interfaceは二部グラフ
Collection
Serializable
ArrayList
Integer
AbstractList Iterable
AbstractSet
HashSet
多対多なので難しい
List
Set
Div I J
Binary matrix
Klass に連番をつけて binary matrix を作る
クラスの動的load/unloadへの対応が難しい
Serializable Collection Iterable List Set
Integer o
AbstractSet o o o o
AbstractList o o o o
HashSet o o o o
ArrayList o o o o
Div I J
線形探索 + Cache
● 数がそんなに多くなければそれほど遅くない
● 前回のinstanceofで参照されたクラスをキャッシュし
ておき、次回は最初にキャッシュをチェックする
CollectionSerializable Iterable ListCloneable RandomAccess
ArrayList の secondary supers
Div I J
ここまでのまとめ
● クラスに対する is_subtype_of
○ 継承ツリーにおける深さで一発で求められる
● interfaceに対する is_subtype_of
○ 前回ヒットしたクラスをチェックする
○ チェックが失敗したら線形探索
Div I J
Div I J
primary_supersをKlassに含める
primary_supers を固定長にするとKlass自体に埋
め込めて、メモリアクセスが減らせる
現状の実装だと supers の長さは 8
▷super depth < 8までしか扱えない
より深いものは?
▷interfaceと同じ扱いにする == 線形探索対象
Div I J
● super_depthはクラスロード時に確定する
● どちらの条件を使うかも確定する
範囲チェックと T との比較を一括で実現できる
load時に決まる
Div I J
Klassのメモリレイアウト
0 1 2 3 4 5 6 7 8 9 A B C D E F
Layout helper Klass ID
Super Check
Offset
Symbol*
name
Array<Klass*>*
Secondary Supers
Klass*
Secondary Super
Cache
Klass*
Primary Supers[0]
super depth < 88 <= super depth
Klass*
Primary Supers[1]
Klass*
Primary Supers[6]
Klass*
Primary Supers[7]
参照すべきメモリ位置が事前に分かる!
Div I J
Klass::is_subtype_of(Klass*)
primary supers / キャッシュの位置
primary super / キャッシュ
== primary super / キャッシュ
super depth < 8 の場合
線形探索
Div I J
x86の場合
cpu/x86/macroAssembler_x86.cpp: check_klass_subtype 関数
MOV: メモリ → レジスタ
CMP: レジスタ⇔メモリ
CMP: レジスタ⇔即値
MOV: Arrayの位置や長さ
REPNE: 線形探索
Div I J
Experiments
C_10 → C_09 → … → C_02 → C_01 → Object
fast slow
Div I J
Results
JIT をオフにして JMH で計測した結果
Summary
Sum y
instanceof 実装まとめ
● 継承ツリー深さが8未満の具象クラス
○ 数回のCPUオペレーションとメモリアクセス
● 深さが8以上 or interface
○ 前回のinstanceofと同じであればキャッシュが効いて高速
○ キャッシュミスしたら線形探索
■ 効率的なCPU命令がある
Sum y
Conclusion
継承が深いクラスやinterfaceを使ったinstanceofを使う場
合はできるだけキャッシュを効かせよう
instanceof を使わなくて済むようきちんと設計しよう
JVM のコード読むの結構楽しいよ
We want more!!
https://smartnews.workable.com/

More Related Content

What's hot

Java EE パフォーマンスTips #glassfish_jp
Java EE パフォーマンスTips #glassfish_jpJava EE パフォーマンスTips #glassfish_jp
Java EE パフォーマンスTips #glassfish_jpNorito Agetsuma
 
Spring3.1概要 データアクセスとトランザクション処理
Spring3.1概要 データアクセスとトランザクション処理Spring3.1概要 データアクセスとトランザクション処理
Spring3.1概要 データアクセスとトランザクション処理土岐 孝平
 
Java SE 9の紹介: モジュール・システムを中心に
Java SE 9の紹介: モジュール・システムを中心にJava SE 9の紹介: モジュール・システムを中心に
Java SE 9の紹介: モジュール・システムを中心にTaku Miyakawa
 
Java9新機能概要
Java9新機能概要Java9新機能概要
Java9新機能概要HonMarkHunt
 
Javaはどのように動くのか~スライドでわかるJVMの仕組み
Javaはどのように動くのか~スライドでわかるJVMの仕組みJavaはどのように動くのか~スライドでわかるJVMの仕組み
Javaはどのように動くのか~スライドでわかるJVMの仕組みChihiro Ito
 
Javaチョットデキルへの道〜JavaコアSDKに見る真似したいコード10選〜
Javaチョットデキルへの道〜JavaコアSDKに見る真似したいコード10選〜Javaチョットデキルへの道〜JavaコアSDKに見る真似したいコード10選〜
Javaチョットデキルへの道〜JavaコアSDKに見る真似したいコード10選〜JustSystems Corporation
 
Introduction to JShell #JavaDayTokyo #jdt_jshell
Introduction to JShell #JavaDayTokyo #jdt_jshellIntroduction to JShell #JavaDayTokyo #jdt_jshell
Introduction to JShell #JavaDayTokyo #jdt_jshellbitter_fox
 
Getting Started GraalVM / GraalVM超入門 #jjug_ccc #ccc_c2
Getting Started GraalVM / GraalVM超入門 #jjug_ccc #ccc_c2Getting Started GraalVM / GraalVM超入門 #jjug_ccc #ccc_c2
Getting Started GraalVM / GraalVM超入門 #jjug_ccc #ccc_c2tamtam180
 
Advanced database monitoring in modern java
Advanced database monitoring in modern javaAdvanced database monitoring in modern java
Advanced database monitoring in modern javaChihiro Ito
 
Head toward Java 16 (Night Seminar Edition)
Head toward Java 16 (Night Seminar Edition)Head toward Java 16 (Night Seminar Edition)
Head toward Java 16 (Night Seminar Edition)Yuji Kubota
 
Prepare for Java 9 #jjug
Prepare for Java 9 #jjugPrepare for Java 9 #jjug
Prepare for Java 9 #jjugYuji Kubota
 
ClassLoader Leak Patterns
ClassLoader Leak PatternsClassLoader Leak Patterns
ClassLoader Leak Patternsnekop
 
20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側
20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側
20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側賢 秋穂
 
クラスローダーについて
クラスローダーについてクラスローダーについて
クラスローダーについてSuguru ARAKAWA
 
Java Batch 仕様 (Public Review時点)
Java Batch 仕様 (Public Review時点) Java Batch 仕様 (Public Review時点)
Java Batch 仕様 (Public Review時点) Norito Agetsuma
 
Javaの進化にともなう運用性の向上はシステム設計にどういう変化をもたらすのか
Javaの進化にともなう運用性の向上はシステム設計にどういう変化をもたらすのかJavaの進化にともなう運用性の向上はシステム設計にどういう変化をもたらすのか
Javaの進化にともなう運用性の向上はシステム設計にどういう変化をもたらすのかYoshitaka Kawashima
 
Sbtのマルチプロジェクトはいいぞ
SbtのマルチプロジェクトはいいぞSbtのマルチプロジェクトはいいぞ
SbtのマルチプロジェクトはいいぞYoshitaka Fujii
 
HeapStats @ Seasar Conference 2015 LT
HeapStats @ Seasar Conference 2015 LTHeapStats @ Seasar Conference 2015 LT
HeapStats @ Seasar Conference 2015 LTYuji Kubota
 

What's hot (20)

Java EE パフォーマンスTips #glassfish_jp
Java EE パフォーマンスTips #glassfish_jpJava EE パフォーマンスTips #glassfish_jp
Java EE パフォーマンスTips #glassfish_jp
 
Spring3.1概要 データアクセスとトランザクション処理
Spring3.1概要 データアクセスとトランザクション処理Spring3.1概要 データアクセスとトランザクション処理
Spring3.1概要 データアクセスとトランザクション処理
 
Java SE 9の紹介: モジュール・システムを中心に
Java SE 9の紹介: モジュール・システムを中心にJava SE 9の紹介: モジュール・システムを中心に
Java SE 9の紹介: モジュール・システムを中心に
 
Java9新機能概要
Java9新機能概要Java9新機能概要
Java9新機能概要
 
Javaはどのように動くのか~スライドでわかるJVMの仕組み
Javaはどのように動くのか~スライドでわかるJVMの仕組みJavaはどのように動くのか~スライドでわかるJVMの仕組み
Javaはどのように動くのか~スライドでわかるJVMの仕組み
 
Javaチョットデキルへの道〜JavaコアSDKに見る真似したいコード10選〜
Javaチョットデキルへの道〜JavaコアSDKに見る真似したいコード10選〜Javaチョットデキルへの道〜JavaコアSDKに見る真似したいコード10選〜
Javaチョットデキルへの道〜JavaコアSDKに見る真似したいコード10選〜
 
Introduction to JShell #JavaDayTokyo #jdt_jshell
Introduction to JShell #JavaDayTokyo #jdt_jshellIntroduction to JShell #JavaDayTokyo #jdt_jshell
Introduction to JShell #JavaDayTokyo #jdt_jshell
 
Getting Started GraalVM / GraalVM超入門 #jjug_ccc #ccc_c2
Getting Started GraalVM / GraalVM超入門 #jjug_ccc #ccc_c2Getting Started GraalVM / GraalVM超入門 #jjug_ccc #ccc_c2
Getting Started GraalVM / GraalVM超入門 #jjug_ccc #ccc_c2
 
Advanced database monitoring in modern java
Advanced database monitoring in modern javaAdvanced database monitoring in modern java
Advanced database monitoring in modern java
 
Head toward Java 16 (Night Seminar Edition)
Head toward Java 16 (Night Seminar Edition)Head toward Java 16 (Night Seminar Edition)
Head toward Java 16 (Night Seminar Edition)
 
Prepare for Java 9 #jjug
Prepare for Java 9 #jjugPrepare for Java 9 #jjug
Prepare for Java 9 #jjug
 
ClassLoader Leak Patterns
ClassLoader Leak PatternsClassLoader Leak Patterns
ClassLoader Leak Patterns
 
20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側
20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側
20160521 大規模映像配信サービスの Java8による全面リニューアルの裏側
 
クラスローダーについて
クラスローダーについてクラスローダーについて
クラスローダーについて
 
キメるClojure
キメるClojureキメるClojure
キメるClojure
 
Spring AMQP × RabbitMQ
Spring AMQP × RabbitMQSpring AMQP × RabbitMQ
Spring AMQP × RabbitMQ
 
Java Batch 仕様 (Public Review時点)
Java Batch 仕様 (Public Review時点) Java Batch 仕様 (Public Review時点)
Java Batch 仕様 (Public Review時点)
 
Javaの進化にともなう運用性の向上はシステム設計にどういう変化をもたらすのか
Javaの進化にともなう運用性の向上はシステム設計にどういう変化をもたらすのかJavaの進化にともなう運用性の向上はシステム設計にどういう変化をもたらすのか
Javaの進化にともなう運用性の向上はシステム設計にどういう変化をもたらすのか
 
Sbtのマルチプロジェクトはいいぞ
SbtのマルチプロジェクトはいいぞSbtのマルチプロジェクトはいいぞ
Sbtのマルチプロジェクトはいいぞ
 
HeapStats @ Seasar Conference 2015 LT
HeapStats @ Seasar Conference 2015 LTHeapStats @ Seasar Conference 2015 LT
HeapStats @ Seasar Conference 2015 LT
 

Similar to Deep dive into instanceof

Shibuya.lisp #28: 仮題: R について
Shibuya.lisp #28: 仮題: R についてShibuya.lisp #28: 仮題: R について
Shibuya.lisp #28: 仮題: R についてtnoda
 
Ruby Extended Library
Ruby Extended LibraryRuby Extended Library
Ruby Extended LibraryAkio Tajima
 
Scalaで萌える関数型プログラミング[完全版]
Scalaで萌える関数型プログラミング[完全版]Scalaで萌える関数型プログラミング[完全版]
Scalaで萌える関数型プログラミング[完全版]Ra Zon
 
Scalaで萌える関数型プログラミング[1.1.RC1]
Scalaで萌える関数型プログラミング[1.1.RC1]Scalaで萌える関数型プログラミング[1.1.RC1]
Scalaで萌える関数型プログラミング[1.1.RC1]Ra Zon
 
あなたが知らない リレーショナルモデル
あなたが知らない リレーショナルモデルあなたが知らない リレーショナルモデル
あなたが知らない リレーショナルモデルMikiya Okuno
 
ステップ・バイ・ステップで学ぶラムダ式・Stream api入門 #jjug ccc #ccc h2
ステップ・バイ・ステップで学ぶラムダ式・Stream api入門 #jjug ccc #ccc h2ステップ・バイ・ステップで学ぶラムダ式・Stream api入門 #jjug ccc #ccc h2
ステップ・バイ・ステップで学ぶラムダ式・Stream api入門 #jjug ccc #ccc h2Masatoshi Tada
 
モジュールの凝集度・結合度・インタフェース
モジュールの凝集度・結合度・インタフェースモジュールの凝集度・結合度・インタフェース
モジュールの凝集度・結合度・インタフェースHajime Yanagawa
 
⑯jQueryをおぼえよう!その2
⑯jQueryをおぼえよう!その2⑯jQueryをおぼえよう!その2
⑯jQueryをおぼえよう!その2Nishida Kansuke
 
知って得するWebで便利なpostgre sqlの3つの機能
知って得するWebで便利なpostgre sqlの3つの機能知って得するWebで便利なpostgre sqlの3つの機能
知って得するWebで便利なpostgre sqlの3つの機能Soudai Sone
 
20120317 IT系勉強会 in 神戸
20120317 IT系勉強会 in 神戸20120317 IT系勉強会 in 神戸
20120317 IT系勉強会 in 神戸Takahiro Iwase
 
JSX 速さの秘密 - 高速なJavaScriptを書く方法
JSX 速さの秘密 - 高速なJavaScriptを書く方法JSX 速さの秘密 - 高速なJavaScriptを書く方法
JSX 速さの秘密 - 高速なJavaScriptを書く方法Kazuho Oku
 
そしてjsの基礎へ戻る#4
そしてjsの基礎へ戻る#4そしてjsの基礎へ戻る#4
そしてjsの基礎へ戻る#4Shingo Inoue
 
Inside frogc in Dart
Inside frogc in DartInside frogc in Dart
Inside frogc in DartGoro Fuji
 

Similar to Deep dive into instanceof (20)

ATN No.2 Scala事始め
ATN No.2 Scala事始めATN No.2 Scala事始め
ATN No.2 Scala事始め
 
Shibuya.lisp #28: 仮題: R について
Shibuya.lisp #28: 仮題: R についてShibuya.lisp #28: 仮題: R について
Shibuya.lisp #28: 仮題: R について
 
Ruby Extended Library
Ruby Extended LibraryRuby Extended Library
Ruby Extended Library
 
Scalaで萌える関数型プログラミング[完全版]
Scalaで萌える関数型プログラミング[完全版]Scalaで萌える関数型プログラミング[完全版]
Scalaで萌える関数型プログラミング[完全版]
 
Scalaで萌える関数型プログラミング[1.1.RC1]
Scalaで萌える関数型プログラミング[1.1.RC1]Scalaで萌える関数型プログラミング[1.1.RC1]
Scalaで萌える関数型プログラミング[1.1.RC1]
 
あなたが知らない リレーショナルモデル
あなたが知らない リレーショナルモデルあなたが知らない リレーショナルモデル
あなたが知らない リレーショナルモデル
 
ステップ・バイ・ステップで学ぶラムダ式・Stream api入門 #jjug ccc #ccc h2
ステップ・バイ・ステップで学ぶラムダ式・Stream api入門 #jjug ccc #ccc h2ステップ・バイ・ステップで学ぶラムダ式・Stream api入門 #jjug ccc #ccc h2
ステップ・バイ・ステップで学ぶラムダ式・Stream api入門 #jjug ccc #ccc h2
 
モジュールの凝集度・結合度・インタフェース
モジュールの凝集度・結合度・インタフェースモジュールの凝集度・結合度・インタフェース
モジュールの凝集度・結合度・インタフェース
 
⑯jQueryをおぼえよう!その2
⑯jQueryをおぼえよう!その2⑯jQueryをおぼえよう!その2
⑯jQueryをおぼえよう!その2
 
知って得するWebで便利なpostgre sqlの3つの機能
知って得するWebで便利なpostgre sqlの3つの機能知って得するWebで便利なpostgre sqlの3つの機能
知って得するWebで便利なpostgre sqlの3つの機能
 
Introduction of Python
Introduction of PythonIntroduction of Python
Introduction of Python
 
Groovyコンファレンス
GroovyコンファレンスGroovyコンファレンス
Groovyコンファレンス
 
20120317 IT系勉強会 in 神戸
20120317 IT系勉強会 in 神戸20120317 IT系勉強会 in 神戸
20120317 IT系勉強会 in 神戸
 
Clojure
ClojureClojure
Clojure
 
JSX 速さの秘密 - 高速なJavaScriptを書く方法
JSX 速さの秘密 - 高速なJavaScriptを書く方法JSX 速さの秘密 - 高速なJavaScriptを書く方法
JSX 速さの秘密 - 高速なJavaScriptを書く方法
 
つぶLT20121215
つぶLT20121215つぶLT20121215
つぶLT20121215
 
Vespa 機能紹介 #yjmu
Vespa 機能紹介 #yjmuVespa 機能紹介 #yjmu
Vespa 機能紹介 #yjmu
 
Tokyo r50 beginner_2
Tokyo r50 beginner_2Tokyo r50 beginner_2
Tokyo r50 beginner_2
 
そしてjsの基礎へ戻る#4
そしてjsの基礎へ戻る#4そしてjsの基礎へ戻る#4
そしてjsの基礎へ戻る#4
 
Inside frogc in Dart
Inside frogc in DartInside frogc in Dart
Inside frogc in Dart
 

Deep dive into instanceof