HN 日本語サマリー

← 一覧へ戻る
その他

Stalwart v1.0: 地球上で最速のメールサーバー

Stalwart v1.0: The Fastest Mail Server on the Planet (stalw.art)

34 pointsby StalwartLabs11 コメント

要約

Stalwartは、5年間の開発を経て、初の安定版リリースであるv1.0を発表しました。このリリースは、パフォーマンスの向上とデータ安定性の確立に焦点を当てており、SIMDやSWARを活用したパーサーの書き直し、データベースへのアクセス最適化、新しい検索エンジンの導入により、PostfixやDovecotといった主要なメールサーバーと比較して、多くのベンチマークで大幅な速度向上を達成しています。また、ドキュメント内の検索機能やポスト量子DKIM2などの新機能も追加されています。

全文翻訳

Stalwart v1.0: The Fastest Mail Server on the Planet

2026年10月26日 - 16分読書

5年前、2021年10月3日、最初のコミットがmail-parserという小さなリポジトリに格納されました。それはRustで書かれたメール解析ライブラリであり、それ以上のものはありませんでした。その後5年間で、JMAP、IMAP、POP3、SMTP、CalDAV、CardDAV、WebDAV、スパムフィルター、クラスタリング、および半ダースのストレージバックエンドのサポートを備えた、完全なメールおよびコラボレーションサーバーに成長しました。本日、5年間の継続的な開発を経て、私たちはStalwart v1.0、最初の安定版リリースを発表できることを誇りに思います。

バージョン1.0は、単なる機能リリースではありませんでした。2つの目標がありました。1つ目はパフォーマンスです。サーバーのすべての部分を可能な限り高速にし、数値でそれを証明することです。2つ目はデータ自体の安定性です。データベーススキーマを最終化し、今後Stalwartのアップグレードは、以前のリリースで必要とされた破壊的なマイグレーションなしに、新しいバージョンをインストールするだけで済むようにすることです。その過程で、PDFおよびOfficeドキュメント内のフルテキスト検索を含む、いくつかの新機能も追加されました。

詳しく見ていきましょう。

マイクロ秒を追いかけた数ヶ月

「マイクロ秒を追いかけた数ヶ月」というタイトルのセクション

このリリースでの作業のほとんどは、プロファイラーの下で行われました。数ヶ月間、StalwartがCPUサイクル、メモリ、データベースへの往復をどこで費やしているかを測定し、目立った部分を書き換え、再度測定しました。このリリースには1,300ファイル以上にわたる約200のコミットが含まれており、その大部分は何かをより速く、またはより軽量にするためのものです。

SIMDとSWARで書き直されたパーサー

「SIMDとSWARで書き直されたパーサー」というタイトルのセクション

メールサーバーは、特定のバイトを探すのにかなりの時間を費やします。ヘッダー行の終わり、MIME境界、引用符付き印刷体の本文中の等号、IMAPタグを終了するスペースなどです。1バイトずつ行うと、10MBのメッセージでは多くのループ反復が発生します。2つの技術により、CPUは一度に多くのバイトでこの作業を行うことができます。

  • SIMD(Single Instruction, Multiple Data)は、最新プロセッサのワイドベクトルレジスタ(x86-64のSSE2、SSSE3、AVX2、ARMのNEON)を使用して、単一の命令で16または32バイトを比較または変換します。
  • SWAR(SIMD Within A Register)は、通常の64ビット整数で同じアイデアを適用します。注意深く選択されたいくつかの算術演算とビット演算により、一度に8バイトすべてをテストします。特別な命令を必要としないため、すべてのCPUで動作します。

Stalwartは現在、両方を、重要な場所すべてで使用しています。スタックの最下部には、サーバーと同時に1.0に到達した2つのライブラリがあります。

  • mail-parser 1.0、Stalwartが始まったまさにそのライブラリは、ゼロから書き直されました。SIMDカーネルはMIME境界とヘッダーフィールドを特定し、SWARはヘッダー名を処理し、解析されたメッセージは少数のフラットベクトルに格納され、本文は実際に誰かが読み取るまでデコードされません。CPU固有のカーネルは実行時に選択され、すべてがプレーンスカラーリファレンスに対してファズテストされています。他のパーサーと比較して、人気のRust mailparseクレートよりも3倍、Dovecot独自のパーサーよりも9倍、libEtPan!、VMime、GMimeよりもフルパースで15〜31倍高速です。
  • encodifyは、Base64、Base32、および引用符付き印刷体用のSIMDカーネルを備えた新しいエンコーディングライブラリです。これらは、メールのほぼすべての添付ファイルと非ASCIIヘッダーを運ぶエンコーディングです。MIMEでラップされたBase64添付ファイルをデコードする速度は、AMD EPYCサーバー上の標準Rust base64クレートよりも22倍高速であり、引用符付き印刷体のデコードはquoted_printableクレートよりも9倍高速です。現在、サーバー内のすべてのBase64、引用符付き印刷体、およびIMAP UTF-7変換を処理しています。

それらの上に、プロトコルレイヤーも同様の処理を受けました。IMAPコマンドパーサーはテーブル駆動になり、文字ごとのステートマシンをステップ実行するのではなく、バイトの連続全体をスキャンします。SMTPコマンドパーサー、JMAPの背後にあるJSONパーサー、スパムフィルターのトークナイザー、HTMLからテキストへのコンバーター、可変長整数コーデック、およびログシリアライザーはすべてSWARスキャンを使用しています。管理者がルーティングとフィルタリングの決定に使用する式言語でさえ、一般的な比較のための特殊化された命令を持つコンパクトなバイトコードにコンパイルされ、リサイクルされたメモリアリーナで評価されます。

より少なく、より速いデータベースへの移動

「より少なく、より速いデータベースへの移動」というタイトルのセクション

高速な解析は、各リクエストがデータベースを待つ場合は無駄になるため、ストレージとのStalwartの対話方法にも同じ時間を費やしました。IDは、それらを使用する書き込みトランザクション内で割り当てられるようになり、各メッセージ配信からの往復がすべて削除されました。キーワードの追加や検索インデックスへの追加などの読み取り-変更-書き込み更新は、バックエンド内でマージ操作として実行されます。格納されるオブジェクトは、メール、カレンダー、連絡先データに特化してトレーニングされた辞書を使用してzstdで圧縮されます。

各バックエンドも個別にチューニングされました。

  • RocksDB: すべての種類のデータは、アクセス方法に合わせて設定されたカラムファミリーに格納されます。ポイントルックアップ用のブルームフィルター、スキャン用の大きなブロック、および変化の多いデータに合わせてチューニングされたコンパクションが含まれます。ホットカウンター(キューのクォータなど)は、書き込み競合を回避するために最大256スロットに分散されます。
  • PostgreSQLおよびMySQL: 事前生成およびキャッシュされた準備済みステートメント、チャンク化されたイテレーション(自動再試行付き)、および書き込みあたりの往復回数の削減。
  • FoundationDB: トランザクションが必要とする読み取りは、並列ウィンドウでプリフェッチされ、大きな値はチャンクで組み立てられます。
  • SQLite: メールワークロードに合わせてチューニングされたページサイズ、キャッシュ、メモリマッピング、およびWAL設定。

ストレージレイヤーの上には、再設計されたキャッシュサブシステムがあります。各アカウントのメッセージインデックスは、コンパクトなパック形式でメモリに保持され、IMAPソート、スレッド、フラグフェッチ、メッセージプロパティの検索、および再同期は、データベースの読み取りがほとんどまたはまったく行われないキャッシュから応答されるようになりました。非常に大きなアカウントには独自のキャッシュティアとメモリ予算があり、キャッシュスナップショットは再構築される代わりにローカルディスク、Redis、またはブロブストアにスワップアウトできます。

新しい検索エンジン

「新しい検索エンジン」というタイトルのセクション

組み込みのフルテキスト検索エンジンは、ゼロから書き直されました。以前の設計では、単語ごとに1つのビットマップを格納し、単語の位置を認識していませんでした。新しいエンジンは、65,536ドキュメントのブロックに投稿を格納し、各メッセージの単語位置を保持します。これにより、実際のフレーズ検索が可能になり、1つのメールボックス内の検索では、そのメールボックスが触れるブロックのみが読み取られます。単語のステミングとプレフィックスをインデックス化し、zstdでデータを圧縮し、同時実行制御、再試行、および再構築を備えたバックグラウンドキューを介して新しいメールをインデックス化します。PostgreSQLおよびMySQLの検索バックエンドも再構築されました。250,000メッセージのメールボックスでは、すべてのメッセージ本文のフルテキスト検索が4ミリ秒未満で完了します。

数百のvCPUでストレステスト

「数百のvCPUでストレステスト」というタイトルのセクション

現実的な負荷で測定せずにコードを最適化することは推測に過ぎないため、このリリースに合わせて専用のベンチマークおよびストレステストラボを構築しました。これはMicrosoft Azure上で、30以上のリージョンにまたがり、最大18の完全なテストラボが並列で実行され、数百のvCPUが同時に稼働しています。

テストカタログは35種類のテストをカバーし、550以上の個別のテストセルに分散されており、以下をカバーしています。

  • すべての主要プロトコル:IMAP、JMAP(EventSourceおよびWebSocket経由のプッシュを含む)、SMTPインバウンド、サブミッションおよびリレー、CalDAV、CardDAV、WebDAV。
  • PostgreSQL、FoundationDB、RocksDBをデータストアとして、Redisをインメモリストアとして、S3およびファイルシステムをブロブストアとして、および混合負荷下での3ノードクラスタ。
  • 大規模データセット:500アカウントにわたる160万メッセージと75万件のカレンダーおよび連絡先アイテム、500万メッセージの個々のメールボックス、単一サーバー上の100,000アカウント、1000万メッセージのメールキュー、および100万レポートのDMARCおよびTLSレポートの洪水。
  • ストームと不正利用:毎秒20,000件の新規接続、大量ログイン、アカウントあたりの数千のIDLEおよびプッシュサブスクライバー、悪意のあるおよびフォーマットされていないメッセージ、slow-lorisクライアント、および巨大なリテラル。
  • 6時間のソーキングテスト:メモリの増加、キャッシュのドリフト、および遅いリークを探し、MTAを介して1000万件以上のメッセージを処理したテストも含まれます。

実行は全体を通してプロファイルされました。CPU時間はperfでサンプリングされ、フレイムグラフに変換されました。オフCPU分析は、スレッドがロックとI/Oで待機している場所を示しました。ヒープはjemallocとheaptrackでプロファイルされ、特別なインストルメントビルドはコマンドごとにすべてのストレージ往復をカウントしたため、どのリクエストがデータベースにヒットしすぎているかを正確に確認できました。各修正は、受け入れられる前に、一致するマシンで前のビルドに対して測定されました。

このサイクルの最初の完全なラウンドで64の問題が見つかり、修正され再テストされました。2番目のラウンドで全体が再実行され、さらに33の問題が修正されました。ラボが発見した例の一部:

  • 500万メッセージのメールボックスを再オープンするのに61ミリ秒から0.21ミリ秒に短縮。
  • 500万メッセージのアカウントでのJMAPクエリが3.3秒から12ミリ秒に短縮。
  • RocksDBでのピークインバウンドメールスループットがほぼ倍増、9,690から18,394メッセージ/秒に。
  • プロセスが実際のヒープが0.4GB未満であるにもかかわらず最大9.6GBを保持していたメモリ問題が見つかり、修正されました。6時間のソーキングテストでは、メモリはフラットなままです。

このラボは、リリースのための一回限りの努力ではありません。これは現在、Stalwartが内部的にテストされる方法の一部となっています。将来のすべてのリリースは、出荷前に同じベンチマークおよびストレステストラウンドを経由するため、パフォーマンスの向上は維持されます。

PostfixとDovecotよりも高速

「PostfixとDovecotよりも高速」というタイトルのセクション

内部の数値は、Stalwartが以前より速くなったかどうかしか教えてくれません。また、世界で最も広く展開されているものと比較してどうかも知りたいと思いました。そこで、Stalwart v1.0を、最も広く展開されているオープンソースメールスタックであるPostfix 3.11(SMTP用)とDovecot 2.4(IMAP用)と直接対決させました。

両方とも同じAzureサーバー(8 AMD EPYC Zen 5 vCPU、32 GiB RAM、ローカルNVMeストレージ)で実行され、同じ1,000のメールボックスと3つの非常に大きなメールボックス(最大250,000メッセージ)がロードされ、まったく同じ作業を受けました。メールの受信、配信、およびIMAPクライアントへの提供です。暗号化、パスワードハッシュ、フルテキスト検索は両方で同じように構成され、2つのシステムは同じハードウェアで交互に測定されました。

Stalwartは、38の主要な比較のうち35でより高速でした。

[画像: StalwartまたはPostfix/Dovecotがテストごとにどれだけ高速か、ログスケールで表示]

いくつかの結果:

  • IMAP: Stalwartは15の日常的なクライアント操作のうち14でDovecotよりも高速で、1.4倍から19倍です。フルTLSハンドシェイクを伴うログインは28ミリ秒ではなく5.1ミリ秒かかります。1MBのメッセージのフェッチは6倍高速、INBOXのスレッド化は5倍高速、100メッセージの移動または削除は18〜19倍高速です。
  • SMTP: StalwartはPostfixよりも3.6〜12倍高速にメッセージを受け入れ、Postfixの723に対して毎秒5,445件のインバウンドメッセージを維持します。
  • 配信: メッセージはIMAPクライアントに16倍早く表示され、IDLEで待機しているクライアントは半秒ではなく3.3ミリ秒で通知されます。
  • 負荷: Stalwartは、遅くなる前に、毎秒5.4倍多い同時IMAPセッションを提供し、3.8倍多いメールをリレーします。

メールボックスのサイズが大きくなるにつれて、ギャップは拡大します。250,000メッセージのメールボックスでは、すべてのメッセージ本文のフルテキスト検索はStalwartでは3.75ミリ秒、Dovecotでは136ミリ秒かかります。また、25,000メッセージの移動または削除は、24〜34秒ではなく約10分の1秒で完了します。これは200倍以上高速です。

[画像: 250,000メッセージのメールボックスでの典型的なレイテンシ、Stalwart対Dovecot]

Dovecotが勝った3つのテストはすべて同じ操作です。メールボックス内のすべてのメッセージを一度に既読としてマークすることです。

PostfixとDovecotのみがテストされましたが、これらは単なる2つの製品ではありません。これらは、ほぼすべての人気のあるセルフホスト型メールサーバーのエンジンです。GitHubで10,000スター以上のすべてのオープンソースDocker化メールサーバー(docker-mailserverやmailcowを含む)は、内部でPostfixとDovecotを実行しており、Mail-in-a-Boxも同様です。ほとんどすべてのベンチマークでこの組み合わせに勝つということは、インターネット上のセルフホスト型メールの大部分の背後にあるスタックに勝つことを意味します。私たちは今、それを率直に言うことに自信を持っています:Stalwartは地球上で最速のメールサーバーです。

私たちの言葉を鵜呑みにしないでください。すべてのスクリプト、設定、テストシナリオ、および生のデータはベンチマークリポジトリにあり、方法論と注意点(2つのシステム間のディスク同期動作の違いなど)の率直なリストとともに提供されています。Azureアカウントを持つ人は誰でも同じサーバーをプロビジョニングして、スイート全体を実行できます。Stalwartのさまざまなストレージバックエンドとクラスタリング設定のベンチマークも、同じリポジトリで準備中です。

パフォーマンスがヘッドラインでしたが、v1.0には新しい機能セットも含まれています。

  • ドキュメント内の検索: Stalwartは現在、PDF、Microsoft Office(docx、xlsx、pptx)、OpenDocument(odt、ods、odp)、EPUB、RTFドキュメントのテキストを抽出してインデックス化します。これらはメール添付ファイルとファイルストレージの両方に含まれます。フレーズを検索すると、メッセージ自体だけでなく、昨年のメッセージに添付された契約を見つけることができます。抽出器はRustでゼロから書かれており、外部ドキュメントライブラリを使用していません。厳格なサイズと複雑さの制限の下で各ドキュメントを処理するため、悪意のあるまたはフォーマットされていないファイルがサーバーを枯渇させることはありません。
  • ファイルストレージのフルテキスト検索、およびパーティションごとのステータス、再試行、再構築を備えたインデックスキュー。
  • メタデータ: メール、メールボックス、カレンダー、連絡先、ファイルなどに関するJMAP Object Metadata、およびIMAP METADATA(RFC 5464)。
  • ポスト量子DKIM2: DKIM2用の複合ML-DSA-44およびEd25519署名。
  • OAuthおよびOpenID Connect: OAuth Client ID Metadata Documents、メール、連絡先、カレンダー、ファイルに対するクライアントごとのスコープ、ユーザーが取り消せる接続済みアプリケーションのリスト、および外部IDプロバイダー向けのオーディエンスマッチング、不透明トークン検証、スコープなしトークンポリシー。
  • ストレージとオペレーション: シングルノードデプロイメント用の組み込みインメモリストア、Azure Blob Storage用の追加認証方法、フェイルオーバー用のセカンダリLDAPサーバー、バッファリングされたデータ用のメモリ予算、すべての送信HTTPリクエスト用のSSRF保護、および設定可能なクライアントIPソースと信頼されたプロキシホップ。
  • AIモデルとEnterprise EditionのAIスパム分類器。OpenAI互換、Anthropic、Gemini、Ollamaモデルをサポートします。

完全なリストは変更ログにあります。

v1.0へのアップグレード

「v1.0へのアップグレード」というタイトルのセクション

データベーススキーマの最終化には一度だけ支払われるコストがかかります。Stalwart v1.0は新しいデータベースレイアウトを使用し、既存のデータはそれに移行する必要があります。v1.0サーバーは以前のバージョンで作成されたストアを開きません。

過去のアップグレードが困難であったことを認識しており、それを真剣に受け止めました。このマイグレーションは、可能な限りスムーズになるように設計およびテストされ、これが最後の種類となります。スキーマは安定しており、将来のリリースはインプレースでアップグレードされます。v1.0に到達するには2つの方法があります。

マイグレーションツール

「マイグレーションツール」というタイトルのセクション

Stalwart v0.16を実行しているデプロイメントの場合、stalwart-migrateが最も簡単なルートです。v0.16.27が必要なため、それ以前の0.16リリースはまずそれに更新する必要があります。このツールは設定をv1.0スキーマに変換し、すべてのデータを新しい空のv1.0ストアにコピーします。古いストアからは読み取るだけなので、元のデプロイメントはそのまま維持され、いつでも再起動できます。

また、段階的にマイグレーションします。最初のコピーはv0.16がユーザーにサービスを提供し続ける間実行されますが、どれだけ時間がかかっても構いません。後続の各実行は、前回から変更されたもののみをコピーし、ダウンタイムはv0.16が停止された後の短い最終実行のみです。アカウントおよびメッセージID、IMAP UID、変更履歴は保持されるため、IMAPおよびJMAPクライアントは何も再ダウンロードせずに続行できます。OAuthでサインインしたユーザーは再度サインインする必要があり、フルテキストインデックスはスイッチ後にバックグラウンドで再構築されます。

マイグレーションプロキシとVandelay

「マイグレーションプロキシとVandelay」というタイトルのセクション

Stalwart v0.15以前を実行しているユーザー、またはユーザーを一度に1人ずつ移動したいユーザーの場合、マイグレーションガイドが2番目のルートを説明しています。マイグレーションプロキシは、新しいサーバーと古いサーバーの両方の前に配置され、各ユーザーをアカウントを保持している方に送信します。Vandelayは、アカウントを1つずつ段階的にコピーします。各アカウントは、マッピングテーブルのエントリを1つ変更することで切り替えられ、そのユーザーのダウンタイムはありません。古いサーバーは、廃止を決定するまで完全なコピーを保持します。同じ手順は、DovecotとPostfixからStalwartへの移行にも機能します。マイグレーション概要は、2つのアプローチを比較しています。

設定の構造はほとんど同じです。約100のキーが、一貫した命名規則に従うように名前が変更され、いくつかのオブジェクト(OIDCディレクトリ、AIモデル、Azureストレージ、転送ヘッダー)が再構築され、stalwart-migrateはそれらすべてを自動的に変換します。アップグレード前に注意が必要な変更が2つあります。

  • クラスタにはRedisが必要です。 クラスタコーディネーターは、Redisベースのインメモリストア(Redis、Redis Cluster、またはRedis Sentinel)を必要とするようになりました。以前のバージョンは、これのためにデータストアにフォールバックできましたが、負荷下では遅く、削除されました。シングルノードデプロイメントは、代わりに組み込みのローカルインメモリストアを取得します。
  • OAuthは、オープンパブリッククライアントプロファイルに従うようになりました。 Stalwartは現在、OAuth Profile for Open Public Clientsを完全に強制しています。これは、メールクライアントが事前に登録することなく、OAuthを使用して任意のメールサーバーにサインインできる、進化中の標準です。Stalwart独自の認証サーバーは、これを標準でサポートしています。多くの外部IDプロバイダーは、動的クライアント登録など、プロファイルが必要とするすべてをまだサポートしておらず、一部のクライアントは必要なスコープをまだ要求していません。

準拠していない外部IDプロバイダーを使用している場合、Stalwartのトークンチェックは、OIDCディレクトリの互換性設定を通じて緩和できますが、それぞれがセキュリティチェックを弱めるため、リスクは自己責任となります。これらの設定は主にWebUIなどのWebクライアントを機能させ続けます。それらが修正できないのは、プロファイル自体を欠いているプロバイダーであり、これはすぐに重要になります。人気のメールクライアント(Apple Mailを含む)はプロファイルを採用しており、一度採用すると、そのユーザーは非準拠プロバイダーに対して認証できなくなります。外部IDプロバイダーに依存している場合は、今すぐサポートを要求する良い時期です。

関連する変更はWebUIに影響します。固定されたクライアントIDの代わりに、クライアントを記述するURLであるClient ID Metadata Documentを使用して、IDプロバイダーに自身を識別するようになりました。一部のIDプロバイダーはまだこれをサポートしていません。それらの場合、管理者はプロバイダーでWebUIのクライアントを登録し、oauthClientIdにそのIDを設定でき、WebUIは以前と同様にサインインします。詳細はWebUIのクライアントIDにあります。

私たちはここにいます

「私たちはここにいます」というタイトルのセクション

マイグレーション中に問題が発生したり、質問がある場合は、support.stalw.artに投稿してください。マイグレーション期間中は毎日、そこで質問に回答します。

5年前、これはメールを解析するための1つのRustライブラリでした。今日、それは完全なメールおよびコラボレーションサーバーであり、v1.0では、測定した他のどのサーバーよりも高速です。コミュニティなしでは何も起こりませんでした。問題点を報告した人、パッチを送った人、フォーラムで質問に答えた人、またはStalwartにメールを託した人、すべての人に感謝します。

Stalwart v1.0をダウンロードして、ご意見をお聞かせください。