LINEのストレージ効率化を支えるJPEG↔HEIF変換プロジェクト「Antman」開発記

はじめに

最近、ユーザーが作成したメディアを保存するためのクラウドサービスがかなり人気を集めています。Google フォトやNAVER nCloudなどのサービスがその例です。LINEでも、ユーザーの写真をサーバーに永久保存していつでも閲覧できるようにしたアルバム機能を提供しています。LINEのアルバム機能は、2013年9月にオープンして今年で6年を迎えます。たくさんのユーザーが活発に利用しているため、サーバーに蓄積されるデータ量も膨大になっています。

写真や動画などのLINEのメディアデータは、すべてLINEのメディアプラットフォームが運営するメディアストレージ「OBS(Object Storage)」で管理しています。OBSは、LINEとLINEファミリーサービスで使うメディアデータを管理しており、計100PB(PetaByte:ペタバイト)くらいのストレージを使用しています。そのうち約30PBを占めているのが、このLINEのアルバム機能なのです。すべてのデータをサーバーに保存しなければならないので、ストレージサーバーの費用だけでも無視できないくらい高い費用がかかっています。

費用もそうですが、一番大きな問題はデータセンターのサーバーラック(サーバーのレンタルスペース)です。サービスの活性化は確かに嬉しいことです。ただ、永久保存ポリシーを採用しているサービスや機能は、初期段階からすべてのデータをサーバーに保存しなければならず、その限界はいつか訪れてしまいます。例えば、人口が増加し続けた結果、住宅が足りなくなってしまうような状況ですね。

最初のストレージ効率化戦略

実は、かなり前からLINEのアルバム機能で急増するデータを懸念しており、一回改善作業を実施したことがありました。OBSは、ユーザーがアルバムデータを消費するパターンを分析し、long-tailになっているという結論を得ました。

ユーザーは、新規でアップロードされた写真は頻繁に閲覧しますが、古い写真はなかなか閲覧していないことが分かりました。結果的に、古い写真はあまり閲覧されることもないまま、ストレージスペースを占有していたのです。でも、だからといってユーザーのデータを任意に削除することはできません。

そのため、OBSはストレージを効率的に使用するための戦略として、アップロード時期によってデータを保存するスペースを分けることにしました。比較的リクエストが多い新規データは高性能SSDが搭載されたサーバーに格納し、アップロード後に一定の期間が過ぎれば低性能・高容量のSATAが搭載されたサーバー、つまり高集積ストレージに移すという戦略を導入しました。私たちは、このストレージ使い分け戦略を「ストレージレイヤリング」と呼んでいます。OBSで使用するストレージのほとんどは安定性のために3つのコピーを保持しますが、高集積ストレージは2つだけを保持します。このストレージレイヤリングを利用して、データセンターのスペースが足りなくなる問題をある程度解消することができました。

しかし、ストレージレイヤリングも、データをもう少し効率よく格納するだけの対策に過ぎませんでした。時間が経つと、LINEのアルバム機能は再びデータセンターのサーバースペースの限界に迫ってきたのです。結局、もっと効果的な解決策が必要と判断し、「Antman」を開発することになりました。

HEIFの導入

Antmanの役割はとても簡単です。あまり閲覧されていない高集積ストレージのJPEGファイルを、「コールド(cold)ストレージ」と呼ばれるHEIF(High Efficiency Image File Format)ファイルに差し替えることが、Antmanの役割です。HEIFは、JPEGより圧縮率が2倍ほど高い画像フォーマットです。理解を深めるために、JPEGとHEIFについてまず簡単に紹介します。

JPEG(Joint Picture Expert Group)は、1994年に初めて公開され、現在も一番汎用的に使われている画像フォーマットです。私たちが使用している動画コーデックのほとんどがJPEGのアルゴリズムを少し改善した方式を利用しているので、JPEGは動画圧縮方式の「元祖」であるともいえます。また、汎用的に使われている画像フォーマットであるため、ほとんどのモバイルプロセッサにハードウェアJPEGコーデックが搭載されており、ほとんどのソフトウェアコーデックも非常にうまく最適化されています。しかし、残念ながら、すでに公開から25年も経っていて、現在ではJPEGより遥かに優れた性能を持つ画像フォーマットが相次いで登場しています。その一つが、HEIF(High-Efficiency Image File Format)です。

HEIFは、2013年に初めて公開されたHEVC(a.k.a H.265)ベースの画像フォーマットです。HEVCは、最近注目されている動画コーデックの一つです。動画の特性にもよりますが、前作のH.264より圧縮率が2倍くらい高いことが知られています。HEIFは画像データを格納するコンテナであり、実際の動画データはHEVCで圧縮されています。静止画はHEVCのキーフレーム(Key-frame)一枚で構成でき、アニメーションはHEVC動画圧縮と同様に処理できます。透明度を調整するためのアルファチャネルもサポートしているので、現在使用されているほとんどの画像フォーマットに取って代わることができます。さらにHEIFは、既存のJPEGがサポートしているメタデータをそのまま含めることもできます。JPEGで一番多く使われるメタデータであるExifXMPも、HEIFで公式にサポートしています。以上のことから、HEIFは、LINEのアルバム機能に蓄積されているJPEG画像をより効率よく格納するための最適な画像フォーマットであるといえます。

GPUの導入

HEVCは高効率である分、演算量もかなり多くなります。実装によって異なりますが、JPEGコーデックの数百倍以上の演算が必要となります。Antmanの開発を始めた当時、アルバムストレージにはすでに20PB以上のJPEGファイルがありました。これらのファイルを短期間で全部HEIFに変換するためには、数多くのサーバーを用意しなければなりません。でも、この問題の解決策は思ったより簡単に見つけることができました。 それは、「ドメイン(目的)に適した設備を導入する」ことでした。私たちはGPU搭載サーバーを検討し始めました。最近ディープラーニング技術がサービスに積極的に導入されるようになったことで、GPUサーバーはディープラーニング技術専用であると認識される傾向があります。しかしGPUには、ディープラーニング技術を加速するハードウェアだけでなく、様々な画像および動画ハードウェアコーデックも内蔵されています。幸いなことに、GPUがJPEG/HEVCコーデックにも対応していたため、私たちは迷わずにGPUサーバーを採用しました。

GPUコーデックインターフェースは、すべてCまたはC++言語で提供されます。そのため、私たちはJPEG↔HEIF変換を担当するCライブラリを開発し、「Pym(ピム)」と名付けました。同じ写真でもデータサイズを自由に拡大・縮小できるということから、マーベル・コミックの同名のスーパーヒーロー「Antman」の名前をプロジェクト名にしたように、JPEG↔HEIF変換を担当するコアライブラリの名前は、Antmanの能力の源である「Pym Particle(ピム粒子)」から持ってきました。Antmanは、Java SpringベースのWebサーバーとして開発され、JPEG↔HEIF変換機能をAPIで提供しています。また、これらのAPIをOBSに提供します。Pymの機能をAntmanで利用するために、PymのすべてのインターフェースはJNA(Java Native Access)を使用して連携されます。Antmanは、新規で流入するJPEGの処理はもちろん、6年間蓄積された過去のJPEGの処理も行っています。GPUを導入してから高速になった処理速度に高集積ストレージが耐えられないという問題もあったため、その負荷を少しでも減らすためにデータを年度別に分散して処理しています。

現在はAntmanがサービスと安定的に連携されていますが、Antmanプロジェクトを進める途中では色々な問題がありました。そのうち、いくつかの重要な問題と解決方法をご紹介します。

HEIF未対応端末への対策

HEIFは最新の画像フォーマットなので、まだサポートしていない端末が多いのが現状です。iOSはバージョン11からHEIF(iOSで使用するHEICはHEIFと同じフォーマットで、分散処理のために少し改良されているタイプ)をサポートしており、Androidはバージョン9.0から標準でサポートしています。また、ほとんどのWindows PCもHEIFに対応していません。そのため、Antmanでは、HEIF未対応端末がダウンロードをリクエストすれば、HEIFをリアルタイムでJPEGに変換して送信します。ここで、一つ問題が出てきます。

「JPEGの圧縮率はどれくらいに設定すればいいのか?」

復元されるJPEGの画質を非常に低く設定すると、ファイルサイズが小さくなってトラフィックコストを削減できます。でも、その分画質が劣化するので、ユーザーエクスペリエンスに悪影響を与えてしまいます。逆に、あまりにも高画質に設定すると、画質は保たれますが、ファイルサイズが大きくなるので、「不要なトラフィックコスト」が発生してしまいます。

JPEGとHEIFは、いずれも損失圧縮方式の一つであり、変換する度に画質が劣化します。ネット上でよく目にする画質の悪い画像も、シェアと画面キャプチャーが何度も繰り返されて画質が劣化した結果なのです。一度くしゃくしゃに丸めた紙は、いくら丁寧に伸ばしても折り曲げられた跡が残ってしまうように、損失圧縮方式を使って一度圧縮された画像は、高画質に圧縮し直しても改善されません。つまり、損失圧縮方式を使って画質が落ちた画像を、いくら高画質設定で保存しなおしても、ファイルサイズが大きくなるだけで画質は改善されません。この無駄に大きくなったファイルサイズのことを、「不要なトラフィックコスト」と表現しています。

原本JPEGのDQT(Define Quantization Table(s))のバックアップ 

では、HEIFをJPEGに変換するときに適切なJPEGの圧縮率は、どう決めればいいでしょうか。私たちは、かなり直感的でシンプルな仮説を立てました。それは、原本JPEGの圧縮設定を保存しておき、HEIFをリアルタイムでJPEGに変換する際に利用すれば、ファイルサイズと画質の最適な組み合わせを見つけられるだろうという仮説でした。JPEGで圧縮率を決定する唯一の情報は、De-Quantization行列です。De-Quantization行列は、8×8 係数ブロック(coefficient block)にそのままマッチングされる64個の8ビットまたは16ビットの値で構成されています。 輝度(Luminance)成分と色度(Chrominance)成分を処理するときに、それぞれ違う行列を使用することもあれば、一つの行列を使用することもあります。JPEGでは、その行列がどの成分を処理するためのものかなどの情報を「DQT」というヘッダーに格納します。私たちは、変換されたHEIFのどこかにこのDQT情報をそのままバックアップすることにしました。また、HEIFからJPEGに変換するときに有効に使える情報も、一緒に格納することにしました。そのため、これらの情報を集めて「Pymヘッダー」という独自のフォーマットを開発しました。

Pymヘッダーは、3バイトの「PYM」という識別子で始まり、以下の情報を含んでいます。

  • SAR(Sample Aspect Ratio)
    • JPEGを拡張したフォーマット「JFIF(JPEG File Interchange Format)」で追加的に保存する情報です。ピクセルを1:1の正方形とみなさず、任意のアスペクト比の四角形で表示するための情報です。例えば、画像の解像度が1080×1080であると仮定してみましょう。この画像は、画面上で正方形に表示されるべきです。しかし、各ピクセルの形を定義するSARが16:9であれば、正方形の画像がアスペクト比16:9の画像で表示されます。
  • Original Image Resolution
    • 解像度はHEVCですでに定義済みなので、別途保存しておく必要はないと思うかもしれません。ただ、JPEGは1ピクセル単位で解像度を指定できるのに対し、HEVCは2ピクセル単位でしか指定できません。そのため、解像度が奇数のJPEGをHEIFに変換してからJPEGに再変換した場合、元の解像度を維持できないという問題がありました。この問題を解決するために、原本JPEGの解像度を追加的に保存しておきます。例えば、原本JPEGの解像度が1920×1079であるとすれば、変換されたHEIFの解像度は1920×1080になり、このHEIFをもう一度JPEGに変換すると1920×1080になります。つまり、原本と同じJPEGを提供するためには、原本の解像度である1920×1079を保存しておく必要があります。
  • DQT for Luma
    • 輝度(Luminance)またはJPEGの全般に使用されるDQTを保存します。JPEGのDQTマーカー(Marker)とDQTのヘッダー長(Header Legnth)を除いて、DQTのデータをそのまま記録します。上位の4ビットはDe-Quantizationテーブルの精度を表すものです。0は8ビット精度を、1は16ビット精度をそれぞれ表します。下位4ビットはDQTの固有の番号で、各画像コンポーネントが使用するDQTを指定するときに参照されます。残りは、実際のDeQuantizationテーブルが追加されます。このテーブルには計64個の値を含んでいるので、8ビット精度の場合は64バイト、16ビット精度の場合は128バイトのデータが含まれます。
  • DQT for chroma(オプション)
    • JPEGは、コンポーネント数が4個以下であれば、どの色空間(YUV、RGBなど)でも使用できます。しかし、Antmanでは、元データの色空間がYUVである場合のみ処理します。JPEGではY、U、Vのすべてのコンポーネントが一つのDQTを使用することもありますが、色差信号のU、Vについては別のDQTを使用する場合もあります。元データにU、VのためのDQTが別途存在する場合は、その情報も保存します。

こうして作成したPymヘッダーを、変換されたHEIFに追加します。HEIFは、動画でよく使われるMP4コンテナの改良版です。MP4は基本的にBOX構造を持っており、HEIFは既存のMP4に画像の格納に必要な情報を入れるいくつかのBOXを追加した形式になっています。MP4には様々なBOXタイプがありますが、そのうちBOXとBOX間のパディング(padding)として使われる「FREE」 BOXというのがあります。「FREE」 BOXは、MP4ファイルを生成する過程で流動的に変化し得るBOXのスペースを事前に確保しておくためのもので、画像自体に全く影響を与えません。私たちは、この「FREE」 BOXにPymヘッダーを追加してHEIFファイルの末尾に追加しました。こうして保存されたPymヘッダーは、HEIFをJPEGに変換する過程での抽出、JPEG圧縮の設定として使われます。

仮説の検証

私たちが立てた仮説は、HEIFをJPEGに変換する際に原本JPEGのDQTをそのまま使用すれば、ファイルサイズと画質の最適な組み合わせを見つけられるだろう、というものでした。この仮説を検証するために、一部のサンプルを対象にしてテストを実施しました。テスト方法は、以下のとおりです。

  • 比較群1 : HEIF→JPEG変換時にバックアップされたDQTをそのまま使用する。
  • 比較群2 : HEIF→JPEG変換時にバックアップされたDQT/2を使用する。
    • DQTはQuantizationステップサイズなので、その値が小さいほどファイルサイズが大きくなり、高画質の画像が得られる。

以下のグラフにおいて、青い線は比較群1と2のファイルサイズの差を表します。このグラフでは表現できませんでしたが、実は比較群1のファイルサイズは、比較群2より平均43%程度小さくなりました。赤い棒グラフは、原本と比較群1、2間の画質の差分を表します。比較群間の画質を比較するためのIQA(Image Quality Assessment)アルゴリズムとしては、SSIM(Structural Similarity)を採用しました。大体のサンプルの画質がほとんど似ていることを確認できます。いくつかのサンプルでは0.01程度のSSIMの差が出ていますが、最大値が1であることを考えればかなり低い数値です。結果的に、HEIFをJPEGに変換する際にJPEGの圧縮率を原本の圧縮率より低く設定しても、ファイルサイズが大きくなるだけで、画質は改善されないことが分かります。

ここまでの説明で、AntmanはHEIF未対応端末のためにリアルタイムのJPEG変換機能を提供しており、HEIFをJPEGに変換する際に、ファイルサイズと画質の最適な組み合わせを見つけるために原本JPEGのDQTを使用していることがわかっていただけたと思います。

JPEGからHEIFへの変換結果を確認する 

ここまで、HEIF未対応端末のためのリアルタイムJPEG変換について説明しました。あとはJPEGをHEIFに変換する部分を説明するだけですね。でも、JPEGをHEIFに変換すればすべて終わり、というわけではありません。変換後に原本JPEGを削除してこそ、ストレージ削減効果が得られるからです。しかし、原本JPEGを削除してしまうと、HEIFに問題が発生しても元に戻す方法が全くありません。そのため、変換されたHEIFが原本JPEGの品質をそのまま維持できているかをチェックする必要があります。ここでいう品質チェックとは、「これくらいならいける」というレベルではなく、「原本JPEGが持つ画質劣化までそのまま再現できているか」というレベルの確認です。データ量が多くなければ直接目視で確認することもできるでしょうが、LINEのアルバムは1秒当たり最大1,000個くらいのJPEGがアップロードされるサービスです。このような膨大な量のデータ変換を全部目で確認するのは事実上不可能ですし、ユーザーのデータなので閲覧することもできません。そのため、私たちは、「変換結果が原本の画質をそのまま維持できているか」をチェックできる技術を開発しなければなりませんでした。

変換結果に確信を持つために、原本JPEGと変換されたHEIFを比較することにしました。一般的なIQA(Image Quality Assessment)手法と同様に、原本JPEG(Original JPEG)と変換後のHEIFについてそれぞれデコードしたRAW画像を比較するというやり方です。しかし、Antmanで使用するGPUのハードウェアJPEG/HEVCコーデックの安定性を100%信頼することはできません。言い換えれば、AntmanのハードウェアHEVCエンコーダーで圧縮した画像がAntmanのハードウェアHEVCデコーダーで正常に認識されたとしても、すべてのHEVCデコーダーで正常に動作するとは確信できないということです。そのため、私たちは、GPU導入のおかげ(?)で余ったCPUリソースをリファレンスコーデックの実行に使用することにしました。一般によく使われるソフトウェアJPEG/HEVCデコーダーをCPUで実行し、その結果として得られたRAW画像も比較群に含めました。なお、変換後のHEIFと復元したJPEG(Restored JPEG)をハードウェア(GPU)およびソフトウェア(CPU)コーデックでぞれぞれデコードした画像2枚も比較群に入れました。結論を言うと、計6枚のRAW画像の比較群のうち、一番低いIQA値を基準にすることにしました。

どのIQA手法を使用するかについては、様々なやり方を試してみました。変換した後に原本JPEGを削除すると元に戻せないため、長い時間をかけて、様々な方法を試しました。

PSNR & SSIM

初めて試みた方法は、最も基礎的なIQAであるPSNR(Peak Signal to Noise Ratio)とSSIM(Structural Similarity)です。PSNRは、単純に各ピクセル値の差に基づいた古典的なIQA手法です。それとは違ってSSIMは、よりHVS(Human Visual System)を考慮したアルゴリズムだと言えます。PSNRのように単なるピクセル値の差ではなく、画像の中の小さいブロックの中で信号変化に関する相関関係がベースのIQAアルゴリズムです。2つのアルゴリズムを検討した結果、それぞれの長所と短所が見えました。Antmanの目的を踏まえると、PSNRを選択したほうがより合理的だという判断になりました。Antmanの目的は、ユーザーが変化に気づかないほど原本JPEGの画質をそのままHEIFに変換することにあります。結局、原本JPEGが持っている映像の劣化までそのままHEIFに反映されるべきです。そのため、HVSを考慮して高度化されたIQA手法は、むしろAntmanの目的に合わないという結論を出しました。そこでPSNRを選択し、相当のサンプルを利用してテストを進めていましたが、思いもよらない問題に直面しました。それは、PNSRは画像全体の平均値をとるという問題です。

以下のように、背景は全体的にシンプルで一部の領域に複雑なパターンがある画像を例に挙げます。

この2つの画像においてPSNRの差は50dB程度で、一般的な基準から見ると両画像の画質にはほとんど差がないと言えます。ビットレート(bitrate)が低くなっても、シンプルな背景では複雑な信号がないため、画質の劣化現象が滅多に発生しませんでした。しかし、赤線のボックスの中には比較的に複雑な信号が含まれており、目立つ劣化現象が発生することが分かります。結局、PSNRは平均値をとるという罠があり、局所的に発生する画質劣化を検出しにくいという結論を出しました。

Grid PSNR

局所的に発生する画質の劣化を簡単に検出するため、Grid方式のPSNRを適用してみました。

上記の図のとおり、画像を特定サイズのタイル(tile)のように分割し、個々のタイルでのPSNR(N,M)を測定した後、最も低い値を代表値として使用する方法です。Grid PSNR方式で、ある程度局所的な劣化現象を検出できましたが、様々な新しい課題が出てきました。まず、タイルのサイズによって代表するPSNRの値の変動が大きくなりました。また、もう1つの問題点は、以下のようにタイルとタイルの境目に劣化が集中している場合、劣化が2つのタイルに分散されるので検出が難しくなるということです。結局、どの画像にも対応できる絶対的なタイル構造を考えるのはなかなか難しいと判断しました。

*訳注:(a)タイルのサイズによるPSNRの変化    (b)タイル間の劣化区間の分散

Sliding-widnow PSNR

Grid PSNRの2つの問題から以下のような結論を導き出しました。

  • タイルのサイズが小さいほど局所的な劣化を検出しやすい。
  • タイルとタイルの境目の局所的な劣化を検出するために、タイルを緻密に並べる必要がある。

結果的に、以下のようなSliding-window方式のPSNRの測定を試みました。Sliding-window PSNRは、局所的な劣化区間を検出することになかなか優れた性能を見せました。コーヒーフィルターのようにきめ細やかなPSNR測定により、すべての劣化区間を検出することができました。

しかし、また別の問題が待っていました。小さいタイルを利用して1枚の画像をピクセル単位で移動しながらPSNRを取得していたら、画像1枚に膨大なPSNRの計算が必要になりました。例えば、8×8のタイルで1024×1024ピクセルの画像を対象にSliding-window PSNRを行うとしたら、計1,034,289回のPSNR計算が必要になります。移動するピクセルの単位をより大きくすると回数は減りますが、PSNRを数回計算しなければならないのは同じです。さらに、PymにおいてPSNRの計算はGPUのCUDA(Compute Unified Device Architecture)関数で処理しますが、CUDAベースの関数はローディングやリリースに多くの時間が必要です。そうなると、実際PSNRの計算にも時間がかかり、PSNRを計算する関数のローディングやリリースもそれぞれ1,034,289回必要になるので、無駄に時間がかかりすぎてしまいます。

Sliding-window MSE

私たちは、Sliding-window PSNRを少し変更してGPU上で最適化されたSliding-window MSE(Mean Squared Error)を開発しました。この手法は、現在Antmanに適用されている最終的なIQAアルゴリズムです。

PSNRの計算式を見ると、PSNRは結局MSEの対数チャート(log scale)の変換に過ぎません。つまり、PSNRに対するしきい値(threshold)があれば、それをMSEに対するしきい値に変換することができます。数回のテストを経てPSNRのしきい値を設定できたため、当該値をもとにMSEに対するしきい値も設定できました。また、Sliding-windowにより、画像の全区間にわたってMSEを求めることはとても簡単に実装できました。

まず、各比較群の画像全体から絶対差(absolute difference)を取得します。 次に、取得した値間のドット積(dot product)であるを計算すると、MSEの計算式で∑の内部項の結果と同じ結果を引き出すことができます。最後にに対し、KxKのカーネルを利用して2-D Mean filterを適用すると、Sliding-window MSEを算出できます。

圧縮率の最適化

このように画質の劣化区間を検出するアルゴリズムを開発してから、より積極的に圧縮率の向上を図ることができました。方法はとても簡単です。HEVCエンコーダーのQuality Factor(値が大きいほど画質が低くなる)を変更して、HEIFへの変換とIQAの実行のプロセスを繰り返します。また、劣化が発生しない範囲で最も高いQuality Factorを使って変換されたHEIFを最終結果として選択します。

*訳注:(図の左上から)最終選択の結果/初期のQ-Factor/(赤)画質劣化の発生/(青)画質劣化なし

このようにして決まった最終Quality Factorは、Antmanで着実に統計処理を行い、次の画像を処理する際に初期のQuality Factorとして使用することでリトライ回数を最低に抑えることができます。初期のQuality Factorから始まり、一定のステップの大きさで値を変更しながら、最適のQuality Factorを探します。このようなアプローチにより、Antmanは当初50%を目指していたストレージ削減率を60%までに引き上げることができました。

Antmanのインフラコスト=0

HEVCの膨大な演算量を解消するためにGPUを導入しました。仕様にもよりますが、サーバーで使うGPUカードの値段は普通のWebサーバーの値段に匹敵するほど非常に高価です。ストレージコストを削減してもスピーディな処理のためにGPUを大量に搭載すると、全体のインフラコストの削減効果が落ちてしまいます。そこで、しばらく空いているリソースを活用する戦略を取ることにしました。すでにOBSでは、当該プラットフォームのビデオトランスコーダー(別名Licoder)にGPUを適用したことがあります。GPUを適用してOBSはトランスコーディングに使われる莫大なインフラコストを削減することができました(これに関しては後に他のエンジニアリングブログの記事として紹介される予定です)。

LINEのサービスでは、年が明けるタイミングで普段の3倍程度のトラフィックが流入します。年末に安定的なサービスを提供するためには、急増するトラフィックに対応できる設備を備える必要があります。そのため、Licoderも普段は使用しないGPUサーバーを常に保持しなければならない状況です。もちろん、予期しなかったイベントや社会的話題でトラフィックが急増することがあり、そのときにはGPUサーバーを有効に活用できますが、依然として高価なGPUサーバーを「予備サーバー」として保持することはインフラコストの無駄でしかありません。そこで、私たちは余っているGPUサーバーをAntmanのサーバーとして使用することにしました。GPUサーバーにはLicoderのインスタンスとAntmanのインスタンスを両方とも起動しておきます。そして、Licoderのリクエスト量のモニタリングを続けてLicoderのインスタンスに余裕があると判断されると、Licoderのインスタンスはリクエストの処理を止め、Antmanのインスタンスが活性化されます。 

結局、Licoderのリクエスト量が少ない時間に遊休状態だったGPUサーバーをAntmanのサーバーとして使用することで、インフラコストの無駄を減らし、Antmanも別途インフラコストがかからなくなりました。すべてのGPUサーバーが常に忙しく回っているのを見て微笑ましくなる、というおまけも付いています。

いよいよLINEのアルバム機能に適用!

2019年上期で見ると、LINEのアルバムのストレージ使用量は毎月0.8PB程度の増加量を見せました。増加量を考慮すると、Antmanがなかった場合、2019年の年末まで9PBが増えて34PB程度のストレージを使用していることが予測できます。Antmanは2019年5月末にLINEのアルバム機能に適用され、7月末からは本格的に原本JPEGの削除を始めました。原本JPEGの削除を始めてからストレージ使用量のグラフは右肩下がりに下がりはじめ、2019年12月年末の使用量は24PB程度でした。2019年12月まで約10PB程度のストレージを削減し、今もAntmanはここ6年間のデータを処理している最中です。導入後1年になる2020年中旬ごろには、保存されているすべてのファイルの処理が終わると見込んでいます。

おわりに

同僚との飲み会であれこれ話している最中に、ぱっと思いついたアイディアが今のAntmanになりました。実は、最初計画を立てたときは、削減できるストレージコストばかり考えて勢いよく始めました。しかし、ユーザーデータを永久に変更するプロジェクトなので、気にかかることが多々ありました。サービスに初めて適用したときは、何か見過ごしたのではないかという気持ちで数か月間神経が尖って寝そびれたりしました。それでも大した問題なく、毎日減っていくストレージの使用量を見て達成感を感じ、良いアイディアが出てこないときは「酒でも飲むべきか」という冗談を交わしたりする余裕もできました。

私たちは、Antmanを皮切りにLINEの各種サービス内に通用するメディアフォーマットの高度化を続ける予定です。LINEは、様々な国や端末で提供されるサービスです。あらゆるプラットフォームがすぐ同期化されるため、展開に困難が多いのは事実です。しかし、AntmanによるHEIFの導入がこれからの発展に良い土台になることを願っています。

最後に、一緒にAntmanの開発を手掛けて同じ負担を感じたはずのBaek SeungHoonさんと、AntmanのOBSとの連携で苦労されたShin WooChulさんにも厚く御礼申し上げます。