クラウド時代と競技プログラミング
この1週間ほど、社内イベントで開催されているプログラミングコンテストにエントリーしてみました。昨年1月に独習・速習したPython、使わずに1年いたらすっかり忘れてたので、いい復習機会になっています。
最初のうちはやりたい処理をそのまま書いていけばクリアできるけど、徐々に処理時間制限1秒との戦いが始まります。言語組込や標準ライブラリの持つリッチな関数を捨て、ループ処理と四則演算やら文字列処理やらで地味に自前実装します。自前ループ処理を眺めていると、大幅に処理回数を減らせそうな箇所に気づき、また書き直します。プロファイラを使ってみると、きっとこの辺が遅いだろうと思ってたところはミリ秒で回ってたりして、大変(に私の頭が悪い)です。
富豪的プログラミングとクラウドコンピューティング
こうした処理時間やリソースを倹約するプログラミングは、かつては王道で花形でした。しかし00年代中頃、ネイティブからWeb 2.0アプリケーションへのシフトが進む中で「画面のレスポンスタイムは3秒まで」とかわりと処理時間の制約は緩くなりました。一方で「永遠のベータ版」「アジャイル」といった流れの中で、リッチな関数やライブラリを使って分かりやすいコードを早く書くことの比重が高まりました。増井俊之氏はこうしたスタイルを「富豪的プログラミング」と呼び、背景をこう説明しています。
プログラマというものは、つい昔の癖で効率的なプログラムを工夫したり 資源を節約したりしようとしがちですが、ユーザインタフェースの プログラムを開発するときにはこれが裏目に出ることもあります。 というのも、ユーザインタフェースのプログラムでは 機械の効率よりも使い勝手が優先されるべきですし、 プロトタイプの作成とその評価/改良のサイクルを 数多く繰り返す必要があるのですが、 計算機資源を節約しようとすると これらの条件が後回しになりがちだからです。
(富豪的プログラミング)
2006年にS3やEC2がサービスイン、2011年にはオバマ政権下で米国のクラウドファースト宣言とNISTによる定義が発行され、クラウドコンピューティングの時代が到来します。圧倒的に計算機資源の調達とスケールアウトが容易な環境が提供され、それがコモディティ化し、相対的にリソース効率よりもコードの簡明さの重要性が高まります。クラウドコンピューティングの世界は、同時に多様な機能がブラックボックスのままAPIで提供されるプラットフォームの時代です。例えば急速に知名度を上げた音声チャットサービスのClubhouseは、音声チャットのプラットフォームを提供するagora.ioのAPIを使って1週間で書かれたといいます。
It’s called Agora (https://agora.io/en/) and it just went public last week. Clubhouse was actually built on it in about a week..
(Justin Caldbeck, 2020年6月29日10:42)
コードは、ひとまとまりの機能が1コールのAPIで提供されるようになると、より簡潔で明瞭に書けるものになっていきます。これはクラウドコンピューティングが富豪的プログラミングをどれほど協力にしているかという一つの典型例だと思います。もはやすべてが富豪プログラミングへ、1秒に収めるためにミリ秒を削るようなプログラミングはこういうコンテストだけに残る過去のものに……
倹約的プログラミングとクラウドコンピューティング
……はならなかったですね。現在、クラウドコンピューティングでは課金単位がどんどん小さくなっています。これはこうした「貧乏性のプログラミング」改め「倹約的プログラミング」がふたたび広く価値を持ち始めていることを意味します。
2017年には、Amazon EC2の課金単位が分単位から秒単位になりました。それまでは、例えばバッチ処理は1分以内に終わるのであれば、5秒でも30秒でも60秒でもコストは同じでした。しかしこの日から、5秒で終わるバッチ処理のコストは60秒かかるものの1/12になりました。月次会計バッチであれば月に一度しか実行しないので気ならないかもしれませんが、5分毎に実行される最新サマリの生成処理だとしたら月に8,640回ほど実行されるので、累積額が目に見えて変わりそうです。
昨年末には、AWS Lambdaの課金単位が100ms単位から1ms単位になりました。今回のコンテストはLambdaに載せられることもありそうな一連のデータセットを処理するものですが、投稿結果を見ると、私たちは900ms〜20msの範囲で計測単位である10msを争っています。ある課題では、私のコードは180msで処理を終えましたが、1人だけ110msと私を上回っている人がいました。昨年までは10ms単位の差、100ms以下の処理時間短縮は無意味でした。しかしこのアップデートで、彼と私のコードには39%のコスト優劣が生まれました(彼のコードの方がコストに優れています)。
もちろん富豪的プログラミングとクラウドコンピューティングの組み合わせは、極めて高いアジリティ(敏捷性)を与えます。それは素早い試行錯誤を可能にするので、問題解決のフレキシビリティ(柔軟性)を与えると言ってもいいかもしれません。一方で一度固まった処理を運用し続けていくとなった場合、倹約的プログラミングとクラウドコンピューティングの組み合わせは、極めて高い効率性を与えます。処理能力の面でも、コストの面でもです。倹約的プログラミングは、ふたたび富豪的プログラミングと合わさって一対の車輪を成す関係を取り戻しつつある、と感じます。
クラウド時代のプログラミングスキル
「NISTによるクラウドコンピューティングの定義」ではRapid elasticity(スピーディな拡張性)とMeasured Service(サービスが計測可能であること)を5つの基本特性に数えています。
クラウドコンピューティングというIT利用モデルは、まずRapid Elasticityという特性で、必要な時に必要なだけリソースを調達するという富豪的プログラミングと親和性の高い環境を提供しました。しかしMeasured Serviceという特性と、その計測単位(≒課金単位)をより小さく高精度にしてきたことで、いまや倹約的プログラミングにも光を当てています。クラウド上での巨大な並列化(スケールアウト)を前提に、10kアクセスを捌きやビッグデータの大量処理を行うなら、一回ごとの処理量を小さくすることでチリも膨大に積もって山を成すわけです。
大切なのは、クラウドコンピューティングには富豪的プログラミングを活かす面も倹約的プログラミングを活かす面もあって、それはRapid elasticityとMeasured Serviceというクラウドの基本特性に根差した本質的なものだということです。きっと一週間でClubhouseを開発できるピーキーな富豪的プログラミング能力も、競技プログラミングで10msや1msを競うピーキーな倹約的プログラミング能力も、両方がこれからも本質的に求められていく能力なのだと思います。
(追記1)
「5秒で終わるバッチ処理のコストは60秒かかるものの1/12」の箇所、初期は「1/20」と記述していました。Facebookでご指摘いただき、修正いたしました。ありがとうございました。
(追記2)
社内SNSで「こういうことですね」と下記記事をご紹介いただきました。まさにこういうことで、10msとか1msに短縮することがコストに関わるという話です。ありがとうございます。
2020年12月から課金の時間単位が1ミリ秒に変わり、余分な課金が抑えられるようになった。従来の課金は100ミリ秒単位で、端数の処理時間は切り上げられた。ナビタイムの小泉亮輔インフラエンジニア グループマネージャーは「当社のLambda利用は数ミリ秒の処理が多いので、コストが5分の1から10分の1に減った」と話す。
(サーバーレス「AWS Lambda」のコストが9割減も、新課金ルールが生きる使い方 | 日経クロステック, 2021.02.08)