クラウドとインフラ

64ビットLinuxで32ビットポインタを使用するとメモリ使用量が25パーセント削減

x32 ABIにより、アプリケーションは64ビットレジスタを維持しながら32ビットポインタを使用でき、速度を犠牲にすることなくRAM使用量を大幅に削減できます。

64-bit boardに収まる小さな32-bit chipと、縮む紙の山。
この記事用に生成されたイラスト

英語の原文から自動翻訳されました。

ソフトウェアエンジニアのAlex Alejandre氏は最近、Janetプログラミング言語をLinux x32 Application Binary Interface (ABI)でコンパイルすると、メモリ消費量が約21パーセント減少することを実証しました。この最適化は64ビットシステム上で32-bit pointersを活用し、ヒープオブジェクトのメモリフットプリントを縮小しつつ、同等の実行速度を維持します。この発見は、Linux上で動作するスクリプト、ユーティリティ、デーモンにおけるより効率的なリソース使用への現実的な道筋を示唆しています。

何が起きたか

Alejandre氏は、軽量設計で知られる動的プログラミング言語であるJanetに対し、-mx32コンパイラフラグの影響をテストしました。標準的な64ビットモードでは、Janetは「nanboxing」を用いて値を8バイトに詰め込み、すでにメモリ使用量を最適化しています。しかし、x32 ABIへ切り替えることで、オブジェクトヘッダとポインタが小さくなるため、さらなる削減効果が得られました。テストでは8パーセントから32パーセントのメモリ削減が確認され、平均で21パーセントの節約となりました。パフォーマンスは安定しており、ネイティブ64-bit buildと比較して13パーセント遅い場合から10パーセント速い場合まで幅がありました。

対照的に、従来の32-bit compilation flag (-x32) を使用すると、顕著なペナルティが発生し、速度は半分になりました。これはx32 ABIの独自の利点を浮き彫りにします。すなわち、x32 ABIはx86-64の広い汎用レジスタと命令セットを保持しながら、より小さいポインタを使用するのです。Alejandre氏は、このアプローチがポインタを多用するヒープにおいて特に効果的であり、ポインタサイズの縮小が直接的にメモリ圧力の低減とキャッシュ利用率の向上につながると指摘しました。

実験ではまた、Janetの現在のメモリ管理における制限も明らかになりました。Janetのヒープオブジェクトは現在、ガベージコレクタを支援するために16バイトを使用しており、これにはフラグ、パディング、リンクポインタが含まれます。x32 ABIは役立ちますが、より深い最適化にはアロケータまたはガベージコレクション戦略の変更が必要です。Alejandre氏は、glibcのmallocはオーバーヘッドを追加し、割り当てを16バイトの倍数に丸めるため、structなどの特定のデータ構造では潜在的な節約が制限されると述べました。しかし、テーブルや特定のタプルは依然として縮小されたポインタサイズから恩恵を受けます。

仕組み

x32 ABIは、プログラムが64-bit modeで実行されながら32-bit pointersを使用できるようにするLinux固有の機能です。通常、64ビットシステムは8-byte pointersを使用しますが、4ギガバイトを超えないデータのアドレス指定を行う場合、メモリを無駄にする可能性があります。4-byte pointersへ切り替えることで、参照を含むすべてのデータ構造のサイズが縮小されます。この縮小により、より多くのデータがCPU cacheに収まるようになり、アドレス空間が小さくなったにもかかわらず、パフォーマンスが向上する可能性があります。

この機能を使用するには、Linux kernelをCONFIG_X86_X32_ABI付きでコンパイルする必要があり、これにより必要なsyscall entry pointsが提供されます。その後、コンパイラは-mx32フラグを通じてこの機能を公開します。純粋な32-bit modeとは異なり、x32は完全なセットの64-bit registersとinstructionsを保持するため、レガシーな32-bit executionに伴うパフォーマンスボトルネックを回避します。これにより、プロセスあたり4 GB以上のメモリをアドレス指定する必要のないサーバーやデスクトップアプリケーションにとって魅力的な選択肢となります。

主要な詳細

  • -mx32フラグにより、JanetのRAM使用量は平均21パーセント削減され、結果は8パーセントから32パーセントの範囲でした。
  • 実行速度はネイティブ64-bit buildsと比較して同等であり、13パーセント遅い場合から10パーセント速い場合まで変動しました。
  • 従来の32-bit compilation (-x32) は50パーセントのパフォーマンス低下を引き起こし、性能重視のタスクには不適切であることを示しました。
  • x32 ABIにはCONFIG_X86_X32_ABIによるLinux kernelサポートが必要であり、DebianやArch Linuxなどのディストリビューションではデフォルトで無効になっています。
  • メモリの節約は、多数の小さなオブジェクトを管理するアプリケーションなど、ポインタを多用するヒープを持つアプリケーションで最も顕著です。
  • Glibcのmallocオーバーヘッドと16-byte alignment要件により、structなどの特定のデータ構造では一部の潜在的な節約が制限されます。

なぜ重要か

インフラストラクチャ、スクリプト、長時間稼働するデーモンを開発しているエンジニアにとって、メモリ効率性はコストとスケーラビリティに直接影響します。RAM使用量の21パーセント削減により、同じハードウェアでより多くのインスタンスを実行できるか、過剰プロビジョニングの必要性が低減されます。これはメモリ制限が厳格なコンテナ化環境で特に重要です。x32 ABIは、コードを書き換えたりアルゴリズムを変更したりせず、単にコンパイルフラグを調整することでこれらの節約を実現する方法を提供します。

x32の未活用は、Linuxエコシステムにとっての機会損失を表しています。ほとんどのソフトウェアはx32用に問題なくコンパイルできますが、プリビルドパッケージがないため、開発者は依存関係を自分でコンパイルする必要があります。この障壁は、多くのワークロードでメリットが明確であるにもかかわらず、採用を妨げています。主要なディストリビューションがデフォルトでx32サポートを有効にすれば、サーバー全体で広範な効率性の向上をもたらし、エネルギー消費量とハードウェア要件を削減できる可能性があります。

あなたができること

  • カーネル設定でCONFIG_X86_X32_ABIを確認して、お使いのLinux kernelがx32をサポートしているかどうかチェックしてください。
  • 小さなユーティリティやデーモンを-mx32フラグを使用してコンパイルし、メモリとパフォーマンスへの影響を測定してみてください。
  • お使いのディストリビューションがx32ライブラリを提供しているか、あるいは依存関係を手動でクロスコンパイルする必要があるかを調査してください。
  • ポインタを多用するアプリケーションをプロファイリングし、縮小されたポインタサイズから最も恩恵を受ける候補を特定してください。
  • mimallocなどの高速なアロケータをx32と併用して、パフォーマンスの向上を最大化することを検討してください。
  • よく使われるツールのプリビルドパッケージを要求することで、お好みのLinuxディストリビューションでのx32サポート改善を提唱してください。

Bytechapストアのツール

続きを読む

クラウドとインフラ

Kubernetes の inode 枯渇:なぜディスク容量のアラートは本当の脅威を見逃すのか

kubelet には inode 枯渇に対する早期警告機能がなく、ディスク容量に余裕があるように見えても突然 Pod が退避されることがあります。コンテナイメージ内の小さなファイルがどのようにこのサイレント障害を引き起こすのかを学びましょう。

すべての記事