Zmij: Faster floating point double-to-string conversion

2025/12/15 0:42

Zmij: Faster floating point double-to-string conversion

RSS: https://news.ycombinator.com/rss

要約

Japanese Translation:

要約:

著者はGitHubで新しいバイナリから10進数への浮動小数点変換ルーチンを公開しました。この実装は既存のソリューションに比べて大幅に高速です。ベンチマークでは、Dragonboxより約68 %速く、自身のSchubfach実装より2倍速いことが示され、macOS上で

sprintf
を最大59倍も速く処理します。また、Apple M1チップ上で単精度・倍精度変換はわずか10–20ナノ秒です。アルゴリズムはSchubfachを改良し、候補選択の簡素化、整数乗算・対数近似・除算/剰余計算・条件分岐の削減により効率化しています。また、Cassio Neriからアイデアを取り入れ、固定小数点演算とルックアップテーブルを用いて計算速度をさらに向上させています。今後は現在の科学的(指数)モードに続き、単純な固定小数形式も追加する予定です。高速化された変換ルーチンは、ロギングライブラリやデータシリアライズフレームワーク、性能重視のアプリケーションなど、浮動小数点数をシリアライズするすべてのソフトウェアに恩恵をもたらし、CPU使用率を下げスループットを向上させます。

要約スケルトン

本文が主に伝えようとしていること(メインメッセージ)
著者はGitHubで既存の方法より大幅に高速な新しいバイナリから10進数への浮動小数点変換ルーチンを公開しました。

証拠/根拠(これが言われている理由)
ベンチマークでは、Dragonboxより約68 %速く、自身のSchubfachコードより2倍速いこと、macOS上で

sprintf
より最大59倍速いことが示され、Apple M1上で単精度・倍精度変換が10–20ナノ秒しかかからないと報告されています。

関連ケース/背景(文脈・過去の出来事・周辺情報)
実装はSchubfachアルゴリズムをベースに、候補選択、整数乗算、対数近似、除算/剰余計算、条件分岐を削減して改良しています。またCassio Neriのアイデアも取り入れ、固定小数点演算とルックアップテーブルで計算を簡素化しています。

今後起こり得ること(将来の展開/予測)
著者は現在の科学的(指数)モードに続き、単純な固定小数形式へのサポートを追加する予定です。

この影響が及ぶ可能性のあるもの(ユーザー・企業・業界)
高速化された変換ルーチンは、ロギングライブラリやデータシリアライズフレームワーク、性能重視アプリケーションなど、浮動小数点数をシリアライズするすべてのソフトウェアに恩恵をもたらし、CPU使用率を削減しスループットを向上させます。

本文

ソフトウェアエンジニアの人生に必ず訪れる瞬間――新しいバイナリからデシマルへの浮動小数点変換手法を思いつくとき

それが私の来た時です。週末だけで書いたものですが、ほぼ完結したコードがあります: https://github.com/vitaut/zmij

Dragon4、Grisu、Schubfach を実装して得られた教訓に加え、自分と他者からの新しいアイデアを取り入れています。主な指針は Alexandrescu の「何もしないことよりも少し作業するほうがいい」という考え方で、Schubfach から条件付き分岐・計算・候補数まで削除していくことで多くの改善を実現しました。


パフォーマンス

dtoa-benchmark
上での性能は以下の通りです。

指標比較対象実際の速度差
~68 % 速いDragonbox(正しさが証明されているアルゴリズムの中では前頭に立つ)
~2× 速いSchubfach の自分実装(原論文に忠実)
~3.5× 速いlibc++ の
std::to_chars
(Ryu?)
~6.8× 速いGoogle の double‑conversion(Grisu3)
~59× 速いmacOS 上の
sprintf
(Dragon4?)

Apple M1 で単一の double を変換するだけで、10〜20 ns 程度です。


改善点は何か?

Schubfach と比較した改善一覧です。

改善項目内容
候補数を 1–3 に減らす考慮する候補が少なくなる
短いケースでの整数乗算を削減計算コストが低下
ログ近似を高速化log10(2) の近似計算をより効率的に
除算と剰余を高速化
divmod100
を最適化
条件付き分岐を減らす可能な限りブランチレスに
符号部・指数の出力を効率化桁ペア用テーブルを利用

小規模分岐の簡略化

NaN、無限大、ゼロまたはサブノーマルといった特殊ケースを一つの分岐で高速に判定。一般ケースはさらにシンプルになります。

固定小数点でのログ近似を高速化

Schubfach は 64‑bit 乗算を使いますが、入力範囲内では 32‑bit 近似でも十分です。

constexpr int log10_2_sig = 315'653;
constexpr int log10_2_exp = 20;

auto floor_log10_pow2(int e) noexcept -> int {
    return e * log10_2_sig >> log10_2_exp;
}

Dragonbox も同様に 32‑bit 近似を採用しています。

整数除算 → 乗算

inline auto divmod100(uint32_t value) noexcept -> divmod_result {
    assert(value < 10'000);
    constexpr int exp = 19;          // 19 は 12 より高速または同等(3 桁でも)
    constexpr int sig = (1 << exp) / 100 + 1;
    uint32_t div = (value * sig) >> exp;   // value / 100
    return {div, value - div * 100};
}

ブランチレスで不規則な丸め区間を処理

追加の複雑さを避け、分岐なしで処理します。

Cassio Neri の洞察

Schubfach は四つの候補数を検討しますが、Cassio からは最初の場合に上限値だけで一つの候補を構築できると示されました。これにより短いケースで二回の 64‑bit 乗算を削減できます。

丸めチェックの簡素化

従来の Schubfach:

uint64_t dec_sig_over = dec_sig_under + 1;
bool under_in = lower + bin_sig_lsb <= (dec_sig_under << 2);
bool over_in  = (dec_sig_over << 2) + bin_sig_lsb <= upper;

if (under_in != over_in) {
    return write(buffer, under_in ? dec_sig_under : dec_sig_over, dec_exp);
}

最適化版:

int64_t cmp        = int64_t(scaled_sig - ((dec_sig_under + dec_sig_over) << 1));
bool   under_closer = cmp < 0 || (cmp == 0 && (dec_sig_under & 1) == 0);
bool   under_in     = (dec_sig_under << 2) >= lower;

write(buffer,
      (under_closer & under_in) ? dec_sig_under : dec_sig_over,
      dec_exp);

符号部と指数の出力

  • 桁ペアをテーブル化して整数乗算を半分に削減。
  • 余計なゼロを除去するために別の小規模テーブルでブランチレスに処理。

新しいアルゴリズムか?

まだ確定ではありませんが、独自の GitHub プロジェクトとして価値があります。

{fmt}
で採用され、Thrift やその他 JSON シリアライゼーションでも候補です。ISO C++ の P2587 「to_string or not to_string」論文により
std::to_string
がこの手法または類似手法を使えるようになれば、標準 API はさらに高速で実用的になります。


現在の制限

  • 科学記数法(指数表記)のみ対応。固定小数点形式は簡単に追加可能です。

ちょっとした話: かつて同僚だった David Gay は Bell Labs で初期の dtoa 実装を書き、長年広く使われました。

最終更新: 2025‑12‑13

同じ日のほかのニュース

一覧に戻る →

2025/12/18 1:42

Gemini 3 Flash: Frontier intelligence built for speed

## Japanese Translation: > **概要:** > Google は、低コストで高速な AI モデル Gemini 3 Flash をリリースしました。これは Flash レベルのレイテンシーでプロ級の推論性能を提供します。Gemini アプリと Search の AI Mode では既にデフォルトエンジンとなり、Gemini 2.5 Flash は世界中で追加料金なしで即座に置き換えられます(Gemini 3 Pro が公開された直後)。ベンチマーク結果では、GPQA Diamond で 90.4 %、Humanity’s Last Exam(ツール無し)で 33.7 %、MMMU Pro で 81.2 %、SWE‑bench Verified で 78 % を獲得し、より大きなフロンティアモデルを上回ります。Gemini 3 Flash は Gemini 2.5 Pro より約30 %少ないトークン数で同等以上の性能を発揮します。価格は入力トークンあたり 0.50 USD、出力トークンあたり 3 USD(音声入力は 1 USD/百万トークン)です。JetBrains、Bridgewater Associates、Figma など多くの企業がこのモデルを活用し、コーディング、データ分析、設計ワークフローの高速化に役立てています。開発者は Gemini API(Google AI Studio)、Antigravity、Gemini CLI、Android Studio、Vertex AI、および Gemini Enterprise を通じて Gemini 3 Flash にアクセスできます。このモデルは Gemini アプリと Search 経由で全ユーザーへ展開されるほか、プレビュー API でも利用可能です。

2025/12/18 6:13

I got hacked: My Hetzner server started mining Monero

## Japanese Translation: ヘツナー VPS 上で Coolify をホストし、Next.js ベースの Umami アナリティクスを含む複数コンテナを実行していた。12 月 7 日に、Umami コンテナ内に Monero マイニングボット(`javae`/`xmrig`)が出現し、CPU スパイクが約 15 倍に増大した。著者はマイナーをコンテナに追跡し、CVE‑2025‑66478 ― Next.js の React Server Components “Flight” プロトコルにおける不安全なデシリアライゼーション(Puppeteer を介さずリモートコード実行が可能)を特定した。HTTP リクエストを巧妙に作成することで RCE が発動し、マイナーがインストールされた。ホストファイルシステムのチェック(`/tmp/.XIN-unix/javae`)ではエスケープは確認できず、コンテナは非 root の `nextjs` ユーザーとして実行され、特権モードやボリュームマウントも無いため、すべての悪意あるプロセスは名前空間内に留まった。 著者は侵害されたコンテナを停止・削除し、CPU 負荷を通常状態へ戻した。UFW をデフォルトで受信トラフィックを拒否するよう設定し、SSH、HTTP、および HTTPS のみ許可することで、オープンな PostgreSQL / RabbitMQ ポートを効果的に遮断した。ヘツナーは 2025‑12‑17 にネットワークスキャン検知後、アブズケース警告を送付し、著者が侵害と対策を説明するとともにチケットはクローズされた。 重要な教訓として、十分に隔離されているコンテナでも基盤フレームワークに脆弱性がある場合は突破可能であり、「Next.js を使っていない」状態が第三者ツールの依存関係によって偽りになるケースがあることを指摘した。この事例は、ファイアウォールルール、非 root ユーザー設定、特権モード無し、監視・ fail2ban の導入、およびタイムリーなパッチ適用という防御層の重要性を強調した。 ## 行動計画 - Umami を廃止する - すべてのコンテナに対してユーザー権限とマウントを監査する - SSH アクセスを強化し、アラートを設定する - セキュリティパッチを定期的に適用し、将来のインシデントを防止する ---

2025/12/18 3:15

How SQLite is tested

## Japanese Translation: > **SQLiteのテストインフラは網羅的で、コードベース全体にわたって完全な分岐カバレッジを実現しています。** > プロジェクトには約155.8 KSLOCのCソースがありますが、テストコードは92 M KSLOC以上――約590倍の量――で、すべての行が実行されることを保証しています。4つの独立したハーネスがカバレッジを提供します: > • **TCL**(27.2 KSLOC、1,390個のスクリプトファイル)で51,445件の異なるケースと数百万回の実行があります; > • **TH3**(1,055.4 KSLOC、約76.9 MBのバイナリ)で50,362件の異なるケース、完全カバレッジに必要な2.4 Mインスタンス、および約248.5 Mテストを実行するソークテストがあります; > • **SQL Logic Test (SLT)** はSQLiteとPostgreSQL、MySQL、MS SQL Server、Oracle 10gを比較し、7.2 Mクエリと1.12 GBのデータで検証します; > • **dbsqlfuzz**(libFuzzerベース)はSQLとデータベースファイルの両方を変異させ、約336個のシードファイルから16コアで1日あたり約500 Mテストを提供します。 > 追加の軽量ハーネスには `speedtest1.c`、`mptester.c`、`threadtest3.c`、`fuzzershell.c`、およびJSONBファズラ `jfuzz` が含まれます。 > 異常テストではメモリ不足、I/O障害、クラッシュ/電源損失、およびカスタムmalloc/VFSフックを使用した複合故障をシミュレートし、各障害後に整合性チェックが実行されます。 > ファズリングの歴史はAFL(2014‑2019)からOSS Fuzz(2016年以降)、その後dbsqlfuzz(2018年末)とjfuzz(2024年1月)へ進化しました。`fuzzcheck` スクリプトは毎回ビルド時に興味深いケースを再実行し、新しいバグが自動的にリグレッションテストとして生成されることを保証します。 > リソースリーク検出はTCL/TH3ハーネスに組み込まれており、メモリリーク、ファイルディスクリプタ枯渇、および不要なスレッドが自動的に監視されます。 > カバレッジは `gcov` を使用して100 %の分岐カバレッジと変異テストで達成され、マクロ(`ALWAYS`、`NEVER`、`testcase`)がMC/DCを強制し、コメント(`/*OPTIMIZATION‑IF‑TRUE/FALSE*/`)は偽陽性を防ぎます。 > 結果として、継続的に拡張される高い信頼性のテストスイートが実現し、ユーザーにSQLiteの安定性への確信を提供し、セキュリティ脆弱性から保護し、オープンソースデータベース品質保証のベンチマークとなります。

Zmij: Faster floating point double-to-string conversion | そっか~ニュース