以下の内容はhttps://dshimizu.hatenablog.com/entry/2024/04/30/000000より取得しました。


Puma HTTP サーバーの挙動等を調査したことのメモ

Puma を使ったアプリケーションを触っているのですが、Puma についてわかっていないので少しドキュメントを読んだり動かしたりしたメモです

Puma のアーキテクチャ

概要図は下記にあります。

Puma は、クラスターモードとシングルモードの 2 つのモードのいずれかで動作するようです。 シングルモードでは、1 つの Puma プロセス(ワーカー)のみが起動します。クラスターモードでは、マスタープロセスが起動され、それに対して、fork() システムコールを使用して 1 つ以上の子プロセス(ワーカー)が作成されます。

Puma 起動時に TCP または UNIX ソケットをリッスンします。

外部からのリクエストをバックログの値分までは受け付けられるようです。 スレッドがソケットからリクエストを読み取りスレッド内部で「todo」という配列に格納されるようです。

試す

Rails のサンプルアプリケーションを使って試してみます。

環境

Ruby はインストールされているものとします。

% cat /etc/os-release
PRETTY_NAME="Debian GNU/Linux 12 (bookworm)"
NAME="Debian GNU/Linux"
VERSION_ID="12"
VERSION="12 (bookworm)"
VERSION_CODENAME=bookworm
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"
% ruby -v
ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) [x86_64-linux-gnu]

bunlder インストール

% gem install bundler
% bundler -v
Bundler version 2.3.7

Rails プロジェクト作成

bundler 用のディレクトリを作成します。

% mkdir -p /path/to/sandbox

% cd !$

bundler を初期化します。Gemfileが生成されます。

% bundle init
Writing new Gemfile to /path/to/sandbox/Gemfile

Gemfile を編集して、以下のようにします。

# frozen_string_literal: true

source "https://rubygems.org"

ruby "3.1.2"

gem "rails", "~> 7.1.3", ">= 7.1.3.2"
gem "puma", ">= 5.0"

gem "sprockets-rails"
gem "sqlite3", "~> 1.4"
gem "importmap-rails"
gem "turbo-rails"
gem "stimulus-rails"
gem "jbuilder"
gem "tzinfo-data", platforms: %i[ mswin mswin64 mingw x64_mingw jruby ]
gem "bootsnap", require: false

group :development, :test do
  gem "debug", platforms: %i[ mri mswin mswin64 mingw x64_mingw ]
end

group :development do
  gem "web-console"
  gem "error_highlight", ">= 0.4.0", platforms: [:ruby]
end

group :test do
  gem "capybara"
  gem "selenium-webdriver"
end

bundler を使ってインストールします。 Debianだとスーパーユーザー権限がないとデフォルトの場所にインストールできないので、インストールパスをプロジェクトディレクトリ内の vendor/bunlde にしておきます。

% bundle config set path 'vendor/bunlde'

% bundle install

Rails プロジェクトを新規に作成します。

% bundle exec rails new .

Rails を起動します。

% bundle exec rails s
=> Booting Puma
=> Rails 7.1.3.2 application starting in development
=> Run `bin/rails server --help` for more startup options
Puma starting in single mode...
* Puma version: 6.4.2 (ruby 3.1.2-p20) ("The Eagle of Durango")
*  Min threads: 5
*  Max threads: 5
*  Environment: development
*          PID: 3850903
* Listening on http://127.0.0.1:3000
* Listening on http://[::1]:3000

top コマンドを使ってプロセスの状態を見てみます。

% top -p 3850903 -H

puma srv tp 00X がワーカースレッドで、5つ起動しています。 reactor などもスレッドとして起動しているようです。

top - 04:08:47 up 52 days, 17:16,  2 users,  load average: 0.00, 0.00, 0.00
Threads:  13 total,   0 running,  13 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.3 us,  0.2 sy,  0.0 ni, 99.5 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
MiB Mem :   3928.8 total,    535.9 free,   2103.6 used,   1581.9 buff/cache
MiB Swap:      0.0 total,      0.0 free,      0.0 used.   1825.2 avail Mem

    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
3850903 dshimizu  20   0  960064 102668  13916 S   0.0   2.6   0:02.89 ruby3.1
3850916 dshimizu  20   0  960064 102668  13916 S   0.0   2.6   0:00.03 DEBUGGER__::SES
3850920 dshimizu  20   0  960064 102668  13916 S   0.0   2.6   0:00.32 puma plgn bg 0
3850921 dshimizu  20   0  960064 102668  13916 S   0.0   2.6   0:00.44 puma srv tp 001
3850922 dshimizu  20   0  960064 102668  13916 S   0.0   2.6   0:00.00 puma srv tp 002
3850923 dshimizu  20   0  960064 102668  13916 S   0.0   2.6   0:00.00 puma srv tp 003
3850924 dshimizu  20   0  960064 102668  13916 S   0.0   2.6   0:00.00 puma srv tp 004
3850925 dshimizu  20   0  960064 102668  13916 S   0.0   2.6   0:00.00 puma srv tp 005
3850926 dshimizu  20   0  960064 102668  13916 S   0.0   2.6   0:00.02 puma reactor
3850927 dshimizu  20   0  960064 102668  13916 S   0.0   2.6   0:00.48 puma srv thread
3850928 dshimizu  20   0  960064 102668  13916 S   0.0   2.6   0:00.01 puma srv thread
3850929 dshimizu  20   0  960064 102668  13916 S   0.0   2.6   0:00.00 puma srv
3850935 dshimizu  20   0  960064 102668  13916 S   0.0   2.6   0:00.02 reaper.rb:42

処理中のPumaスレッド数を上回るHTTPリクエストを投げた時の動き

puma にはリクエスタイムアウトの仕組みがないようで、そのままの状態で使うと、大量のリクエストが来た場合に、スレッド数を上回るリクエストは、クライアント側のタイムアウト設定値だけ待機し、それを超えると接続が切られるようです。

この時、例えば、ECS で Rails/Puma を動かしている場合、 重いリクエストで空きのスレッドがなくなっている場合、ALB ヘルスチェックリクエストも滞留することになってヘルスチェックに失敗し、ECSタスクがターゲットとして登録されているALB上のターゲットノードのステータスがUnhealty状態になり、ECS タスクが停止する形になる、といった状態が発生する可能性があります。

試してみます。

config/routes.rb に resources :samples, only: [:index, :show] を追記します。

Rails.application.routes.draw do
  # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html

  # Reveal health status on /up that returns 200 if the app boots with no exceptions, otherwise 500.
  # Can be used by load balancers and uptime monitors to verify that the app is live.
  get "up" => "rails/health#show", as: :rails_health_check

  # Defines the root path route ("/")
  # root "posts#index"

  resources :samples, only: [:index, :show]
end

app/controllers/samples_controller.rb を作成し、samples エンドポイントで60秒待機するようにするため、以下のようにしておきます。

class SamplesController < ApplicationController
  def index
    puts 'Started to wait 60 seconds'
    sleep 60
    puts 'Finished waiting'

    head :ok

  end

  def show

  end
end

Railsを起動します。 puma が5スレッド起動してます。

% bundle exec rails s
=> Booting Puma
=> Rails 7.1.3.2 application starting in development
=> Run `bin/rails server --help` for more startup options
Puma starting in single mode...
* Puma version: 6.4.2 (ruby 3.1.2-p20) ("The Eagle of Durango")
*  Min threads: 5
*  Max threads: 5
*  Environment: development
*          PID: 1051532
* Listening on http://127.0.0.1:3000
* Listening on http://[::1]:3000
Use Ctrl-C to stop

10個のリクエストを並列で投げてみます。 Curlでのタイムアウト値を3秒にしています。

% para=10; seq $para | xargs -I{} -P$para curl -v --max-time 3 http://127.0.0.1:3000/samples

クライアント側(curl)の10リクエスト全てタイムアウトしました。

*   Trying 127.0.0.1:3000...
* Connected to 127.0.0.1 (127.0.0.1) port 3000 (#0)
*   Trying 127.0.0.1:3000...
* Connected to 127.0.0.1 (127.0.0.1) port 3000 (#0)
> GET /samples HTTP/1.1
> Host: 127.0.0.1:3000
> User-Agent: curl/7.88.1
> Accept: */*
>> GET /samples HTTP/1.1
> Host: 127.0.0.1:3000
> User-Agent: curl/7.88.1
> Accept: */*
>

*   Trying 127.0.0.1:3000...
* Connected to 127.0.0.1 (127.0.0.1) port 3000 (#0)
> GET /samples HTTP/1.1
> Host: 127.0.0.1:3000
> User-Agent: curl/7.88.1
> Accept: */*
>
*   Trying 127.0.0.1:3000...
* Connected to 127.0.0.1 (127.0.0.1) port 3000 (#0)
> GET /samples HTTP/1.1
> Host: 127.0.0.1:3000
> User-Agent: curl/7.88.1
> Accept: */*
>
*   Trying 127.0.0.1:3000...
* Connected to 127.0.0.1 (127.0.0.1) port 3000 (#0)
> GET /samples HTTP/1.1
> Host: 127.0.0.1:3000
> User-Agent: curl/7.88.1
> Accept: */*
>
*   Trying 127.0.0.1:3000...
* Connected to 127.0.0.1 (127.0.0.1) port 3000 (#0)
> GET /samples HTTP/1.1
> Host: 127.0.0.1:3000
> User-Agent: curl/7.88.1
> Accept: */*
>
*   Trying 127.0.0.1:3000...
* Connected to 127.0.0.1 (127.0.0.1) port 3000 (#0)
> GET /samples HTTP/1.1
> Host: 127.0.0.1:3000
> User-Agent: curl/7.88.1
> Accept: */*
>
*   Trying 127.0.0.1:3000...
* Connected to 127.0.0.1 (127.0.0.1) port 3000 (#0)
> GET /samples HTTP/1.1
> Host: 127.0.0.1:3000
> User-Agent: curl/7.88.1
> Accept: */*
>
*   Trying 127.0.0.1:3000...
* Connected to 127.0.0.1 (127.0.0.1) port 3000 (#0)
> GET /samples HTTP/1.1
> Host: 127.0.0.1:3000
> User-Agent: curl/7.88.1
> Accept: */*
>
*   Trying 127.0.0.1:3000...
* Connected to 127.0.0.1 (127.0.0.1) port 3000 (#0)
> GET /samples HTTP/1.1
> Host: 127.0.0.1:3000
> User-Agent: curl/7.88.1
> Accept: */*
>
* Operation timed out after 3000 milliseconds with 0 bytes received
* Closing connection 0
curl: (28) Operation timed out after 3000 milliseconds with 0 bytes received
* Operation timed out after 3001 milliseconds with 0 bytes received
* Closing connection 0
curl: (28) Operation timed out after 3001 milliseconds with 0 bytes received
* Operation timed out after 3001 milliseconds with 0 bytes received
* Closing connection 0
curl: (28) Operation timed out after 3001 milliseconds with 0 bytes received
* Operation timed out after 3001 milliseconds with 0 bytes received
* Closing connection 0
curl: (28) Operation timed out after 3001 milliseconds with 0 bytes received
* Operation timed out after 3001 milliseconds with 0 bytes received
* Closing connection 0
curl: (28) Operation timed out after 3001 milliseconds with 0 bytes received
* Operation timed out after 3001 milliseconds with 0 bytes received
* Closing connection 0
curl: (28) Operation timed out after 3001 milliseconds with 0 bytes received
* Operation timed out after 3001 milliseconds with 0 bytes received
* Closing connection 0
curl: (28) Operation timed out after 3001 milliseconds with 0 bytes received
* Operation timed out after 3001 milliseconds with 0 bytes received
* Closing connection 0
curl: (28) Operation timed out after 3001 milliseconds with 0 bytes received
* Operation timed out after 3001 milliseconds with 0 bytes received
* Closing connection 0
curl: (28) Operation timed out after 3001 milliseconds with 0 bytes received
* Operation timed out after 3000 milliseconds with 0 bytes received
* Closing connection 0
curl: (28) Operation timed out after 3000 milliseconds with 0 bytes received

Rails 側の出力は以下のようになりました。 5スレッド分のリクエストはサーバー側(Rails/Puma)の処理が行われましたが、残りの5リクエスト分はクライアント側でタイムアウトとなり、pumaのログには何も出力されませんでしたので、処理されずに終わったことになるかと思います。

Started GET "/samples" for 127.0.0.1 at 2024-04-28 02:51:09 +0000
  ActiveRecord::SchemaMigration Load (0.2ms)  SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC
Processing by SamplesController#index as */*
Started to wait 61 second
waiting ends
Completed 200 OK in 61003ms (ActiveRecord: 0.0ms | Allocations: 1248)


Started GET "/samples" for 127.0.0.1 at 2024-04-28 02:56:03 +0000
Processing by SamplesController#index as */*
Started to wait 61 second
Started GET "/samples" for 127.0.0.1 at 2024-04-28 02:56:03 +0000
Processing by SamplesController#index as */*
Started to wait 61 second
Started GET "/samples" for 127.0.0.1 at 2024-04-28 02:56:03 +0000
Processing by SamplesController#index as */*
Started to wait 61 second
Started GET "/samples" for 127.0.0.1 at 2024-04-28 02:56:03 +0000
Processing by SamplesController#index as */*
Started to wait 61 second
Started GET "/samples" for 127.0.0.1 at 2024-04-28 02:56:03 +0000
Processing by SamplesController#index as */*
Started to wait 61 second


## --- 最初の5リクエスト分のサーバー側(Rails/Puma)の処理完了のログ ---

Finished waiting
Completed 200 OK in 61001ms (ActiveRecord: 0.0ms | Allocations: 4077)


Finished waiting
Completed 200 OK in 61001ms (ActiveRecord: 0.0ms | Allocations: 3329)


Finished waiting
Completed 200 OK in 61001ms (ActiveRecord: 0.0ms | Allocations: 2686)


Finished waiting
Completed 200 OK in 61000ms (ActiveRecord: 0.0ms | Allocations: 1931)


Finished waiting
Completed 200 OK in 61001ms (ActiveRecord: 0.0ms | Allocations: 1163)

クラスターモードの起動

クラスターモードの起動を試してみます。

config/puma.rb に以下を worker 数の指定を追記して puma を再度起動します。

workers 2

ワーカーが2つ起動して、Cluster モードになっていることが確認できます。

% bundle exec rails s
=> Booting Puma
=> Rails 7.1.3.2 application starting in development
=> Run `bin/rails server --help` for more startup options
[506579] Puma starting in cluster mode...
[506579] * Puma version: 6.4.2 (ruby 3.1.2-p20) ("The Eagle of Durango")
[506579] *  Min threads: 5
[506579] *  Max threads: 5
[506579] *  Environment: development
[506579] *   Master PID: 506579
[506579] *      Workers: 2
[506579] *     Restarts: (✔) hot (✔) phased
[506579] * Listening on http://127.0.0.1:3000
[506579] * Listening on http://[::1]:3000
[506579] Use Ctrl-C to stop
[506579] - Worker 0 (PID: 506582) booted in 0.0s, phase: 0
[506579] - Worker 1 (PID: 506585) booted in 0.0s, phase: 0

5 スレッド * 2 worker と 10 スレッド * 1 worker の簡易負荷検証

以下のようなk6のリクエストシナリオを記述したファイルを準備します。

import http from 'k6/http';
import { sleep } from 'k6';

export default function () {
  http.get('http://127.0.0.1:3000/up');
  sleep(1);
}

100ユーザーを使って65秒間負荷テストを実行してみます。

100ユーザーや65秒は適当に決めた値で意味はありません。手元の環境では request timeout が結構発生しました。

% k6 run --vus 100 --duration 65s k6.js

5 スレッド * 2 worker の結果

### 1回目

    :
     data_received..................: 2.0 MB 30 kB/s
     data_sent......................: 267 kB 4.0 kB/s
     http_req_blocked...............: avg=230.52µs min=3.64µs  med=5.2µs   max=27.66ms  p(90)=6.89µs  p(95)=21.39µs
     http_req_connecting............: avg=212.67µs min=0s      med=0s      max=27.61ms  p(90)=0s      p(95)=0s
     http_req_duration..............: avg=1.02s    min=11.69ms med=29.03ms max=1m0s     p(90)=43.34ms p(95)=83.25ms
       { expected_response:true }...: avg=107.66ms min=11.69ms med=28.94ms max=4.98s    p(90)=41.49ms p(95)=54.63ms
     http_req_failed................: 1.53%  ✓ 50        ✗ 3204
     http_req_receiving.............: avg=55.39µs  min=0s      med=51.39µs max=558.18µs p(90)=70.4µs  p(95)=78.59µs
     http_req_sending...............: avg=42.76µs  min=9.66µs  med=14.04µs max=44.45ms  p(90)=25.63µs p(95)=39.21µs
     http_req_tls_handshaking.......: avg=0s       min=0s      med=0s      max=0s       p(90)=0s      p(95)=0s
     http_req_waiting...............: avg=1.02s    min=10.11ms med=28.96ms max=1m0s     p(90)=43.28ms p(95)=83.19ms
     http_reqs......................: 3254   48.541967/s
     iteration_duration.............: avg=2.02s    min=1.01s   med=1.02s   max=1m1s     p(90)=1.04s   p(95)=1.08s
     iterations.....................: 3254   48.541967/s
     vus............................: 6      min=6       max=100
     vus_max........................: 100    min=100     max=100


running (1m07.0s), 000/100 VUs, 3254 complete and 0 interrupted iterations
default ✓ [======================================] 100 VUs  1m5s



### 2回目

    :
     data_received..................: 2.0 MB 30 kB/s
     data_sent......................: 265 kB 4.0 kB/s
     http_req_blocked...............: avg=497.09µs min=3.61µs med=5.08µs   max=34.35ms p(90)=7.1µs    p(95)=20.45µs
     http_req_connecting............: avg=478.83µs min=0s     med=0s       max=34.29ms p(90)=0s       p(95)=0s
     http_req_duration..............: avg=1.03s    min=9.5ms  med=434.71ms max=1m0s    p(90)=460.68ms p(95)=505.93ms
       { expected_response:true }...: avg=301.1ms  min=9.5ms  med=434.1ms  max=5.02s   p(90)=457.69ms p(95)=475.92ms
     http_req_failed................: 1.23%  ✓ 40        ✗ 3193
     http_req_receiving.............: avg=54.67µs  min=0s     med=50.63µs  max=364.8µs p(90)=69.36µs  p(95)=77.79µs
     http_req_sending...............: avg=77.91µs  min=9.31µs med=13.79µs  max=26.86ms p(90)=25.7µs   p(95)=40.62µs
     http_req_tls_handshaking.......: avg=0s       min=0s     med=0s       max=0s      p(90)=0s       p(95)=0s
     http_req_waiting...............: avg=1.03s    min=9.38ms med=434.65ms max=59.99s  p(90)=460.61ms p(95)=505.87ms
     http_reqs......................: 3233   48.209701/s
     iteration_duration.............: avg=2.04s    min=1.01s  med=1.43s    max=1m1s    p(90)=1.46s    p(95)=1.5s
     iterations.....................: 3233   48.209701/s
     vus............................: 1      min=1       max=100
     vus_max........................: 100    min=100     max=100


running (1m07.1s), 000/100 VUs, 3233 complete and 0 interrupted iterations
default ✓ [======================================] 100 VUs  1m5s



### 3回目

    :
     data_received..................: 2.0 MB 30 kB/s
     data_sent......................: 266 kB 4.0 kB/s
     http_req_blocked...............: avg=272.63µs min=3.51µs med=5.28µs  max=27.37ms  p(90)=7.25µs  p(95)=21.96µs
     http_req_connecting............: avg=262.21µs min=0s     med=0s      max=27.33ms  p(90)=0s      p(95)=0s
     http_req_duration..............: avg=1.03s    min=7.69ms med=29.72ms max=59.99s   p(90)=47.73ms p(95)=94.99ms
       { expected_response:true }...: avg=110.02ms min=7.69ms med=29.62ms max=5.03s    p(90)=46.19ms p(95)=56.39ms
     http_req_failed................: 1.53%  ✓ 50        ✗ 3199
     http_req_receiving.............: avg=55.25µs  min=0s     med=51.71µs max=301.38µs p(90)=71.41µs p(95)=80.62µs
     http_req_sending...............: avg=43.85µs  min=9.49µs med=14.17µs max=5.41ms   p(90)=26.42µs p(95)=44.15µs
     http_req_tls_handshaking.......: avg=0s       min=0s     med=0s      max=0s       p(90)=0s      p(95)=0s
     http_req_waiting...............: avg=1.03s    min=7.6ms  med=29.64ms max=59.99s   p(90)=47.66ms p(95)=94.91ms
     http_reqs......................: 3249   48.437741/s
     iteration_duration.............: avg=2.03s    min=1s     med=1.03s   max=1m1s     p(90)=1.04s   p(95)=1.09s
     iterations.....................: 3249   48.437741/s
     vus............................: 6      min=6       max=100
     vus_max........................: 100    min=100     max=100


running (1m07.1s), 000/100 VUs, 3249 complete and 0 interrupted iterations
default ✓ [======================================] 100 VUs  1m5s

10 スレッド * 1 worker の結果

### 1回目

    :
     data_received..................: 2.0 MB 30 kB/s
     data_sent......................: 265 kB 3.9 kB/s
     http_req_blocked...............: avg=420.98µs min=3.51µs   med=5.25µs   max=25.54ms  p(90)=7.03µs   p(95)=20.71µs
     http_req_connecting............: avg=412.69µs min=0s       med=0s       max=25.49ms  p(90)=0s       p(95)=0s
     http_req_duration..............: avg=1.04s    min=266.61ms med=343.31ms max=1m0s     p(90)=386.07ms p(95)=420.53ms
       { expected_response:true }...: avg=398.49ms min=266.61ms med=342.97ms max=4.97s    p(90)=383.94ms p(95)=409.82ms
     http_req_failed................: 1.08%  ✓ 35        ✗ 3190
     http_req_receiving.............: avg=58.08µs  min=0s       med=54.9µs   max=641.59µs p(90)=72.39µs  p(95)=80.78µs
     http_req_sending...............: avg=32.46µs  min=9.76µs   med=14.3µs   max=874.12µs p(90)=25.69µs  p(95)=39.37µs
     http_req_tls_handshaking.......: avg=0s       min=0s       med=0s       max=0s       p(90)=0s       p(95)=0s
     http_req_waiting...............: avg=1.04s    min=266.54ms med=343.25ms max=59.99s   p(90)=385.99ms p(95)=420.46ms
     http_reqs......................: 3225   48.129766/s
     iteration_duration.............: avg=2.04s    min=1.26s    med=1.34s    max=1m1s     p(90)=1.38s    p(95)=1.42s
     iterations.....................: 3225   48.129766/s
     vus............................: 5      min=5       max=100
     vus_max........................: 100    min=100     max=100


running (1m07.0s), 000/100 VUs, 3225 complete and 0 interrupted iterations
default ✓ [======================================] 100 VUs  1m5s


### 2回目

    :
     data_received..................: 2.0 MB 30 kB/s
     data_sent......................: 266 kB 4.0 kB/s
     http_req_blocked...............: avg=584.55µs min=3.65µs med=5.28µs  max=34.07ms p(90)=7.24µs   p(95)=21.18µs
     http_req_connecting............: avg=566.77µs min=0s     med=0s      max=32.53ms p(90)=0s       p(95)=0s
     http_req_duration..............: avg=1.03s    min=8.53ms med=45.89ms max=59.99s  p(90)=100.4ms  p(95)=155.64ms
       { expected_response:true }...: avg=127.37ms min=8.53ms med=45.23ms max=5.07s   p(90)=92.73ms  p(95)=142.96ms
     http_req_failed................: 1.50%  ✓ 49        ✗ 3200
     http_req_receiving.............: avg=58.99µs  min=0s     med=54.08µs max=5.22ms  p(90)=73.6µs   p(95)=82.74µs
     http_req_sending...............: avg=36.37µs  min=9.69µs med=14.03µs max=1.02ms  p(90)=26.1µs   p(95)=43.15µs
     http_req_tls_handshaking.......: avg=0s       min=0s     med=0s      max=0s      p(90)=0s       p(95)=0s
     http_req_waiting...............: avg=1.03s    min=7.97ms med=45.81ms max=59.99s  p(90)=100.32ms p(95)=155.57ms
     http_reqs......................: 3249   48.405461/s
     iteration_duration.............: avg=2.03s    min=1.02s  med=1.04s   max=1m1s    p(90)=1.1s     p(95)=1.15s
     iterations.....................: 3249   48.405461/s
     vus............................: 4      min=4       max=100
     vus_max........................: 100    min=100     max=100


running (1m07.1s), 000/100 VUs, 3249 complete and 0 interrupted iterations
default ✓ [======================================] 100 VUs  1m5s


### 3回目

    :
     data_received..................: 2.0 MB 30 kB/s
     data_sent......................: 267 kB 4.0 kB/s
     http_req_blocked...............: avg=95.1µs   min=3.52µs med=5.27µs  max=31.36ms  p(90)=7.19µs  p(95)=24.95µs
     http_req_connecting............: avg=74.63µs  min=0s     med=0s      max=14ms     p(90)=0s      p(95)=0s
     http_req_duration..............: avg=1.02s    min=6.04ms med=23.94ms max=1m0s     p(90)=63.47ms p(95)=92.73ms
       { expected_response:true }...: avg=108.04ms min=6.04ms med=23.82ms max=5.06s    p(90)=61.31ms p(95)=82.59ms
     http_req_failed................: 1.53%  ✓ 50        ✗ 3207
     http_req_receiving.............: avg=55.68µs  min=0s     med=52.34µs max=280.71µs p(90)=71.26µs p(95)=82.13µs
     http_req_sending...............: avg=121.33µs min=9.79µs med=14.14µs max=21.22ms  p(90)=25.54µs p(95)=39.29µs
     http_req_tls_handshaking.......: avg=0s       min=0s     med=0s      max=0s       p(90)=0s      p(95)=0s
     http_req_waiting...............: avg=1.02s    min=5.91ms med=23.86ms max=1m0s     p(90)=63.4ms  p(95)=92.68ms
     http_reqs......................: 3257   48.540327/s
     iteration_duration.............: avg=2.02s    min=1s     med=1.02s   max=1m1s     p(90)=1.06s   p(95)=1.09s
     iterations.....................: 3257   48.540327/s
     vus............................: 8      min=8       max=100
     vus_max........................: 100    min=100     max=100


running (1m07.1s), 000/100 VUs, 3257 complete and 0 interrupted iterations
default ✓ [======================================] 100 VUs  1m5s

この程度だとぱっと見あまり差はないように思いました。(多少5 スレッド * 2 workerの方が良さそうだが誤差かも)

参考




以上の内容はhttps://dshimizu.hatenablog.com/entry/2024/04/30/000000より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14