Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Speaker Deck
PRO
Sign in
Sign up for free
静的クラスは遅いことがあるよ
Kazuhiro Fujieda
July 29, 2020
Technology
3
1.6k
静的クラスは遅いことがあるよ
Kazuhiro Fujieda
July 29, 2020
Tweet
Share
More Decks by Kazuhiro Fujieda
See All by Kazuhiro Fujieda
NaN BoxingによるJSONパーサーの高速化
kfujieda
2
630
ftp.jaist.ac.jpの低レイヤーの話
kfujieda
0
45
Other Decks in Technology
See All in Technology
PUTとPOSTどっち使う?
hankehly
0
160
2022年度新卒技術研修「良いコードの書き方」講義
excitejp
PRO
0
230
セキュリティ 開運研修2022 / security 2022
cybozuinsideout
PRO
2
3k
DAO (分散型自律組織) vs. 自律分散組織 / DAO vs. Distributed Autonomous Organization
ks91
PRO
0
220
Internet Explorer は Microsoft Edge へ - IE の歩みとこれから -
yuhara0928
1
3.4k
HoloLens2とMetaQuest2どちらも動くWebXRアプリをBabylon.jsで作る
iwaken71
0
150
サイボウズの アジャイル・クオリティ / Agile Quality at Cybozu
cybozuinsideout
PRO
4
1.7k
1人目QA奮闘記/QA Engineer's Struggle
mii3king
2
1k
suppress-ts-errors を使って TypeScriptの型チェックを漸進的に強化する / Introducing-suppress-ts-errors
kawamataryo
2
110
2022年度新卒技術研修「DNS」講義
excitejp
PRO
0
330
データチームの境界を考える
yummydum
0
170
Modern Android dependency injection
hugovisser
1
110
Featured
See All Featured
VelocityConf: Rendering Performance Case Studies
addyosmani
316
22k
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
7
1.1k
From Idea to $5000 a Month in 5 Months
shpigford
373
44k
Atom: Resistance is Futile
akmur
255
20k
Product Roadmaps are Hard
iamctodd
34
6.5k
KATA
mclloyd
7
8.7k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
10
3.3k
In The Pink: A Labor of Love
frogandcode
131
21k
Statistics for Hackers
jakevdp
781
210k
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
237
19k
Making Projects Easy
brettharned
98
4.3k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
236
1M
Transcript
静的クラスは遅いことが あるよ 藤枝 和宏 twitter: kfujieda fujieda@roundwide.com
DynaJson • https://github.com/fujieda/DynaJson/ • 高速なJSONパーザー • DynamicJson互換 dynamic json =
JsonObject.Parse(@"{ ""foo"": ""json"", ""nest"": {""foobar"": true} }"); string a1 = json.foo; // "json" bool a2 = json.nest.foobar; // true
速い citm_catalog.json (1.7MB)をパーズ .NET Core 3.1 Ubuntu 18.04 on Azure
D2ds_v4 0 5 10 15 20 25 30 35 40 DynaJson Utf8Json Jil Newtonsoft.Json DynamicJson Time (ms) ←lower is better
静的クラスを避ける public class JsonParser { private static readonly JsonParser Instance
= new JsonParser(); // インスタンスは一つ public static object Parse(TextReader reader, int maxDepth) { return Instance.ParseInternal(reader, maxDepth); // インスタンスメソッドを呼ぶ } private object ParseInternal(TextReader reader, int maxDepth) { // パーザーの本体 } }
静的クラスは遅い なぜか遅い 0 2 4 6 8 10 12 14
Static Normal Time (ms) ←lower is better .NET Core 3.1 Ubuntu 18.04 on Azure D2ds_v4
ディスアセンブルしてみる .NET Core 3.1.6 (CoreCLR 4.700.20.26901, CoreFX 4.700.20.31603), X64 RyuJIT
JsonParser.ParseJsonInternal() ... mov r9d,[rbp+24] inc r9d mov [rbp+24],r9d inc dword ptr [rbp+28] cmp [rbp+20],r9d jne short M04_L01 ... Total bytes of code 7845 JsonParseStatic.Parse() ... mov r9d,[7FFE540EB864] inc r9d mov [7FFE540EB864],r9d inc dword ptr [7FFE540EB868] cmp [7FFE540EB860],r9d jne short M02_L01 ... Total bytes of code 9701
中身の大きなループは遅い • DynaJsonのJsonParserは大きなループ • 中身が全部L1キャッシュに乗らないと遅い 1 2 3 4 5
6 7 8 プログラム L1キャッシュ 1 2 3 4 5 6 7 8 9 9
なぜコードが大きいのか インライン展開の多用 case 'n': CheckToken("ull"); value.Type = JsonType.Null; break; private
void CheckToken(string s) { Consume(); foreach (var ch in s) { if (ch != _nextChar) throw JsonParserException.ExpectingError($"'{ch}'", _position); Consume(); } } private void Consume() { _bufferIndex++; _position++; if (_available == _bufferIndex) { _bufferIndex = 0; _available = _reader.ReadBlock(_buffer, 0, _buffer.Length); if (_available == 0) { _isEnd = true; _nextChar = '¥0'; return; } } _nextChar = _buffer[_bufferIndex]; }
なぜコードが大きいのか インライン展開の多用 case 'n': CheckToken("ull"); value.Type = JsonType.Null; break; cmp
eax,6E ← 'n' jne near ptr M04_L104 mov r10d,[rbp+24] inc r10d mov [rbp+24],r10d inc dword ptr [rbp+28] cmp [rbp+20],r10d jne near ptr M04_L38 xor r9d,r9d mov [rbp+24],r9d mov rdx,[rbp+10] mov r9d,[rdx+8] mov rcx,[rbp+8] xor r8d,r8d mov rax,[rcx] mov rax,[rax+48] call qword ptr [rax+28] mov [rbp+20],eax cmp dword ptr [rbp+20],0 jne near ptr M04_L38 mov byte ptr [rbp+2E],1 mov word ptr [rbp+2C],0 M04_L08: mov r9,23E10009B48 mov rsi,[r9] xor edi,edi mov r12d,[rsi+8] test r12d,r12d jle short M04_L11 M04_L11: mov dword ptr [rsp+0B4],0FFF80001 jmp near ptr M04_L05 127 bytes
インライン展開をやめてみる • 差が縮まった • 静的クラスのキャッシュミスが減ったかな 0 2 4 6 8
10 12 14 16 Static (inlined) Normal (inlined) Static Normal Time (ms) ←lower is better
まとめ • 静的クラスはコードが大きくなることがある • 中身の大きすぎるループは遅くなることがある