strings.Builderとbytes.BufferのWrite系関数のベンチマーク

TL; DR 平均して見るとstrings.Builder#WriteXXXの方が速そう strings.Builder Go 1.10からstrings.Builder構造体が追加されました。 公式ドキュメントには、 A Builder is used to efficiently build a string using Write methods. It minimizes memory copying. The zero value is ready to use. Do not copy a non-zero Builder. と説明が書かれています。 おそらく、これまで文字列の組み立てをする際にはbytes.Bufferを使っている場合が多かったと思われますが、そういった目的の選択肢として作られたようです。 が、説明を読んでもいまいち違いがわかりません。 とりあえず、bytes.Bufferとstrings.Builderでは速度面で違いがあるのか調べるべく、ベンチマークを実施しました。 条件 実行した環境 MacBook Air MacOS Sierra 10.12.6 CPU: Core i7 1.7GHz メモリ: 8GB 実行する関数 Write WriteByte WriteRune WriteString exec 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 $ for i in {1..10}; do go test -bench . | tail -n +4 | head -n 8 && echo; done BenchmarkBuilderWrite-4 10000000 129 ns/op BenchmarkBuiderWriteByte-4 200000000 6.47 ns/op BenchmarkBuilderWriteRune-4 200000000 7.61 ns/op BenchmarkBuilderWriteString-4 30000000 92.4 ns/op BenchmarkBufferWrite-4 50000000 196 ns/op BenchmarkBufferWriteByte-4 300000000 9.40 ns/op BenchmarkBufferWriteRune-4 200000000 8.18 ns/op BenchmarkBufferWriteString-4 50000000 217 ns/op BenchmarkBuilderWrite-4 10000000 189 ns/op BenchmarkBuiderWriteByte-4 100000000 10.5 ns/op BenchmarkBuilderWriteRune-4 100000000 10.4 ns/op BenchmarkBuilderWriteString-4 30000000 157 ns/op BenchmarkBufferWrite-4 50000000 238 ns/op BenchmarkBufferWriteByte-4 100000000 19.9 ns/op BenchmarkBufferWriteRune-4 100000000 15.5 ns/op BenchmarkBufferWriteString-4 30000000 422 ns/op BenchmarkBuilderWrite-4 10000000 131 ns/op BenchmarkBuiderWriteByte-4 200000000 7.58 ns/op BenchmarkBuilderWriteRune-4 200000000 8.48 ns/op BenchmarkBuilderWriteString-4 30000000 113 ns/op BenchmarkBufferWrite-4 50000000 199 ns/op BenchmarkBufferWriteByte-4 100000000 10.4 ns/op BenchmarkBufferWriteRune-4 200000000 12.0 ns/op BenchmarkBufferWriteString-4 50000000 382 ns/op BenchmarkBuilderWrite-4 10000000 122 ns/op BenchmarkBuiderWriteByte-4 200000000 7.45 ns/op BenchmarkBuilderWriteRune-4 200000000 8.44 ns/op BenchmarkBuilderWriteString-4 30000000 155 ns/op BenchmarkBufferWrite-4 50000000 264 ns/op BenchmarkBufferWriteByte-4 200000000 7.08 ns/op BenchmarkBufferWriteRune-4 200000000 10.1 ns/op BenchmarkBufferWriteString-4 30000000 413 ns/op BenchmarkBuilderWrite-4 20000000 117 ns/op BenchmarkBuiderWriteByte-4 200000000 6.81 ns/op BenchmarkBuilderWriteRune-4 200000000 6.87 ns/op BenchmarkBuilderWriteString-4 50000000 219 ns/op BenchmarkBufferWrite-4 20000000 101 ns/op BenchmarkBufferWriteByte-4 200000000 6.22 ns/op BenchmarkBufferWriteRune-4 200000000 12.2 ns/op BenchmarkBufferWriteString-4 50000000 513 ns/op BenchmarkBuilderWrite-4 10000000 161 ns/op BenchmarkBuiderWriteByte-4 200000000 8.36 ns/op BenchmarkBuilderWriteRune-4 200000000 8.24 ns/op BenchmarkBuilderWriteString-4 30000000 109 ns/op BenchmarkBufferWrite-4 50000000 296 ns/op BenchmarkBufferWriteByte-4 100000000 10.6 ns/op BenchmarkBufferWriteRune-4 100000000 11.4 ns/op BenchmarkBufferWriteString-4 50000000 484 ns/op BenchmarkBuilderWrite-4 10000000 133 ns/op BenchmarkBuiderWriteByte-4 200000000 7.16 ns/op BenchmarkBuilderWriteRune-4 200000000 8.10 ns/op BenchmarkBuilderWriteString-4 30000000 194 ns/op BenchmarkBufferWrite-4 50000000 190 ns/op BenchmarkBufferWriteByte-4 200000000 5.51 ns/op BenchmarkBufferWriteRune-4 200000000 8.72 ns/op BenchmarkBufferWriteString-4 50000000 281 ns/op BenchmarkBuilderWrite-4 10000000 136 ns/op BenchmarkBuiderWriteByte-4 200000000 11.4 ns/op BenchmarkBuilderWriteRune-4 50000000 28.0 ns/op BenchmarkBuilderWriteString-4 10000000 119 ns/op BenchmarkBufferWrite-4 20000000 144 ns/op BenchmarkBufferWriteByte-4 100000000 16.0 ns/op BenchmarkBufferWriteRune-4 200000000 8.43 ns/op BenchmarkBufferWriteString-4 50000000 248 ns/op BenchmarkBuilderWrite-4 10000000 130 ns/op BenchmarkBuiderWriteByte-4 200000000 7.83 ns/op BenchmarkBuilderWriteRune-4 200000000 7.13 ns/op BenchmarkBuilderWriteString-4 30000000 99.0 ns/op BenchmarkBufferWrite-4 50000000 202 ns/op BenchmarkBufferWriteByte-4 200000000 10.7 ns/op BenchmarkBufferWriteRune-4 100000000 13.8 ns/op BenchmarkBufferWriteString-4 50000000 452 ns/op BenchmarkBuilderWrite-4 10000000 146 ns/op BenchmarkBuiderWriteByte-4 200000000 7.89 ns/op BenchmarkBuilderWriteRune-4 200000000 8.24 ns/op BenchmarkBuilderWriteString-4 30000000 122 ns/op BenchmarkBufferWrite-4 50000000 248 ns/op BenchmarkBufferWriteByte-4 100000000 31.7 ns/op BenchmarkBufferWriteRune-4 100000000 25.4 ns/op BenchmarkBufferWriteString-4 30000000 413 ns/op Source ベンチマークスクリプトのソースは以下の様になっています。 ...

2018-03-05 · nasa9084

Go言語で文字列を処理する

Go言語のregexpパッケージを使用した正規表現の処理は、一般的なスクリプト言語の処理速度と同程度で、正規表現を使用しない処理に比べてパフォーマンスがよくありません1。 そのため、可能であるならregexpパッケージを使用しないようにすべきです。 しかし、すべての処理を自分で書くのは大変です。 標準パッケージにも文字列を処理する関数が数多く用意されています。 strings パッケージ stringsパッケージはその名の通り、文字列を取り扱うパッケージです。 UTF-8でエンコードされた文字列(普通の文字列)をそのまま取り扱います。 判別系 Contains 1 func Contains(s, substr string) bool Contains関数は、sの中にsubstrが存在するかどうかを返します。 Pythonで言うところのsubstr in sに相当します。 正規表現ならば、substrとのmatchで真偽値をとることに相当します。 example 1 2 3 4 5 fmt.Println(strings.Contains("hogefugapiyo", "fuga")) // Output: true fmt.Println(strings.Contains("hogefugapiyo", "foo")) // Output: false ContainsAny 1 func ContainsAny(s, chars string) bool ContainsAny関数はsの中に、charsに含まれる文字のいずれかが存在するかどうかを返します。 つまり、charsは文字列ですが、扱いとしては文字の配列であると考えた方が良いでしょう。 正規表現で表すなら、/[${chars}]/の様な表現と考えられます(${chars}は置き換える)。 example 1 2 3 4 5 fmt.Println(strings.ContainsAny("hogefugapiyo", "abcd")) // Output: true fmt.Println(strings.ContainsAny("hogefugapiyo", "1234")) // Output: false HasPrefix 1 func HasPrefix(s, prefix string) bool HasPrefix関数は、sの頭がprefixと等しいかどうかを判別します。 正規表現で^を使った文字列マッチに相当します。 Prefixなのでマッチさせたい文字列をつい第一引数に与えたくなりますが、第二引数がPrefixです。 example 1 2 3 4 5 fmt.Println(strings.HasPrefix("hogefugapiyo", "hoge")) // Output: true fmt.Println(strings.HasPrefix("hogefugapiyo", "piyo")) // Output: false HasSuffix 1 func HasSuffix(s, suffix string) bool HasSuffix関数は、HasPrefix関数と対になる関数で、sの末尾がsuffixと等しいかどうかを判別します。 正規表現で$を使った文字列マッチに相当します。 ...

2018-03-05 · nasa9084