Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Go1.10 strings.Builder の紹介
Search
Kenshi Kamata
February 20, 2018
Programming
1.4k
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Go1.10 strings.Builder の紹介
Go 1.10 Release Party in Tokyo の発表です
Kenshi Kamata
February 20, 2018
More Decks by Kenshi Kamata
See All by Kenshi Kamata
500万ユーザーを支える残高の冪等性 / The idempotency of the balance for 5 million Merpay users
knsh14
0
3k
チャネルの仕組み
knsh14
6
5.6k
Go でインタプリタを 書いてみよう
knsh14
0
3.1k
Let’s Create An Interpreter In Go
knsh14
0
160
Go Code Review Comment を翻訳した話
knsh14
0
7.7k
tvOS Leaderboard
knsh14
0
1.2k
Other Decks in Programming
See All in Programming
コンテキストの使い捨てをやめる — ビジネスルール駆動開発と miko —
ioki
0
200
Contextとはなにか
chiroruxx
1
320
気圧・高度・GPSを記録&可視化するアプリ「Koudo」を作った話
hjmkth
1
250
[2026年度第1回ORセミナー] 計画最適化ベンチャーと競技プログラミング人材
terryu16
0
260
Javaの型とAI時代に型が大事な理由 / java types and type in AI era
kishida
2
130
net-httpのHTTP/2対応について
naruse
0
480
LLMによるContent Moderationの本番運用の裏側と品質担保への挑戦
suikabar
2
650
Composerを使ったサプライチェーン攻撃の様子を眺めてみる #phpstudy
o0h
PRO
2
250
エージェンティックRAGにAWSで入門しよう!
har1101
8
1.5k
AI時代のUIはどこへ行く?その2!
yusukebe
21
7.2k
作って学ぶ、 JSX (TSX) ランタイムの基本
syumai
7
1.6k
TSKaigi Night Talks 2026_TypeScriptでサプライチェーンの整合性を型に閉じ込める
geekplus_tech
0
350
Featured
See All Featured
Collaborative Software Design: How to facilitate domain modelling decisions
baasie
1
250
Self-Hosted WebAssembly Runtime for Runtime-Neutral Checkpoint/Restore in Edge–Cloud Continuum
chikuwait
0
590
Embracing the Ebb and Flow
colly
88
5.1k
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
333
22k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
231
55k
svc-hook: hooking system calls on ARM64 by binary rewriting
retrage
2
300
Why You Should Never Use an ORM
jnunemaker
PRO
61
9.9k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
123
22k
Ruling the World: When Life Gets Gamed
codingconduct
0
250
Intergalactic Javascript Robots from Outer Space
tanoku
273
27k
Code Review Best Practice
trishagee
74
20k
Avoiding the “Bad Training, Faster” Trap in the Age of AI
tmiket
0
170
Transcript
strings.Builder の紹介 Golang 1.10 release party 鎌田 健史
自己紹介 • 鎌田 健史 • @knsh14 (twitter, GitHub) • KLab
株式会社 ◦ Unity のエディタ拡張書いたり ◦ JavaScript でゲーム書いたり • 技術書典ではバイトしてました
strings.Builder って何 ? • https://golang.org/pkg/strings/#Builder • 1.10 から入った新しいデータ型 • 文字列を構築するために使われる
strings.Builder の使い方 https://github.com/knsh14/monkey/blob/master/ast/ast.go#L182-L1 96 こういう箇所を string.Builder で置き換えたい
bytes.Buffer との比較 bytes.Buffer strings.Builder io.Writer を実装している ◯ ◯ io.Reader を実装している
◯ ✕ 初期値を与える NewXXX(s string) ◯ ✕
strings.Builder を作った理由 • Issue ◦ https://github.com/golang/go/issues/18990 ◦ https://go-review.googlesource.com/c/go/+/74931 • bytes.Buffer
に溜め込んだ文字列を string にする時に発生する余 計なアロケーションを回避したい
パフォーマンス見てみる https://gist.github.com/knsh14/fd4b0413a32b8b2ca544f2706d8557 d0 1. 100 回 WriteString してその結果を n 回取り出す
2. n 回 WriteString してその結果を String() で取り出す 3. 事前に n * 10 で容量を確保しておき、2と同じことをする 4. これを 10, 100, 1000, 10000, 100000 回で試す
1. については確かに早くなっている • 回数が多くなればなるほど差が開いていく • 10万回 String() すると 400倍近い差がでる •
Allocation は 100000 回呼ぶと 約 1/12500
なぜだろう? • bytes.Buffer の String → メモリコピーが走る ◦ String(b []byte)している
• strings.Builder の String → メモリコピーが走らない ◦ unsafe.Pointer からのキャスト • ちょうど修正したところが活かされている
もう一つのベンチマーク • n 回 WriteString して書き込んで一度だけ String() を読んで文字列 を取得すると若干遅くなる •
特に allocation とメモリのパフォーマンスが落ちる • 事前に Grow(n int) している場合には遅くならない ◦ Grow は Buffer の cap を増やす処理 • 実装を調べてみる
bytes.Buffer の WriteString • https://golang.org/src/bytes/buffer.go?s=6183:6240#L172 • cap にまだ書き込める余裕があるかチェック • 余裕がなければ
make で cap を増やす • 増えたら copy で書き込む
strings.Builder の WriteString • https://tip.golang.org/src/strings/builder.go?s=3201:3253#L105 • 自分自身がコピーされたものじゃないかチェック • append する
実装の比較 • bytes.Buffer の grow は cap を増やす時に もとの長さ *
2 + 増や す分 の長さを取っている ◦ https://golang.org/src/bytes/buffer.go?s=4258:4292#L144 • strings.Builder は append(d []byte, s string) • 繰り返しが小さいと差が出づらい ◦ 小さい要素だと append も倍増やす仕組みになっているらしい • この差で bytes.Buffer は少し make する回数が減っているのでは ないか?
どう使い分けるのがいいのか? • どれくらい buffer に書き込むか事前にわからない場合は bytes.Buffer のほうが少し有利 • String() を何回も呼ぶ必要がある場合には
strings.Builder のほう が圧倒的に有利 • 事前にどれくらい書き込むかわかっている場合には strings.Builder がおすすめ
更に細かい実装の話
コピーされたかどうか検知する • https://play.golang.org/p/nzYsBpxYZpc • struct をコピーすると、フィールドがポインタの場合はアドレスがコ ピーされる ◦ フィールドのアドレスが共有され、思わぬ副作用が •
これを回避したい ◦ 最初に書き込むときに自分自身のアドレスを持っておく ◦ B := A とコピーする ◦ B 自身のポインタとフィールドが持っているポインタが違うのでコ ピーされたことが検出できる
noescape を使ってパフォーマンス改善 • https://github.com/golang/go/issues/23382 • https://go-review.googlesource.com/c/go/+/86976 • コピーされてないかチェックするだけでメモリ確保が走ってしまうのを 防ぐ •
`//go:nosplit` がついてる関数ではスタックの操作はしない ◦ Goならわかるシステムプログラミング Go言語のメモリ管理 を 参考にしました