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
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
Kenshi Kamata
February 20, 2018
Programming
1.4k
2
Share
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
2.9k
チャネルの仕組み
knsh14
6
5.5k
Go でインタプリタを 書いてみよう
knsh14
0
3k
Let’s Create An Interpreter In Go
knsh14
0
150
Go Code Review Comment を翻訳した話
knsh14
0
7.6k
tvOS Leaderboard
knsh14
0
1.2k
Other Decks in Programming
See All in Programming
最初からAWS CDKで技術検証してもいいんじゃない?
akihisaikeda
4
180
CS教育のDX AIによる育成の効率化
niftycorp
PRO
0
180
一度始めたらやめられない開発効率向上術 / Findy あなたのdotfilesを教えて!
k0kubun
3
2.7k
L’IA au service des devs : Anatomie d'un assistant de Code Review
toham
0
180
The Past, Present, and Future of Enterprise Java
ivargrimstad
0
1.3k
Goの型安全性で実現する複数プロダクトの権限管理
ishikawa_pro
2
1.4k
Claude Code Skill入門
mayahoney
0
460
野球解説AI Agentを開発してみた - 2026/02/27 LayerX社内LT会資料
shinyorke
PRO
0
390
見せてもらおうか、 OpenSearchの性能とやらを!
shunta27
1
170
[PHPerKaigi 2026]PHPerKaigi2025の企画CodeGolfが最高すぎて社内で内製して半年運営して得た内製と運営の知見
ikezoemakoto
0
320
OTP を自動で入力する裏技
megabitsenmzq
0
130
生成 AI 時代のスナップショットテストってやつを見せてあげますよ(α版)
ojun9
0
330
Featured
See All Featured
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
PRO
199
73k
Leadership Guide Workshop - DevTernity 2021
reverentgeek
1
260
The innovator’s Mindset - Leading Through an Era of Exponential Change - McGill University 2025
jdejongh
PRO
1
140
The Pragmatic Product Professional
lauravandoore
37
7.2k
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.7k
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
55
3.3k
Making Projects Easy
brettharned
120
6.6k
So, you think you're a good person
axbom
PRO
2
2k
End of SEO as We Know It (SMX Advanced Version)
ipullrank
3
4.1k
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
11
880
Game over? The fight for quality and originality in the time of robots
wayneb77
1
150
Designing Experiences People Love
moore
143
24k
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言語のメモリ管理 を 参考にしました