natumn.blog

なつめ(ん)?ブログ

メルカリのスカラーシップでGo Conference 2018 Autumn に行ってきた

f:id:nktafuse:20181125210400j:plain

こんにちは、natumnです。
11/25に開催されたGo Conference 2018 Autumnにメルカリのスカラーシップ制度で行ってきました!

スカラーシップ制度について

tech.mercari.com

今回のGo Conference に参加するにあたって

  • 交通費、宿泊費
  • Go Conference 2018 Autumnへの参加
  • ルカリオフィス見学
  • Goエンジニアの方々とランチ

のサポートをしてもらいました。
東京のカンファレンスに参加したくてもお金がないという地方の学生にとってとてもありがたい制度です。 基本的にメルカリの社員の方とご一緒させてもらうわけではなく当日自由にイベントやセッションに参加する形でした。 今回は会場近くのホテルを予約していただきました。徒歩10分くらいで会場にいけて近くて便利でした。

会場 と セッション

今回のGo ConferenceはGoogle Tokyo office 27Fで行われ、セッションの行われるA会場とB会場, ハンズオンが行われるC会場の3つの会場に別れていました。 どれもとても面白そうでどのセッションを聴きに行くかとても迷いました...!


私は以下のセッションを聴きに行きました。

  • Keynote session - Go on App Engine Second generation
  • S1 - Microservices実装ガイド in Go at Mercari
  • S2 - よくあるJava IT企業で新規プロジェクトをGoで立ち上げてみてる話
  • A1 - OpenCensus による APM の実現と、未来
  • A2 - Profiling Go Application
  • B3 - Linting, Slicing, and Dicing OpenAPI documents
  • A4 - Consider pluggable CLI tool implementation
  • A5 - フィードバック制御によるGoroutine起動数の最適化
  • B6 - API Testing the Hard Way
  • A7 - Introduce GAE/Go 2nd generation
  • S3 - Pains and gains of architecting microservices on local dev environment
  • S4 - 大規模ウェブサービスにおけるコードレビュー観点
  • LT1 - 社内初導入のAPIサーバーサイドアーキテクチャ設計戦略
  • LT2 - gorealizeで始めるDocker開発環境

セッションまとめ、感想

以下セッションのまとめと感想です。

Keynote session - Go on App Engine Second generation

GoogleのSteven Buss氏によるGoogle App Engineの始まりから現在までのランタイムの歴史の話でした。
1st genのGoogle App Engineではセキュリティの観点から Google Linux → ptrace → NaCl (Google Native Client) → Go という構造で二重にサンドボックス化をしていたそうです。
しかし、それにより

  • GoのマイナーバージョンのリリースごとにRuntimeのバージョンあげる必要がある
  • パッチやセキュリティレビューの時間がかかる
  • appengine packageなどによる利用制限
  • NaCl自体が難しい

など多くの制限が存在しました。 それらの解決策としてgVisorが開発され、NaClからgVisorへの移行が行われました。 1st genに比べ http.ListenAndServe 使えたり、dev_appserver.py いらないかったり、同じアプリを通常どおり go build して起動できるようになったり、goappコマンドいらなくなったりと appengine特有のものが減ってありがたい。しかし、ptraceが若干ボトルネックになりデプロイが遅くなってしまっているとのこと。いずれにせよ、正式リリースが楽しみですね...!
私は最近Google App EngineとGoを利用して開発を行うことが多いのですが、gVisorは名前だけ知っているという状態でしたので、今回1st genから2nd genへの移行とその経緯の話を聞けて興味深かったです。 また、gVisorではptraceやseccomp-golangを用いてアプリケーション側からのシステムコールの監視や制限を行なっているのですが、実際にコードを読んでみるとGoでのシステムプログラミング学べてそれがまた新鮮で面白かったです。

A2 - Profiling Go Application

speakerdeck.com

@orisano氏がGoのプロダクトで実際に行った高速化やプロファイリングの実例のお話でした。
自前の画像変換サーバーからOSSのkubelet、go-swaggerのパフォーマンス改善をしてどのようなプロセスで改善をしていくのかわかりやすいセッションでとても勉強になりました。エンジニアにおけるパフォーマンス改善のなかで「推測するな、計測せよ」とはよく言いますが、実際にそれを行動に起こすにはイメージがわかなかったり、具体的にどうしたらいいかわかりづらくて少し難しいと思います。そこで今回のお話は具体的にどんなGoのツールやライブラリを利用してどんなプロセスで、どんなことを考えていたのかを聞けて勉強になりました。また、個人的にコンパイラのBounds Check Eliminationを初めて知ったので興味深かったです。
OSSでも意外とカリカリにチューニングしてあるプロダクトは少ないとのことなので、私も頑張ってコントリビューションしていきたいと思いました。

B6 - API Testing the Hard Way

speakerdeck.com

Goにおけるアプリケーションのテストの話でした。ネット上に投稿してあるGoのテストのノウハウは

などばかりでテストの実例が少なく、特にインテグレーションテストが少ない。そこでスピーカーの@timakin氏が実際に行っているTestのTipをまとめて話してくれました。
まず、テストにおけるインターフェースによる抽象化のメリットやTable driven Test, テストのキャッシュ、Goでテスタビリティーをあげるために心がけたいことなどを前提としていかにそれらを実現していくかを考えてきました。 個人的にfailed時に呼び出し場所の出力を行うTest HelperメソッドやtryというHTTPリクエストのラッパーが参考になりました。また、それらはGo標準やGoogleのプロダクトのテストコードを見てみると勉強になるとのことでした。今回のセッションでGoにおけるテストはいかにうまくテストのヘルパー関数を作り、わかりやすくて簡単にテストコードがかける仕組みを提供するのも大事だなと思いました。 便利に効率的にテストを書いていきたいと思いました!
また、テストのキャッシュに関しては以下のプレゼンを見て欲しいのとのことでしたが、こちらも面白かったです。

speakerdeck.com

ルカリオフィス見学 & ランチ

次の日にはメルカリのオフィス見学とGoエンジニアの@tenntennさん、@codehexさん、@inukiromさんと焼肉ランチにいきました。 エディタなどの開発環境の話やGo Conferenceのセッションを振り返ったり、最近出たanalysis packageの話をしました。analysis packageは静的解析するモジュールのインターフェースと構造体を定義したパッケージです。それを利用することにより直接ast/goなどのパッケージを扱うよりもモジューラビリティが高く、静的解析のツールが扱いやすくなります。実際に触ってみたい方はtenntennさんのreadonly が使い方がシンプルでわかりやすいので参考にするといい思います。また、analysis/passes以下に色々な実装が入っているのでそこのモジュールを利用していくのもおすすめです。 私もanalysisパッケージを利用してツールを作ってみてます。ガンガン静的解析で便利なツールを作っていきたい!
あと、なぜか税金の話もしてました笑 学生であまり気にしたことはなかったのですが、社会に出る前にしっかり勉強しておこうと思いました。

おわりに

一年ぶり2度目のGo Conference への参加だったのですが、なによりとても楽しかったです!!! セッションがどれもおもしかったのはもちろんですが、周りにはGoが好きなエンジニアしかいないと思うととても刺激的な場でした。 よりGoの良さを知れてもっとGoでプロダクトを作っていきたいと思いました。
運営をしてくださった方々、スポンサーとして様々な支援をしてくださった企業さん、今回スカラーシップを提供してくださったメルカリさん、本当にありがとうございました!
次もまた参加したい。

Rustでheadコマンドを作ってみる

はじめに

この記事はAizu Advent Calendar 2017の19日目の記事です。

adventar.org

2月以降ブログは全く書いてなくて、約10ヶ月ぶりです。natumnです。
最近はアルバイトでフロントエンドをかき、個人的にバックエンドやシステムプログラムをかくみたいな生活を送っています。


そこで今ちょうど、「ふつうのLinuxプログラミング(第二版)」という本を読んでるのですが、本の中に「headコマンドを作る」という章がありました。
そのままC言語で写経してもあまり面白くないので、自分が今勉強中であるRustでheadコマンドを実装していきたいと思います。

環境

cargoバージョン 0.19.0
Rustバージョン 1.18.0

目標

今回は以下のような仕様を満たすコマンドを作っていきたいと思います。

  • 第一引数はrhead
  • nオプションとその後ろの数字で行数指定
  • ファイル名指定

例)

$ rhead -n 5 cat.txt

プログラムは

github.com

にあります。

それでは、作っていきましょう!

コマンドラインの解析を行う

まずコマンドラインの解析だけを行います。
ツールは公式から提供されているgetoptsというcrateを利用します。

doc.rust-lang.org

まずは rhead、-nオプションとそれに続く行数、-rファイル名の3つを取得します。
以下のように書きます。

    // argsを取得
    let args: Vec<String> = env::args().collect();
    let program = args[0].clone();
    let filename = Some(args[4].clone());

    // optionの設定
    let mut opts = Options::new();
    opts.optopt("n", "", "set number of lines", "LINES");
    opts.optflag("h", "help", "print this help menu");

    // optionの解析
    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(f) => panic!(f.to_string()),
    };
    if matches.opt_present("h") {
        print_usage(&program, &opts);
    }
    let opt = matches.opt_str("n");
    let cmd = if !matches.free.is_empty() {
        matches.free[0].clone()
    } else {
        print_usage(&program, &opts);
        return;
    };

    // cmd, opt, filenameをprintする関数
    do_work(&cmd, opt, filename);

fn do_work(inp: &str, lines: Option<String>, filename: Option<String>) {
    println!("{}", inp);
    match lines {
        Some(x) => println!("{}", x),
        None => println!("No lines"),
    }
    match filename {
        Some(x) => println!("{}", x),
        None => println!("No File"),
    }
}

fn print_usage(program: &str, opts: &Options) {
    let brief = format!("Usage: {} FILE [options]", program);
    print!("{}", opts.usage(&brief));
    process::exit(0);
}

コードの流れとしては

まず、はじめにコマンドライン引数に渡される値を取得します。
その後、getopsを利用してoptionの設定を行っています。(例えば、-nがきたらその後ろの値をLINESとして取得しています)
そして、それぞれの引数の解析をおこない、その結果をdo_work関数に渡します。
do_work関数では情報であるコマンド名、行数、ファイル名が出力されます。


出力例)

f:id:nktafuse:20171219135659p:plain


head関数を作る

次にhead関数を作っていきます。
head関数は取得した行数とファイル名を元にファイル内容を出力します。

コードは以下のようになります。

fn head(lines: i32, filename: String) -> i32 {
    // ファイル読み込み
    let string = String::from(filename);
    let path = Path::new(&string);
    let mut file = BufReader::new(File::open(&path).unwrap());

    // ファイルが空かチェック
    if lines <= 0 {
        return 0;
    } else {
        let mut buf = String::new();
        let mut count = 0;
        let mut done = false;

        // 選択した行数かファイルの最後まで行ごとに出力
        while !done {
            file.read_line(&mut buf).expect(
                "reading from BufReader won't fail",
            );
            print!("{}", buf);
            count += 1;
            if lines == count || buf == "" {
                done = true;
            }
            buf.clear();
        }
        return 0;
    }
}

このコードではまず、ファイル名からファイルのバイト列を取得して、それを一行ごとに print! してます。
バイト列の取得にはBufReaderトレイトを利用します。


そして、カウントが指定の行数に達するかファイルが最終行までいったらループを抜けるようになっています。
今回の場合、file.read_line()はBufReadトレイトを満たしたトレイトでかつ、引数ではバイトのスライスでなければ利用できませんので、注意が必要です。
自分はここへんの知識が曖昧で結構時間を溶かしました。

そして、最後にmain関数のもとあったdo_work関数をhead関数に合うように変更してcargoで実行すると、以下のような実行結果が得られます。


出力例)

f:id:nktafuse:20171219180403p:plain



なんとか仕様をみたすプログラムができました!

まとめ

  • getoptsでオプション解析できる。
  • トレイトや型の条件を満たす実装をしているかの把握は重要。

おわりに

Aizu Advent Calendarの投稿に間に合ってよかった...
簡単でヘルプなどの機能を追加していないのですが以上になります。
比較的簡単なプログラムなのに意外と時間かかった... traitや所有権とかまだ慣れない。

私自身Rustを最近学び始めたので、なかなかRustの機能を生かした書き方ができていないかもしれません。
上記のコード中にある、行数分の出力する処理の部分など所々いい書き方が思い浮かびませんでした...
これから書いていって、知見を増やしていきたい。


もし、「ここをこう書いたら良くなる」などアドバイスありましたら、お願いします...!


では、これで!読んでくれた方、ありがとうございました!

Developers Summit 2017 1日目に行ってきた。

こんにちは。2ヶ月ぶりくらいの投稿です。
先日2/16に、東京の目黒で開催されたDevelopersSummit2017に行ってきたのでそのことを書く。

f:id:nktafuse:20170220162950j:plain

会場は目黒雅叙園

Developers Summit 2017とは

総合ITコンファレンスです。
様々な会社の方が最新のソフトウェア開発やシステム開発、インフラ管理、自社制度などのIT系技術、制度のプレゼンを五十分くらいで話すといったようなものです。
GoogleYahoo!Japan,Mozillaなどなど様々の会社の人がスピーカーとして話してました。

Developers Summit 2017 エンジニアとして生きる、技術の先にある現実に踏み出す


自分が聞いたプレゼン

自分は以下のようなプレゼンを見てきました。

  1. 「データテクノロジースペシャル」Yahoo! JAPANにおけるメタデータ管理の試み 吉野 彰真氏 [ヤフー]
  2. Google のインフラ技術から考える理想の DevOps 中井 悦司氏 [グーグル]
  3. エンジニアが働きたい場所で働けるために、チームに必要なこと 岡田 勇樹氏 [サイボウズ]
  4. Node.js の未来について 古川 陽介氏 [リクルートテクノロジーズ]
  5. MicrosoftのAI開発機能/サービス 佐藤 直生氏 [日本マイクロソフト]
  6. 新しいビルドターゲットとしての Webブラウザ。もしくは C/C++ で書く Web フロントエンドプログラム 清水 智公氏 [Mozilla Japan]

感想(4つ)

Yahoo! JAPANにおけるメタデータ管理の試み

Yahoo!JAPANという大企業がどのようにデータを対処していくかというのが今回のプレゼンの本筋で、データが重要になってきた情報社会でデータマネジメントの重要性が比例すること、また、そのためのメタデータが資産・情報管理の第一歩なることがよくわかった。例えばそのデータの価値、利用頻度、品質、人が取ってくるのか自動で取れるかといったようなものを課題ベースで決定し、データを可視化できるようにすることなど、バックエンド開発(インフラよりではないにしても)を勉強している自分も考えていかなければならない課題が新たに発見できたのでよかった。また、実践する際はやはりYahoo!JAPANのような大企業の真似から入るが手っ取り早いと感じた。
一発目からめっちゃ面白かった。


f:id:nktafuse:20170220182638j:plain



Google のインフラ技術から考える理想の DevOps

実際の開発環境例をベースにGoogleがどういった開発環境をつかっているか、どういった考えのもとで開発を行っているかというようなことが聞けた。
Googleの徹底的な合理主義、技術的な制約に対する洞察力は本当に素晴らしくて、見習いたいし、これから意識していこう思った。実際の開発ではコンテナ利用してレイヤーどとにしっかり分けること(例えば、OSレイヤーはアプリケーション開発側からはできるだけ隠蔽するとか)などにより、全体を最適化しスムーズに開発をおこなえるようになること。また、使う技術要素を理解し、システム全体のアーキテクチャを理解すること、そのためにソフトウェアの特性などを把握して知識としてのフルスタックを目指すことが大切ということがわかった。やっぱりGoogleの社員さんはカッコイイ!


f:id:nktafuse:20170220182204j:plain



Node.js の未来について

日本Node.jsユーザーグループ代表の古川さんの話が聞けてよかった。内容としては、今までのNode.js(v4v6v7)の機能の解説、そしてこれからのNode.js(v8v10)の話だった。v8からついにhttp/2のサポートが入り、今回はその解説となって早く使ってみたいと思った。また、v10からでる?と思われるES modulesの話もあり、ES modulesはいままでのNode.jsとは少し違ったものとなるのでとても興味深かった。Node.jsが好きな自分としてとても面白かった!


f:id:nktafuse:20170220182811j:plain



新しいビルドターゲットとしての Webブラウザ。もしくは C/C++ で書く Web フロントエンドプログラム

最近少し名前が出てきたWebAssemblyの話。冒頭にいきなりemccというコマンドを実行してcのコードからhtmlファイルとcssファイル
,jsファイルが出てきたときは驚いた!実際はEmscriptenというC/C++ のコードからウェブブラウザや Node.js などで動作する JavaScript を出力するコンパイラを利用することによって生成されている。元々、ウェブブラウザからゲームしたくね?という発想から生まれたらしいが、色々な場面で役立ちそうだし、何よりめっちゃ速い。凄く速い。自分はC/C++は書けないので実際に使えるようになるのはまだまだ先の話だけど、これからがとても楽しみな分野だと感じた。


f:id:nktafuse:20170220181450j:plain


まとめ

どのプレゼンも本当にとても面白かったです。二日目に行けなかったのが、悔しい。。 次こそ2日間いく!!!
技術的なものを得られたのはもちろんのことですが、しかしそれだけでなく、周りの実際に企業で働いている人たちやスピーカーの方々をみて、モチベーションのアップにも繋がりました。やはり、こうゆうコンファレンスなどは得るものが多くて改めて行ってよかったと感じます。

では!