AWS re:Inforce 2019に参加してきました

技術部セキュリティグループの三戸 (@mittyorz) です。こんにちは。 去る6/25,26日に開催されたAWS re:Inforce 2019に参加しましたので、簡単ではありますが紹介させていただきたいと思います。 今回が初開催なため規模感や雰囲気などは未知数の中、クックパッドからはセキュリティグループの三戸・水谷 (@m_mizutani)とVP of Technologyの星 (@kani_b) のあわせて3名で参加いたしました。

AWS re:Inforce とは

AWS re:Inforceは、数あるAWSのカンファレンスの中でもセキュリティに特化したカンファレンスです。 セキュリティに関するイベントはre:Inventなどでもこれまであったわけですが、re:Inventが非常に巨大なイベントとなってしまったこと、クラウドベンダーとしてセキュリティにおいてどのような姿勢で望むのかを積極的にアピールする場としてre:Inforceが新たに用意されたのではないかなと思っています。 AWS以外にも様々なセキュリティベンダーがパートナーとして参加しており、ブースの様子などについては後ほど触れたいと思います。

Builderにとってのセキュリティ

初日、AWSのVPかつCISOであるSteve SchmidtによりKeynoteが行われました。この中で、セキュリティはセキュリティエンジニアだけが考えるものではなくサービスに関係する全てのメンバーが意識し関わるべきものであること、 サービスを作り上げるうえで必要なものを自分たちで選択し作り上げていくように、セキュリティにおいてもベンダーの製品をそのまま使うのではなく、要素を組み合わせ自分たちにとって本当に必要なものを作っていく必要があることが強く主張されていました。 その際に、AWSのクラウドサービスをどのように上手に選択するか、ということが大事になってくるわけです。

セキュリティベンダーの事例紹介でも同様で、単に顧客の環境に自社の製品を導入したという話ではなく、AWSのサービスと組み合わせることでどういうことが新たにできるようになったかということが説明されていました。 そのためには自分たちでセキュリティを作り上げていく必要があり、度々キーワードとして出てきた「Builder」にそのことが表れていると思います。

会場の様子

AWS re:Inforceは現地ボストンにおいて6/25,26の二日間に渡って開催されました。 AWSのカンファレンスといえばまずre:Inventを思い浮かべる方が多いかと思いますが、規模としてはそこまで巨大というわけではなくおおよそ一つの建物にまとまっていました*1

f:id:mittyorz:20190723152400j:plain
会場となったBoston Convention and Exhibition Centerの、おそらく正面入口

f:id:mittyorz:20190723152532j:plain
ベンダーによるブースなどが並ぶ、受付からすぐのスペース。会場は4階まであったので写っているのはごく一部と言えます

日本からは24日18時に成田から離陸して現地に24日18時に到着*2、翌日から二日間会場入りして、三日目木曜日には帰国に向け出発し金曜日夕方に日本に到着するというちょっと強行軍かなとも言えるスケジュールでした。 幸いにも恐れていた時差ボケにはならず、はじめての海外出張かつ大規模なカンファレンス初参加の割には落ち着いて見て回れたのではないかと自分では思っています。

セッションについて

日程は二日間でしたが、聴講タイプのいわゆるSessionの他、手を動かすWorkshopやSecurity Jam他、非常に沢山の ブースではベンダーの説明を聞いたり質問を行うことも出来ますし、待ち合わせ時間などに手元のPCから参加できるCTFも用意されていました。

1時間単位のセッションにいくつか参加したのと、4時間かけて点数を競い合うSecurity Jamに3名でチームを組んで参加しました。

以下、参加したセッションから特に印象に残った点などを簡単に紹介します。

Encrypting Everything with AWS (SEP402)

AWSの各サービスでどの部分でどのような暗号化をしているか、物理層の安全性をどう担保しようとしているか、について広く説明するセッションです。 ただ、時間のかなりの部分が「暗号論入門」という感じで、暗号アルゴリズム自体の説明になっていてちょっと期待とは違ったかなという感想でした。 セッションには難易度が設定されていて、これは「Expert」向けとされていたのですが、暗号アルゴリズムの数学的背景を予め知っているのであればだいぶわかりやすかったのではないかなと思います。 後半はAWSの各サービスでどのように暗号化が行われているかそのアルゴリズムも含め解説され、AWS SDKからの利用といったユーザが直接触れる部分から、インスタンス間やVPC間の通信をどのように行っているのか、更にはリージョン間の物理ネットワークの暗号化などレイヤーごとに説明されていました。 後述するNitro Controllerを用いて暗号化する際には、複数のキーストアから取得した鍵の「一部分」をNitron Controller内であわせることで実際に用いる鍵を生成し用いているという話が特に興味深かったです。

Firecracker: Secure and fast microVMs for serverless computing (SEP316)

LambdaおよびFargateの実行環境を効率的に隔離するために実装されたLinux KVMベースのHypervisior、Firecrackerについてのセッションです。 アカウントごとに実行環境をきちんと分離しつつ、オーバーヘッドの低減を両立させるのは難しいと説明しつつ、一方でFirecrackerを用いることでVMの起動をだいたい120ms以下で行い、一つのホストで1秒間に150VM起動できるようになると話していたのが興味深かったです。 Lambdaを実行している環境は、そのLambdaをデプロイしたアカウントごとに別々のゲストOSにHypervisorによって分離されているわけですが、このHypervisiorにFirecrackerを用いることで一つのホストによりたくさんの環境を詰め込める、ということが詳しく説明されていました*3。 Fargateについては、Firecrackerを用いることでEC2のインスタンスサイズの荒い粒度ではなくより細かくリソースが割り当てられるようになったこと、起動が非常に速いので「EC2 Warm Pool」を用意する必要がなくなり価格が大きく削減できたこと*4が説明されていました。 今後のロードマップでは、現在はIntel CPUのみがサポートされていますが、年内にはAMD CPUのサポートも計画されているとアナウンスされました。

Security benefits of the Nitro architecture (SEP401)

このセッションでは、Nitro Contollerと呼ばれる物理的なチップとそれを用いた全体のアーキテクチャについて説明がありました。 「Nitro」という言葉自体はAWSの最新世代のEC2インスタンスなどで用いられている仮想化技術というコンテキストでよく出てきますが、このシステムを構成するために通常のCPUや周辺機器とは独立して組み込まれているのがNitro Contollerです。 仮想化に伴うオーバーヘッドを低減するために、出来る限りNitro Controllerを用いて処理をオフロードする仕組みになっているのですが、インスタンスストレージへのアクセスを含めDisk I/O、Network I/OなどすべてのI/OはNitro Controllerを用いて透過的に暗号化される仕組みになっています。 また、暗号化に必要な情報はNitro Contoroller同士で自動的にやり取りされるとのこと。 Nitro Controller自体も独自に内部的なストレージを持っていて、ファームウェアのアップデートなどはシステムを再起動すること無く行えるようになっているそうです。 Nitro Controllerが改ざんされないようCPUからは書き込みができないようになっていたり、システムの起動時にはNitro Contorollerによってマザーボードのファームウェアがチェックされるようになっているなど、システムの健全性を担保するのにNitro Controllerが要になっていることがよく分かるセッションでした。

Security Jam

複数人でチームを組み*5、競技時間の4時間の間に出題された問題を出来るだけ問いて順位を競い合います。 競技時間終了と同時に出題ページがクローズされてしまったので記憶を元にちょっと紹介すると、

  • 複数のVPCにまたがって構成されたウェブサービスを再構成する問題
  • EKSのCI/CDと、EKS自体のセキュリティの設定を修正する問題

といったように、AWSの各サービスをきちんと理解していないと問題が解けないようにうまく設計されていて、普段の業務で触ってない部分の知識も容赦なく必要とされなかなか苦労しました。

f:id:mittyorz:20190723152620j:plain
全体で60席くらい用意されていましたが、オンラインで参加できるのでこのホール外から参加していたチームもあったようです

f:id:mittyorz:20190723152643j:plain
5-hour ENERGY という、ちょっとヤバそうなエナジードリンク

最終的に45チーム中11位という結果になりました。

セキュリティの競技だといわゆる「CTF」をまず思い浮かべる方が多いかと思いますが、普通のCTFと比較してみてAWSの環境自体を直す要素が強かったかなと思います。 また、AWSのアカウント・リソースが問題ごとに別々に用意されていて、出題ページからAWSのコンソールにログインすると独立した環境が自由に使えるようになったのは流石だなという感じでした。

ブース

企業ブースでは日本でもよく見る有名・老舗セキュリティベンダーがやはり多かったですが、一方で日本ではあまり見ないベンダのブースも多くありました。こういったブースだと直接担当の人と話して質問ができるのでなかなかカタログスペックなどから分からないことを聞けて面白かったです。全体の傾向としては、以下のような印象でした。 - コンテナ環境を対象としたサービスがメインストリームになりつつあり、逆に言うとEC2インスタンスなどにフォーカスするようなサービスの宣伝はあまり見なかった - クラウド環境全体の監査・コンプライアンスチェックを自動化するというサービスがかなり目立っていた

程度の差はありましたが、ブースエリアはそれほど混んでおらず気になった製品のブースで気軽に質問できるようになっていました。

おわりに

AWS re:Inforce 2019を簡単にですが紹介させていただきました。 AWS自身が提供するセキュリティ機能だけではなく、各社がクラウド向けに出してきているセキュリティ製品をどううまく活用していくのか、いうなれば「顧客が本当に必要だったもの」をきちんと構築できるようになりましょう、というメッセージを強く感じました。 新しい技術・製品がどんどん出てくる中で、適切な技術選択を行うのはとても難しいことですが、難しいからこそ面白い分野でもあると再確認できてとても良かったと思います。

クックパッドでは技術を用いてセキュリティを高め最高のサービスを提供することに興味のある仲間を募集しています。

セキュリティエンジニア

*1:もっとも、建物自体が巨大で、規模感としては東京国際展示場の各展示棟を一つにまとめたくらいをイメージすると近いのではないかなと思います

*2:搭乗時間と時差がちょうど一致

*3:動画で18:30頃から出てくる図を見るとわかりやすいかと思います

*4:https://aws.amazon.com/jp/blogs/compute/aws-fargate-price-reduction-up-to-50/

*5:一人でも参加可能なようでした

Grafana の scripted dashboards を利用してダッシュボードを自動生成する

技術部 SRE グループの鈴木 (id:eagletmt) です。

去年クックパッド開発者ブログでも紹介した hako-console の延長として、メトリクス表示に Grafana の scripted dashboards を利用するようにしているのでその紹介をしようと思います。

アプリケーション毎のダッシュボード

クックパッドではダッシュボードの作成に Grafana を利用しており、主に Amazon CloudWatch と Prometheus に保存されているメトリクスを Grafana で可視化しています。それ以外にも一部開発用のメトリクスは InfluxDB に保存しており、その可視化にも Grafana が利用されています。

Grafana の variables 機能を利用すればリソースの種類毎にダッシュボードを作成することは簡単です。 ELB のロードバランサー名、RDS のクラスタ名、ECS のサービス名を variable として受け取るようにして CloudWatch の dimensions や Prometheus の PromQL にその variable を入れるようにすれば、各リソースの状況を閲覧することができるようになります。

ではアプリケーション毎のダッシュボードはどうでしょうか。典型的な Web アプリケーションの状態やパフォーマンスを知りたいときには

  • ALB のリクエスト数やレスポンスタイムの95パーセンタイルはどうなっているか
  • cAdvisor から得られるコンテナの CPU 使用率やメモリ使用率はどうなっているか
  • RDS の CPU 使用率やクエリのレイテンシはどうなっているか
  • Memcached の CPU 使用率や Eviction はどうなっているか

等の情報を一覧したいでしょう。

hako-console がその一覧するための役割を担っていたのですが、私が実装した hako-console のメトリクス表示画面よりも Grafana でのダッシュボードのほうが圧倒的に見やすく使いやすいため、アプリケーション毎に Grafana にダッシュボードを自動生成する方法を考えました。

Scripted Dashboards

そこで Grafana の scripted dashboards 機能を利用することにしました。 これは Grafana サーバに public/dashboards/nanika.js という JS ファイルを設置して Grafana 上で /dashboard/script/nanika.js にアクセスすると設置した JS ファイルを評価し、その結果をダッシュボードの JSON 表現として解釈しダッシュボードを表示するという機能です。この JS ファイルでは任意の JS コードを実行できるため、以下のように別のサーバが返した JSON をそのまま返すような JS ファイルを設置することで、サーバから Grafana のダッシュボードを制御することが可能になります。

'use strict';

var ARGS;

return async function(callback) {
  const fallback = {
    schemaVersion: 18,
    title: 'Failed to load dashboard from hako-console',
    panels: [
      {
        id: 1,
        type: 'text',
        gridPos: {
          w: 24,
          h: 3,
          x: 0,
          y: 0,
        },
      },
    ],
  };
  try {
    const response = await fetch(`https://hako-console.example.com/grafana_dashboards/${ARGS.app_id}`, { credentials: 'include' });
    if (response.status === 200) {
      const dashboard = await response.json();
      callback(dashboard);
    } else {
      fallback.panels[0].content = `hako-console returned ${response.status} error.`;
      callback(fallback);
    }
  } catch (e) {
    fallback.panels[0].content = `Failed to fetch API response from hako-console: ${e}`;
    callback(fallback);
  }
};

この例ではクエリストリングで app_id というアプリケーションの識別子を受け取り、それを hako-console に問い合わせています。hako-console はこの問い合わせに対してこのアプリケーションに関連する ALB、RDS、Memcached 等のリソースを見つけ、それぞれに対応するメトリクスを表示するようなダッシュボードの JSON 表現を返すようになっています。ダッシュボードの JSON 表現についてはドキュメントがあるのですが、すべてを網羅できているわけではないので、Grafana 上で実際にダッシュボードを作ってその JSON Model を見てそれに合わせる、と進めたほうが私は分かりやすかったです。 https://grafana.com/docs/reference/dashboard/

たとえばとある Web アプリケーションの自動生成されたダッシュボードは以下のようなものです。このダッシュボードを表示する JSON 表現として hako-console は https://gist.github.com/eagletmt/45f8c8bffcbe34f48e937a756aac2a34 のようなレスポンスを返しています (※一部の値はマスキングしてます)。 f:id:eagletmt:20190724111907p:plain f:id:eagletmt:20190724112029p:plain Grafana はダッシュボードの JSON 表現を介して import することもできます。したがって自動生成されたダッシュボードでは物足りず、たとえばアプリケーションが独自に Prometheus に保存しているメトリクスも表示したい場合にも、簡単に拡張することもできます。hako-console 上で固定のメトリクスを表示していたときと比べて、この点も Grafana を利用するメリットだと思っています。

ダッシュボードの工夫

アプリケーション毎のダッシュボードを自動作成するにあたって、見やすさと実用性を重視するために各リソースについて頻繁に参照するメトリクスのみを表示するようにしました。たとえば ElastiCache Memcached の場合、使用可能な空きメモリの量 (FreeableMemory) やキャッシュされた容量 (BytesUsedForCacheItems) 等が役に立つこともありますが、多くのケースで役立つメトリクスは CPU 使用率 (CPUUtilization) や eviction の発生回数 (Evictions)、キャッシュのヒット率等でしょう。公式のドキュメントも参考になります。 https://docs.aws.amazon.com/ja_jp/AmazonElastiCache/latest/mem-ug/CacheMetrics.WhichShouldIMonitor.html

ちなみにキャッシュのヒット率は CloudWatch の基本的なメトリクスには含まれていませんが、GetHits と GetMisses から算出することができます。Grafana は CloudWatch の Metric Math 機能をサポートしているため、これを利用して GetHits / (GetHits + GetMisses) の値を Grafana 上に表示できます。

見やすさのために一部の主要なメトリクスに絞って表示することにしたとはいえ、主要でないメトリクスが手掛かりになることがあるのはたしかです。そこで Grafana パネルのリンク機能を使い、別途用意された詳細なメトリクスが表示されたダッシュボードへ移動できるようにしています。 この機能を利用すると現在のダッシュボードで選択されている time range をリンク先のダッシュボードに引き継ぐことができます。とくに1日以上前の障害を調査したり振り返ったりするときには time range の引き継ぎは便利でしょう。

また、このアプリケーション毎のダッシュボードにはデプロイのタイミングを annotation として表示するようにしています。 f:id:eagletmt:20190724112414p:plain メトリクスの傾向が変化する原因の多くはデプロイです。プロモーション等によるユーザ数の急激な変化や下流のマイクロサービスのデプロイによるアクセス傾向の変化といった他の要因でメトリクスの傾向が変化することもありますが、それらよりもそのアプリケーション自身の変更が原因であることが多いでしょう。ダッシュボード上でデプロイのタイミングを分かりやすくすることで、意図しないパフォーマンス劣化が発生していないか、パフォーマンス改善を狙った変更がうまくいったかどうか、といったことが分かりやすくなることを狙っています。

なお、このデプロイのタイミングはどうやって取得しているかというと、クックパッドではほとんどのアプリケーションが ECS で動いているため、ECS の UpdateService API が実行されたタイミングをデプロイのタイミングとすることができます。そこで、S3 バケットに配信された CloudTrail のログファイルを加工して Prism に渡すことで Redshift Spectrum で読める状態にし、Redshift にクエリすることで UpdateService API が実行されたタイミングを取得して InfluxDB に保存し、Grafana からそれをデータソースとして annotation の query に設定しています。CloudTrail のログは他にも用途があるため、このように一度 Redshift に入れてからそれぞれが使うようになっています。 f:id:eagletmt:20190724112506p:plain

まとめ

Grafana の scripted dashboards という機能と、それを利用してどのようなダッシュボードを自動生成しているかについて紹介しました。Grafana は手軽に見やすいダッシュボードを作成できて便利な反面、variables 機能ではカバーできないような個別のダッシュボードを1つ1つ作るのが面倒に感じている方は、自由度の高い scripted dashboards 機能を利用してみてはどうでしょうか。

ISMM 2019 で発表してきました

技術部の笹田です。遠藤さんと同じく Ruby のフルタイムコミッタとして、Ruby インタプリタの開発だけをしています。

先日、アメリカのフェニックスで開催された ISMM 2019 という会議で発表してきたのと、同時開催の PLDI 2019 という会議についでに参加してきたので、簡単にご報告します。

f:id:koichi-sasada:20190717032426j:plain
カンファレンス会場

ISMM 2019

ISMM は、International Symposium on Memory Management の略で、メモリ管理を専門にした、世界最高の学術会議です。というと凄いカッコイイんですが、メモリ管理専門って凄くニッチすぎて、他にないってだけですね。多分。ACM(アメリカのコンピュータ関係の学会。すごい大きい)SIGPLAN(プログラミングに関する分科会。Special Interest Group)のシンポジウムになります。

発表するためには、他の多くの学術会議と同じく、論文投稿をして、査読をうけ、発表に値すると判断される必要があります。基本的に、ガーベージコレクション(GC)のテクニックの提案や、新しい malloc ライブラリの提案とか、NVMどう使うかとか、そういう話を共有する場です。

ISMM 2019 は、6/23 (日) にアメリカのアリゾナ州フェニックスで1日で開催されました。外はムッチャ暑い(40度近い)ですが、室内は空調でムッチャ寒い、というつらい環境でした。外は暑すぎて歩けなかった。

会議は、キーノート2件に通常発表が11件でした。投稿数が24件だったそうで、採択率は50%弱だったようです。日本国内の会議より難しい(私の知っている範囲では、50%はあまり切らない)けど、トップカンファレンスに比べると通りやすい、というレベルだと思います。

今回、ISMM 2019 に投稿した論文が採択されたので、はじめて行ってきました。GC に関する仕事をしているので、ISMM は一度行ってみたい会議だったので、今回参加できてとても嬉しい。Ruby の GC に関する論文の発表だったので、出張としていってきました。感謝。おかげで、最新研究の雰囲気を感じることができました。

正直、内容と英語が難しくて、あんまり聞き取れなかったんですが、分かる範囲でいくつか発表などをご紹介します。

基調講演

2件の発表がありました。

Relaxed memory ordering needs a better specification

1件目はGoogleのHans-J. Boehmさんよる「Relaxed memory ordering needs a better specification」という発表でした。Boehmさんといえば、私にとってはBoehm GCというよく知られた実装の開発者の方ということで、お会いできて大変光栄でした。最近はC++言語仕様の策定などでお名前をよく聞きますが、今回はその話でした。なお、ここ最近は GC の実装にはほとんど関わってないと伺いました。

f:id:koichi-sasada:20190717032523j:plain
Boehmさんのキーノート

マルチスレッドプログラミングにおいて、メモリを読み書きする順序(メモリオーダリングといいます)が問題になることがあります。書いたと思った変数の値を読み込んでみたら、書き込む前の値だった、ってことがあったら驚きますよね。実は、マルチスレッドだとそういうことが起こってしまうんです。性能を良くするために、いくつかのCPUでは、共有メモリに対する他のスレッドからの書き込みが、逐次実行で見える書き込みの順序と違う可能性があるのです。

何を言っているかよくわからないと思うんですが、正直私もよくわかりません。例えば、0初期化された共有メモリ上にある変数 a, b があったとき、a = 1; b = 2; というプログラムがあったら、(a, b) の組は (0, 0)、(1, 0)、(1, 2) の3通りしかないように思うんですが(逐次(シングルスレッド)プログラムだと、実際そうです)、他のスレッドから観測すると、(0, 2) という組が見えたりします(他の最適化が絡むと、もっと変なことが起る可能性があるらしいです)。わけわからないですよね? わからないんですよ。人間にはこんなの管理するのは無理だと思う。共有メモリなんて使うもんじゃない(個人の感想です)。

さて、どんなふうにメモリーオーダリングをするか、という指定をするための言語機能が C++ などにあります(std::memory_order - cppreference.com)。例えば memory_order_seq_cst というのが一番厳しい指定で、他のスレッドからも同じように見える(つまり、上記例だと (0, 2) という組は見えない)ようになり、プログラミングするにはこれが多分一番便利です。ただ、性能のために都合の良いように CPU が順序を変えている(可能性がある)のに、その順序を厳しく制御する、ということになるので、オーバヘッドがかかります。で、どの程度厳しくするか、みたいなので、いくつか種類があるわけです。CPU によって、どの程度デフォルトが厳しいか決まるんですが、幸い、x86(x86_64)は比較的強いメモリオーダリングを行うので、あんまり難しくない、らしいのです。ARM とかだと弱いらしいとか、さっきググったらありました。やばいっすね。

今回の基調講演では memory_order_relaxed という、多分一番ゆるい(何が起こるかわからない)メモリオーダリング指定を、どうやって仕様化すればいいか難しい、という話を、実際にすごく不思議な挙動があるんだよねぇ、という豊富な実例をあげて紹介されていました。従来の仕様では、例ベースでしか仕様に書けなかったんだけど、なんとか書きたいなぁ、でも難しいなあ、というお話でした。結論がよくわかってなかったんだけど、結局うまいこと書けたんだろうか。

なんでメモリ管理の会議 ISMM でメモリオーダリングの話が問題になるかというと、並行GCっていう研究分野があって、GC するスレッドとプログラムを実行するスレッドを並行・並列に実行していくってのがあるんですね。で、それを実現するためにはメモリオーダリングをすごく気にしないといけないわけです。これもきっと人間には無理だと思うんですが、実際にいくつかの処理系でやってるのが凄いですよねえ。いやぁ凄い。

Why do big data and cloud systems stop (slow down)?

2件目のキーノートは、シカゴ大学のShan Lu氏による「Why do big data and cloud systems stop (slow down)?」という発表でした。

実際のウェブアプリケーションや分散処理基盤(Azure。共同研究されてるんでしょうなあ)でどんな問題があるか、主に性能の観点から分析してみたよ、という話でした。ウェブサイト(Shan Lu, CS@U-Chicago)を拝見すると、輝かんばかりの業績ですね(研究者は良い学会に論文を通すことが良い業績と言われています。で、見てみると本当に凄い学会に沢山論文が採択されていて凄い)。

面白かったのが、ウェブアプリケーションの性能分析で Rails が題材になっていたことです。「あ、見たことあるコードだ」みたいな。

ウェブアプリケーションに関する分析の話は、View-Centric Performance Optimization for Database-Backed Web Applications (ICSE'19) のものだったように思います。主に ORM でのアンチパターンをいろいろ分析して(講演では、そのパターンを色々紹介されていました)、それを静的解析してアプリからそのアンチパターンを見つけて良い方法を提案するツールを作ったよ、と。Panorama というツールを作っていて公開されています。なんと IDE (Rubymine)との統合までやっているようです。凄い。論文中に、いくつかリファクタリング例があるので、気になる方は参考にしてみてください。しかし、Rails アプリの静的解析って、えらく難しそうだけど、どれくらい決め打ちでやってるんですかねぇ。

Azure のほうは、設定間違いがほらこんなに、とか、そんなご紹介をされてたような気がします。具体的には What bugs cause production cloud incidents? (HotOS'19) の話かなぁ。論文中 Table 1 がわかりやすいので引用します。

    What are the causes of incidents?
↓ Few hardware problems
↓ Few memory bugs
↓ Few generic semantic bugs
↑ Many fault-detection/handling bugs
↑ Many data-format bugs
↑ More persistent-data races

    How are incidents resolved?
↑ More than half through mitigation w/o patches

Table 1: How are cloud incidents different from failures in single-machine systems?
(↑ and ↓ indicate cloud incidents follow certain pattern more or less than single-machine systems.)

いやぁ、こういう網羅的な調査を行うって凄いですよね。

一般発表

一般発表は、次の4つのセッションに分かれていました(Program - ISMM 2019)。

  • Scaling Up
  • Exotica
  • Mechanics
  • Mechanics / Message Passing

かなり大ざっぱな区切りですよね。Exotica とか凄い名前。

そういえば、"Scaling Up" セッションは、東工大とIBM東京基礎研の方々による3件の発表となっており「東京セッション」と座長に紹介されてました。また、私が発表しているので、東京の組織の発表が11件中4件あったことになるんですね。日本人はメモリ管理好きなんでしょうか。まぁ、私は好きですけど。

いくつか紹介します。

malloc の改良

  • Timescale functions for parallel memory allocation by Pengcheng Li (Google) et.al.
  • A Lock-Free Coalescing-Capable Mechanism for Memory Management by Ricardo Leite (University of Porto) et.al.
  • snmalloc: A Message Passing Allocator by Paul Lietar (Drexel University) et.al.

これら3件の発表は、malloc の実装を改良、もしくは新規に作りました、という話でした。なんというか、malloc() は、まだまだ進化するんだなぁ、やることあるんだなぁ、という感想。どれも、並列計算機(マルチスレッド環境)での弱点をどう克服するか、という研究でした。

とくに最後の snmalloc は面白くて、確保 malloc()、解放 free() のペアって、たいていは同じスレッドで行われると仮定してライブラリを作るので、別スレッドで free() しちゃうと余計なオーバヘッドがかかっちゃう、ことが多いようです(実際、私も作るならそう作りそう)。ただ、いくつかの種類のプログラム、例えば複数スレッドで仕事をパイプライン的に流していくとき、確保と解放は必然的に別スレッドになって、そこがボトルネックになるので、メッセージパッシング機構をうまいこと作ることで、free()の時にしか同期が不用で速いアロケータを作ったよ、というものでした。

Google の中川さんが論文の説記事を書いていたので、ご参照ください(論文「snmalloc: A Message Passing Allocator」(ISMM 2019))。

GC の改良

  • Scaling Up Parallel GC Work-Stealing in Many-Core Environments by Michihiro Horie (IBM Research, Japan) et.al.
  • Learning When to Garbage Collect with Random Forests by Nicholas Jacek (UMass Amherst) et.al.
  • Concurrent Marking of Shape-Changing Objects by Ulan Degenbaev (Google) et.al.
  • Design and Analysis of Field-Logging Write Barriers by Steve Blackburn (Australian National University)

GCの改善の話も結構ありました。

最初の話は、IBM東京基礎研の堀江さんらによる、並列GCの work-stealing を効率化した、という話でした。GCスレッドを複数立てて、GC処理を速く終わらせるには、仕事を分散させるためのテクニックである work-stealing が必要になります。それに関するテクニックの話でした。対象が POWER なのが IBM っぽくて凄いですね。

二つ目は、GCのいろいろなチューニングをランダムフォレストでやってみよう、という話でした。GC の制御も AI 導入、みたいな文脈なんでしょうか?

三つ目は、Google V8 での並行マーキングにおいて、メモリの形(というのは、メモリレイアウトとかサイズとか)を変更しちゃう最適が、並行GCと食い合わせが悪いので、それをうまいこと性能ペナルティなくやるって話で、実際に Chrome に成果が入っているそうです。みんなが使うソフトウェアに、こういうアグレッシブな最適化を入れるの、ほんと凄いですね。話は正直よくわからんかった。

最後は、Field-Logging Write Barriersというのは、フィールド単位(Ruby でいうとインスタンス変数)ごとにライトバリアを効率良く入れる提案でした。Ruby 2.6(MRI)だと、オブジェクト単位でライトバリアを作っているんですが、さらに細かく、バリア、というか、バリアによって覚えておくものを効率良く記録する方法、みたいな話をされていました。むっちゃ既存研究ある中(発表中でも、既存研究こんなにあるよ、と紹介していた)で、さらに提案するのは凄い。

Gradual Write-Barrier Insertion into a Ruby Interpreter

私(笹田)の発表は、Ruby にライトバリア入れて世代別GCとか作ったよ、という Ruby 2.1 から開発を続けている話を紹介しました(Gradual write-barrier insertion into a Ruby interpreterスライド資料)。2013年に思いついたアイディアなので、こういう学会で発表するのはどうかと思ったんですが、ちゃんとこういう場で発表しておいたほうが、他の人が同じような悩みをしなくても済むかも、と思って発表しました。RubyKaigi などでしゃべっていた内容をまとめたものですね。

簡単にご紹介すると、Ruby 2.1 には世代別GC(マーキング)、2.2 にはインクリメンタルGC(マーキング)が導入されました。これを実現するために、"Write-barrier unprotectred object" という概念を導入して、ライトバリアが不完全でもちゃんと動く仕組みを作った、という話です(次回の Web+DB の連載「Ruby のウラガワ」でも解説しますよ。宣伝でした)。GC は遅い、という Ruby の欠点は、この工夫でかなり払拭できたんじゃないかと思います。まだ GC が遅い、というアプリケーションをお持ちの方は、ぜひベンチマークを添えて笹田までご連絡ください。

「Gradual WB insertion」というタイトルは、ライトバリアをちょっとずつ入れて良い、って話で、実際 Ruby 2.1 から Ruby 2.6 までに、徐々にライトバリアを入れていったという記録を添えて、ちゃんと「Gradual に開発できたよ」ということを実証しました、という話になります。

結構面白い話だと思うんだけど、アイディア自体が簡単だったからか、質問とかほとんどなくて残念でした。まぁ、あまり研究の本流ではないので、しょうがないのかなぁ(本流は、ライトバリアなど当然のようにある環境でのGCを考えます)。

PLDI 2019

PLDI は、Programming Language Design and Implementation の略で、プログラミング言語の設計と実装について議論する、世界で最高の学術会議の一つです。以前は、実装の話が多かったんですが、PLDI 2019 から引用しますが、

PLDI is the premier forum in the field of programming languages and programming systems research, covering the areas of design, implementation, theory, applications, and performance.

とあって、設計と実装だけじゃなく、理論やアプリケーション、性能の分析など、プログラミング言語に関する多岐にわたる話題について議論する場です。言語処理系に関する仕事をしているので、一度は行ってみたかった会議です。ISMM出張のついでに出席させて貰いました。参加費だけでも6万円くらいするんですよね。

PLDI 2019 は、6/24-26 の3日間で行われました。ISMM 2019 は、この PLDI 2019 に併設されています。PLDI は言語処理系によるメモリ管理もスコープに入っているので、実は ISMM で発表するよりも PLDI で発表するほうが、他の人から「凄い」と言われます。どの程度凄いことかというと、283論文が投稿され、その中で76本が採択されたそうです(27%の採択率)。これでも、例年より高かったそうです。死ぬまでに一度は通してみたい気もしますね。まぁ、難しいかなぁ(例えば、日本人で PLDI に論文を通した人は、あんまり居ません)。

発表

三日間で最大3セッションパラレルに発表がされるため、あまりちゃんと追えていないのですが、印象に残った発表についてちょっとご紹介します。

ちなみに、以前は結構、がっつり実装の話が多かったんですが、今回の発表は、

  • 理論的な分析の話
  • 特定分野(例えば機械学習)の DSL の話

が多いなぁという印象であり、あんまり(私が)楽しい実装の話は少なかったように思います。

セッションは次の通り(これだけ見てもムッチャ多い)

  • Concurrency 1, 2
  • Language Design 1, 2
  • Probabilistic Programming
  • Synthesis
  • Memory Management
  • Parsing
  • Bug Finding & Testing 1, 2
  • Parallelism and Super Computing 1, 2
  • Type Systems 1, 2, 3
  • Learning Specifications
  • Reasoning and Optimizing ML Models
  • Static Analysis
  • Dynamics: Analysis and Compilation
  • Performance
  • Systems 1, 2
  • Verification 1, 2

いくつかご紹介します。

Renaissance: Benchmarking Suite for Parallel Applications on the JVM

発表は聞いてないんですが、JVM の並列実行ベンチマークについての発表だったそうです。よく DaCapo とかが使われていましたが、また新しく加わるのかな。

DSL

繰り返しになりますが、ある分野に対する DSL の話が沢山ありました。ちょっと例を挙げてみます。

  • LoCal: A Language for Programs Operating on Serialized Data は、シリアライズされた状態のままデータを操作する DSL
  • Compiling KB-Sized Machine Learning Models to Tiny IoT Devices は、IoT 環境みたいなリソースセンシティブな閑居杖、良い感じに整数で浮動小数点っぽい計算をする DSL
  • CHET: An Optimizing Compiler for Fully-Homomorphic Neural-Network Inferencing は、暗号化したまま計算する仕組みのための DSL/Compiler(多分。自信ない)。
  • FaCT: A DSL for Timing-Sensitive Computation は、タイミングアタック(計算時間によって秘密情報を取ろうというサイドチャンネルアタック)を防ぐために、計算時間を結果にかかわらず一定にするコードを生成するための DSL(多分)。

なんかがありました。もっとあると思います。適用領域が変われば言語も変わる。正しいプログラミング言語の用い方だと思いました。

メモリ管理

メモリ管理はわかりやすい話が多くて楽しかったです。

  • AutoPersist: An Easy-To-Use Java NVM Framework Based on Reachability は、Java (JVM) に、良い感じに NVM (Non-volatile-memory) を導入する仕組みを提案。
  • Mesh: Compacting Memory Management for C/C++ Applications C/C++ で無理矢理コンパクションを実現しちゃう共学のメモリアロケータの実装。
  • Panthera: Holistic Memory Management for Big Data Processing over Hybrid Memories は、NVM をでかいメモリが必要な計算でうまいこと使うためのシステムの紹介。

Mesh については、これまた Google 中川さんの論文紹介が参考になります(論文「MESH: Compacting Memory Management for C/C++ Applications」(PLDI 2019) )。むっちゃ面白い。Stripe にも務めている(多分、論文自体は大学の研究)ためか、評価プログラムに Ruby があって面白かった。ちょっと聞いたら(発表後の質疑応答行列に30分待ちました。凄い人気だった)、Ruby のこの辺がうまくマッチしなくて云々、みたいな話をされてました。

Reusable Inline Caching for JavaScript Performance

V8のインラインキャッシュを、再利用可能にして、次のブート時間を短縮しよう、という研究でした。私でも概要がわかる内容で良かった。インラインキャッシュの情報って、基本的には毎回変わっちゃうんで、難しいのではないかと思って聞いてたんですが、巧妙に変わらない内容と変わる内容をわけて、変わらないものだけうまいことキャッシュして、うまくボトルネック(ハッシュ表の検索など)を避ける、という話でした。V8って膨大なソースコードがありそうなので、Google の人に聞いたのですか、と聞いてみたら、全部独学だそうで、すごい苦労して読んだと言ってました。凄い。

Type-Level Computations for Ruby Libraries

RDL なんかを作っている Foster 先生のグループの発表で、Ruby では動的な定義によって、実行時に型が作られるので、じゃあ実行時に型を作ってしまおうという提案です。Ruby でも PLDI に通るんだなあ、と心強く感じます。Ruby 3 の型はどうなるんでしょうね。

A Complete Formal Semantics of x86-64 User-Level Instruction Set Architecture

x86-64 の全命令(3000命令弱といってた)に形式定義を K というツールのフォーマットで記述した、という発表で、ただただ物量が凄い。おかげで、マニュアルなどにバグを見つけたとのことです。成果は Github で公開されてます(kframework/X86-64-semantics: Semantics of x86-64 in K)。

おわりに

ISMMはPLDIに併設されたシンポジウムですが、PLDIもFCRC という、学会が集まった大きな会議の一部として開催されました。懇親会はボーリング場などが併設された会場で行われ、いろいろ規模が凄かったです。

f:id:koichi-sasada:20190717032623j:plain
懇親会の様子

こういう学会に出席すると、最新の研究成果に触れることができます。正直、しっかりと理解できないものが多いのですが、雰囲気というか、今、どういうことが問題とされ、どういうところまで解けているんだ、ということがわかります(まだ、malloc ライブラリの研究ってこんなにやることあるんだ...とか)。このあたりの知見は、回り回って Ruby の開発にも役に立つと信じています。立つと良いなぁ。

今回の論文執筆と参加をサポートしてくれたクックパッドに感謝します。