pandazx's blog

データ分析など雑多な技術ブログ

Go Conference 2014 Springに行ってきた

まずは主催者の方のまとめブログがあるので紹介。スライド資料のリンクもあります。
http://ymotongpoo.hatenablog.com/entry/2014/06/01/124350

さて、以下はカンファレンスのメモですが、メモ書きレベルなので、読んでも意味わからないところがあるかもしれません。ちゃんとした内容はスライド資料見てください。ここでは雰囲気を掴んでもらえればいいかなと。あと英語のセッションはちゃんとメモれてないかも。

感想としては、goroutine と channelを使うとハイパフォーマンスなプログラムが作れるという話が印象に残った。

Date: 2014/5/31
Place: Gran Tokyo South Tower 41F
Academy Hall of the Recruit Life Style Company

Go Tutorial

講師: tenntenn
if,for,map,sliceなどの基本的なお作法、
インタフェース、継承について学ぶ。

そこで作成したコード
https://github.com/pandazx/go_test

ここでやった内容とは違うけど、興味がある人は、A Tour of Goをやればいい。
http://go-tour-jp.appspot.com/#1

Keynote: Go: 90% Perfect, 100% of the time

Brad Fitzpatrick

script is eacy but slow for computer
C is fast but read difficult for human

language map
y: Fun vs. fast(perl, python, LL)
x: Computer(c)
Java is middle. But don't like it.
(middleはx,yの両方をいい感じに満たしているという意味。Bladがそう言ったわけではなく、自分のメモのために便宜上、使った言葉)
Go is middle, but it is easy more than Java
Speed is same as Java.

Perlythonubyscript
(各種スクリプト言語まとめた略記)

language map 2
y: Concurrency and performance
x: Beautiful, staraight code
Erlang is middle(Callback hellがないから?)
Go is middle and Concurrency higher than Erlang

Goが使われているシーン
Image processing

Crypto

  • pure Go AES, TLS(SSL), OpenPGP

replacing shell scripts

  • os/exec, goroutine

Camlistore

  • web handlers
  • web APIs
  • pure Go

Controlling flying drones

Mobile

  • Go runs on ARM
  • minux's iOS port of Go

Audio synthesis

Cloud Infrastructure

  • docker, packer
  • CoreOS's etcd and fleet

Load balancers & servers

Raspberry Pi GPIO

他にこれだけの場所すべてで使える言語があるか?

Go built-in tools

  • testing
  • benchmarking
  • profiling(CPU, memory, blocking)
  • race detector

Generics(cons)

Data races can happen

  • use channels
  • but documentation is cheap
  • be careful

Code generation

  • ARM上でコンパイルすると、たまにpretty dumb codeを作ることがある

gccgo

  • lacks escape analysis, パフォーマンス悪い
  • 32bit

Compiling to JavaScript isn't great yet

  • TADRIS Go Compiler

Limited Mobile Support

他の言語で呼び出すことが出来ない(no embed in other language environment)

no shared library

  • 対応優先度はlow priority

Garbage collector

  • Pauses:
  • Precision

Hot stack splits

  • 1.3でだいたい修正されたが、残りは1.4で

自分のプロジェクトにおいて、2012年頃からはほとんどGoだけを使っている

Session 1:社内システムをGoで書き直した話

App EngineアプリのPythonからGoへの移行
Rui Ueyama(Google Inc)

当初、話すつもりだったが、ボツネタになったGo標準ライブラリの話

  • 標準ライブラリのパッチを送った話
  • Google Docs(code?)にUPしてあり、読めるらしい

以下、本題。
2010年にPythonで作ったシステムを
2013年にGoで書き直した話

  • Google社内で最大の画像ホスティングサービス
  • 700万画像、1日4万アップロード
  • 当時はApp Engineなかった

App Engineのストレージ

  • Datastore(NoSQL)
  • Blobstore(binary database for big file)
  • Memcache

App Engineアプリのアップグレード方法

  • version X,Y
  • Xが稼働中にYをアップロード
  • テスト
  • GUIからYにスイッチするだけ
  • 新しいバージョンでデータモデルを変更する場合
    • 旧バージョンで存在しないデータがあるので、

その場合はデフォルトの処理を記述する必要がある

Go bindingではUserが定義されておらず、Pythonバージョンで
Userのメールアドレスを別フィールドにコピーする必要があった。
これを移行してから、新バージョンに移行。

HTTP Handlerで90秒の接続制限があったので、
1000件取得ずつ処理して、8時間かかった。
実はApp EngineはDatastoreに対してMapReduceが実行できたらしい。。。

全面的にリライトしているので、traffic splittingを活用。
App Engineでは複数のバージョンにトラフィックを分割できる。
10%->50%->100%と段階的に新バージョンへのトラフィックを増やして移行した。

ソースコード量はPythonからGoに移行して1.3倍?程度
増えたのはGoには閉じカッコがあるからと思われる。実質はほぼ変わらない。

移行メリット

  • CPU, memoryが減った
  • 静的な型付けによる安心感

Session 2: Five features that make Go fast

Dave Cheney
Go Community Management Leader in Sydney

Values

  • Goではint32を4byteで扱える
  • Pythonでは2014を24byte
  • Javaでは32bitで16byte, 64bitで24byte
  • データが小さいということはCPU cacheを効率よく使えて、パフォーマンスが向上する

Inlining

Escape analysis

Goroutines

  • process switching cost

Copying Stacks

  • hot splits

Session 3: Go in Production At Makerel.io

@stanaka(はてな)

Makerel

  • ServerにAgentを入れて、クラスタ環境のリソース使用量を可視化
  • Licence: APL2

why go

  • need to support various environmens -> cross compiler
  • easy setup -> one binary
  • works quietly as possible -> usage memory: 6MB

1分ごとに起動
goroutineで多重起動しないように制御
取得したメトリクス情報は文字列処理して、色々なフォーマットに対応
(一番大変だった)

multi architectures

  • build constrainsという仕組みがある
  • linux, windowsごとにswitchできる

packaging

  • dockerを使って、clean environmentでパッケージを作っている

agentのデーモン起動はnohupで

detect memory leak

  • net/http/??? を使っている

Pros

  • channel and goroutine is GREAT
  • Easy to support various architectures

Cons

  • String processing(parse)
    • Q&Aでそれほど大変ではないと思っている人もいた。慣れの問題か。
  • JSON parseも大変.静的言語の宿命だが

今後、色々使っていきたい

clash dumpの取得機能はまだない
メトリクスの収集失敗情報も取得できるようにしたい

Session 4: お仕事とgolang

非公開内容のため、省略

Session 5: 300万人をGoで捌いた話

@y_matsuwitter, Gunosy Inc.

ピークでのアクセスに対応できていない状況だった

System Architecuture
ELB
Nginx
Ruby on Rails
20-60req/sec

最初の改善後
ELB
Nginx
Rails | Sinatra
RDS | Redis
200req/sec

ここでTV CM開始

様々な技術を試行した

  • Haskell -> 扱いづらい。メンテナンス大変。技術者いないし
  • Node.js -> 高速。Goがなければ、これだった
  • OpenResty -> ルアーつらい。ルアー?

Go導入後
ELB
Nginx
Rails | Sinatra | Go
RDS | Redis
2000req/sec(m1.large)
サーバ周り:net/http + gorilla/mux
DB周り:sql + Gorp

以下、goroutineを活用して様々なサービスを作った話。ただ、スクラッチから必要最低限の機能だけを作ったっぽい。

Goroutine as Cache DB

  • Redis accessボトルネックだった
  • cache用のgoroutineを作って、DBからfetchさせておく
  • channelやshared memoryをcache DBとして使う
  • 結果
    • network越しから、同プロセス内になった
    • single core -> multi core
    • データ形式はGoオブジェクトそのまま. パース不要

Goroutine as Message Queue

  • どうしても直列化したい処理があった
  • 重いのでブロックしたくない
  • Pros
    • 導入コストが低い
    • パフォーマンス
  • Cons
    • Retry機構がない

ピーク負荷が異常に高いAPIに対してGoは非常に有効
GoroutineとChannelの組み合わせは有用

Q&A
プロセス再起動でキャッシュクリアされるが、それはどうしている?
今は起動後、数秒でロードできるので問題になっていない。

監視は?
httpを使って出来る

Session 6: Go駆動開発で超速Pushエンジンを作った話

@plan9user, フェンリル(受託開発部)

趣味はPlan 9. Plan 9って何?

受託開発にGo導入。
対象:保守なしの短期利用アプリ

最初はPHPで実装
2000req/secが限界
設計がまずかった

net/rpc packageを使用

4000req/secまで向上

性能測定

  • 実際のAPNs/GCMを使ってのベンチマークは難しい
  • 端末を用意するのが難しい
  • APNsは同一端末から数万件送るとInternalServerError
  • Fake APNs/GCMを用意してベンチマークした

結果

  • 並列数が10以上でレスポンス30秒程度でスケールした

Pros

  • 環境構築が簡単。バイナリだけ
    • 本番環境でライブラリ管理が不要
  • WindowsでもLinuxでも動作する

Goがあって良かったことはあるが、
Goであって困ったことはなかった。

Q&A

  • すべてGo標準ライブラリを使用

Session 7: pt & Goroutins

@monochromegane, GMO Pepabo, Inc.

自作したptの話。

文字列検索には色々ある

  • grep
  • ack
  • ag
  • pt(platinum searcher) written in Golang

SJIS,EUC-JPファイルにも対応
agなどはskipされてしまう

検索の処理フロー
1.ファイル検索
2.文字列検索
3.表示

Approach 1: 最初は普通に直列で実装

Approach 2:各処理をgo f()で並行化
goroutine

  • 軽量、並行処理を実現(not 並列)

channels

  • goroutine間のメッセージング
  • これを使って各処理の結果を次の処理に渡す

goroutine & channnelsでやったら逆に遅くなった

Approach 3:
channelの受付容量を変更

  • ch := make(chan 型, 容量)
  • 容量超えると送信側は待ちになってしまう

これでも、まだ遅い
もっと並行にしよう

grepの部分はfindから来た複数ファイルに対して
1つのgrepを実行するので、これをファイルごとにgrep groutine起動

結果、open too many files...

channelについて、MAX同時並行数を決めておき、
それを越えてはgrep goroutineが待ちになるように修正

Approach 4: 並列にしよう
GOMAXPROCS

  • goroutineの並列度
  • CPUコア数だけ設定する

やっとApproach 1よりも速くなった

今回の開発で、go f()による並行だけでは足りず、並列化する必要があるということがわかった。


残り後2つセッションがあったが、予定があったため、途中退場。残念。