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
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
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
3k
チャネルの仕組み
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
実用!Hono RPC2026
yodaka
2
260
PHPer、Cloudflare に引っ越す
suguruooki
1
100
TiDBのアーキテクチャから学ぶ分散システム入門 〜MySQL互換のNewSQLは何を解決するのか〜 / tidb-architecture-study
dznbk
1
190
Kubernetes上でAgentを動かすための最新動向と押さえるべき概念まとめ
sotamaki0421
3
640
Cache-moi si tu peux : patterns et pièges du cache en production - Devoxx France 2026 - Conférence
slecache
0
290
Coding as Prompting Since 2025
ragingwind
0
840
ハーネスエンジニアリングとは?
kinopeee
13
6k
Claude Codeをカスタムして自分だけのClaude Codeを作ろう
terisuke
0
140
AIベース静的検査器の偽陽性率を抑える工夫3選
orgachem
PRO
3
350
JAWS-UG横浜 #100 祝・第100回スペシャルAWS は VPC レスの時代へ
maroon1st
0
170
Making the RBS Parser Faster
soutaro
0
500
의존성 주입과 모듈화
fornewid
0
150
Featured
See All Featured
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
46
2.8k
Learning to Love Humans: Emotional Interface Design
aarron
275
41k
SEO for Brand Visibility & Recognition
aleyda
0
4.5k
Building an army of robots
kneath
306
46k
The Illustrated Children's Guide to Kubernetes
chrisshort
51
52k
The Cost Of JavaScript in 2023
addyosmani
55
9.9k
Designing for humans not robots
tammielis
254
26k
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
49
9.9k
Bridging the Design Gap: How Collaborative Modelling removes blockers to flow between stakeholders and teams @FastFlow conf
baasie
0
520
My Coaching Mixtape
mlcsv
0
110
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
47
8.1k
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
12
1.1k
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言語のメモリ管理 を 参考にしました