歌った
歌い手なので歌った。喉のねじ切れる様をお楽しみいただけます。
権により消える可能性がある。
元ネタはScaleAbilityというGoogle社のアカペラグループが2014年秋のコンサートで歌った曲。
作った
これだけじゃアレなので、ついでにPythonの import this
(The Zen of Python)っぽいやつを作った。
インポートすると問答無用で歌詞が出る。
example/example.go
package main
import _ "github.com/drillbits/wig/this"
func main() {}
$ go run example/example.go
The schedule’s tight on the cluster tonight
So I parallelized my code
All those threads and continuations
My head’s going to explode
:
学び
最初はPythonのthis実装に倣ってROT13をルックアップテーブルで実装したのだけど、そもそもA Tour of GoにROT13を実装する演習がある。
それの解答例を見るとテーブルを作らずに1文字ずつ変換している。
毎回変換するよりテーブルから取るだけのが速いのでは?と思って両方実装して計測したら違った。
$ go test -bench
BenchmarkInterpreter 50000000 67.7 ns/op
BenchmarkLookup 500000 6303 ns/op
ルックアップめっちゃ遅い。
-benchmem
を使ったらメモリアロケートが発生してる分だけ遅いっぽい?
$ go test -bench . -benchmem
BenchmarkInterpreter 50000000 67.7 ns/op 0 B/op 0 allocs/op
BenchmarkLookup 500000 6303 ns/op 616 B/op 7 allocs/op
とりあえずマップ作るときにキャパシティのヒントがなかったので指定してみる(アルファベット26文字 * 2で固定になる)。
lookup.go
func NewLookupReader(r io.Reader) LookupReader {
- t := make(map[byte]byte)
+ t := make(map[byte]byte, 52)
BenchmarkInterpreter 50000000 66.0 ns/op 0 B/op 0 allocs/op
BenchmarkLookup 500000 3879 ns/op 359 B/op 3 allocs/op
これでallocs減って一応速くはなったけどやっぱりマップ作るより逐次変換のほうが速いっぽい。
変換対象の文字列が増えたらどこかで逆転するだろうと思って1300万文字まで増やしたけど全然追いつけなかった。
BenchmarkInterpreter 50000000 66.3 ns/op 0 B/op 0 allocs/op
BenchmarkInterpreterLongString 20000000 74.0 ns/op 2 B/op 0 allocs/op
BenchmarkLookup 500000 4147 ns/op 358 B/op 3 allocs/op
BenchmarkLookupLongString 200000 6647 ns/op 620 B/op 3 allocs/op
まあ go test -bench
は便利。
まとめ
Qiitaに歌ってみたタグができた。