コンテンツにスキップ

性能と配布サイズ

日本語analyzerを有効にすると、Go組み込みの準備は2.13msから319.7msへ伸びます。seed読込中にkuromojiを初期化するためです。server SDKにはchild processの起動が加わり、Javaではclasspath binaryの展開も待ち時間に含まれます。以下は単一マシンの観測値です。

2026-09-13、Apple M3、macOS arm64、Go 1.27.0、Python 3.14.7、Node.js 26.8.1、Java 25.0.2、OrbStack上のDocker 29.4.0で計測しました。osmemの全経路で同じ525-byte seed(2 index、3 document)を読み込みます。日本語有効ではseed内のkuromoji analyzerを初期化し、無効ではCJK fallbackを使います。

API経路 日本語 起動平均 範囲 計測区間
Go組み込み 無効 2.13ms 1.54〜2.87ms (n=10) osmem.New() + LoadSeed()。起動済みGo test processと実行ファイルlaunchは除外
Go組み込み 有効 319.7ms 312.0〜347.8ms (n=10) 同上。osmem/jaをimportして有効化
Python server SDK 無効 23.5ms 10.1〜69.4ms (n=5) OsmemServer.start()からchild起動・seed読込完了まで。Python runner起動済み
Python server SDK 有効 332.8ms 321.1〜366.8ms (n=5) 同上、日本語analyzer有効
Java server SDK 無効 435.2ms 305〜868ms (n=5) OsmemServer.start()でclasspath内binaryを展開し、child起動・seed読込完了まで
Java server SDK 有効 730.4ms 653〜797ms (n=5) 同上、日本語analyzer有効
Node.js server SDK 無効 10.8ms 10.1〜12.8ms (n=5) OsmemServer.start()からchild起動・seed読込完了まで。Node runner起動済み
Node.js server SDK 有効 325.1ms 318.6〜344.1ms (n=5) 同上、日本語analyzer有効
Docker上のOpenSearch 6.07秒 5.99〜6.31秒 (n=5) warmなopensearchproject/opensearch:2.19.0、linux/arm64。PUT /benchmark成功まで
Testcontainers Go + OpenSearch 6.26秒 5.79〜6.89秒 (n=5) Testcontainers-Go 0.44.0。毎回fresh container、image取得済み。初回Ryuk起動を含む
Devbox管理のOpenSearch 7.94秒 6.85〜10.63秒 (n=5) Devbox 0.17.5 services up -b。process-composeからdocker run、image取得済み

Python・Java・Node.jsはlanguage runtimeが起動した後に計時しており、test runnerからSDKを呼ぶ条件です。server binaryは計測前にbuild済み。Javaは起動のたびにclasspathからbinaryを一時fileへcopyし、PythonとNode.jsは配置済み実行ファイルを使います。日本語無効のJava計測には868msの外れ値も含まれます。Go組み込みはHTTP listenerを起動せず、Go test process自体の起動も含みません。container系はPUT /benchmark成功をready条件とし、seed済みosmemとは準備完了の境界が異なる参考値です。

構築済みindexを使うtestでは、個々のdocument書き込みは起動コストと別です。そこでwrite latencyではなく、seed済みの環境が使えるまでを測りました。

日本語有効で構築済みのseedを先に用意し、cloneを作る呼び出しだけを計測しました。fork側を変更しても共有baseには影響しません。document/indexのwriteとcloneのcloseは計時していません。

API経路 clone生成平均 試行
Go組み込み Cluster.Clone() 14.4µs 5 batch × 5,000 clone。seed準備は計測外
Python server.clone() 240µs 起動済みseed serverから300回
Java server.clone() 583µs 起動済みseed serverから300回
Node.js server.clone() 1.63ms 起動済みseed serverから300回

language SDKの値にはlocalhostのHTTP management requestとJSON decodeが含まれます。Go組み込みはportを開かないin-process copy-on-write forkです。closeや、その後にテストが行うindex/document変更は含めません。process schedulingによるoutlierがあるため、clone計測の詳細値は平均よりばらつきます。

経路 常駐メモリ平均 query 条件
日本語analyzer使用後のosmem server RSS 160.4MiB 同じseedで5 process。日本語match queryの後にRSS取得
Go in-process API 未計測 filter + sort + date histogram: 1.71ms。完全一致term: 33.3µs。読み取りclone + count: 270µs 1万document fixture。`go test -run ‘^$’ -bench ’Benchmark(CloneReadOnly
日本語無効のosmem HTTP query 未計測 中央値1.53ms、p95 1.84ms、p99 2.94ms match_all、size 10のrequestを500回逐次実行
Docker上のOpenSearch container RSS 942.2MiB 中央値4.45ms、p95 9.76ms、p99 19.02ms test index作成後にdocker stats。queryは別試行
Testcontainers Go + OpenSearch container 952.9MiB + runner RSS増分4.5MiB = 957.5MiB Go runnerは起動前15.3MiB、ready時19.9MiB。Docker daemonとRyukは除外
Devbox管理のOpenSearch container 947.6MiB + process-compose/Docker CLI 61.0MiB = 1,008.6MiB Docker daemonは除外

検索行ごとにindexとquery planは異なります。Go benchmarkは1万document、小さなseedを使うosmem HTTP確認、空indexを検索するOpenSearchであり、厳密なengine比較ではありません。Dockerはsingle node、heap 512MiB、security demo設定無効で測りました。hardware、heap、architecture、storage driver、image cache、readiness条件で結果は変わります。

Testcontainersはテスト側からcontainer runtimeを扱うwrapperで、検索engineではありません。JVMの大きく変動するbaselineをcontainer消費と誤認しないよう、Go版(testcontainers-go 0.44.0)で計測しました。fresh containerを5回起動し、index準備まで平均6.26秒です。Go test processはcontainer起動直前にRSS平均15.3MiB、ready時に19.9MiBで、差分4.5MiBだけをcontainerの952.9MiBに加算しました。containerとrunner増分の合計は957.5MiBです。初回はTestcontainersのRyuk helperも起動しましたが、memoryにはhelperとDocker daemonを含めません。class全体でcontainerを共有すれば、起動時間はそのclass内のtestで按分されます。

Devboxはprocess-compose経由でserviceを管理できます。公式services guidedevbox services upとbackground起動の説明があります。ここではdevbox services up -bで、同じcache済みOpenSearch imageをdocker run経由で起動しました。新規起動5回の平均はPUT /benchmark成功まで7.94秒。ready時のcontainer RSS平均947.6MiBに、常駐するprocess-composeとDocker CLIの61.0MiBを足して1,008.6MiBです。Docker daemonは除外しています。warm状態のno-op devbox run(156ms)とMaven/JDK closureの初回download(194.1MiB、展開後351.7MiB)は、server起動・server imageとは別の開発toolchain costです。

リンク後のアプリケーションバイナリとコンテナのdownload size

Section titled “リンク後のアプリケーションバイナリとコンテナのdownload size”

ライブラリのサイズは、source codeやpackage/archiveの容量ではなく、Goアプリケーションをlinkした最終実行ファイルの増分で示します。Go 1.27.0、-trimpath-ldflags=-buildid=を揃え、空のmain、osmem clusterを生成・終了するmain、さらに日本語analyzerをimportするmainの3種類をビルドしました。日本語analyzerの値は空のbaselineからの合計増分に加え、osmem単体への追加分も示します。

Go実行ファイル サイズ
最小mainのbaseline 1,815,314 bytes (1.73 MiB)
osmemをlinkした実行ファイル 25,668,722 bytes (24.48 MiB)、増分+23,853,408 bytes (+22.75 MiB)
osmem + 日本語analyzer 38,529,298 bytes (36.74 MiB)、baseline比増分+36,713,984 bytes (+35.01 MiB)。このうちanalyzerの追加分は12,860,576 bytes (12.26 MiB)

これは特定のtoolchainと最小プログラムにおけるlink結果で、packageサイズの一般的な保証値ではありません。Node.jsとPythonは別プロセスのosmem実行ファイルを使い、JavaはJVM artifactを使うため、静的にlinkしたアプリケーションバイナリ増分とは同じ条件で比較できません。

トップページでは3種類のサイズを10進MBの同じscaleで比較しています。Go appへのlink増分は36.7 MB (+35.0 MiB)、Devbox Maven/JDK環境の初回downloadは203.5 MB (194.1 MiB)、Docker Hub掲載の圧縮済みlinux/arm64 image sizeは739.3 MBです(Docker Hub)。それぞれlink済み実行ファイルの差分、一度だけ取得するtoolchain、圧縮されたserver image全体であり、対象範囲は異なります。DockerローカルのSizeは展開後の容量なのでdownload sizeの代用にはしません。layerがcache済みなら実際の転送量はこれより少なくなる場合があります。

TestcontainersとDevbox serviceも同じOpenSearch imageを使うため、別のserver binaryはlinkしません。Devboxのtoolchain downloadはserver imageとは別指標です。

repository rootで実行します。

ターミナルウィンドウ
go test -run '^$' -bench 'Benchmark(CloneReadOnly|Search10k|TermQuery10k)$' -benchmem -count=3

query計測の前にbenchmarkが1万documentのfixtureを構築します。サービス起動やclient transportを測るときは、compile、binary展開、image取得、seed loadingを計測時間に含めるか、事前に明記してください。