Java Web アプリケーションの場合、CPU コアの数が多いほうが良いのでしょうか、それともクロック速度が高いほうが良いのでしょうか?

Java Web アプリケーションの場合、CPU コアの数が多いほうが良いのでしょうか、それともクロック速度が高いほうが良いのでしょうか?

serverfault がこれを質問するのに適切な場所かどうかはわかりませんが、Java Web アプリケーションに新しい CPU タイプを選択しなければならない場合、どのような選択をするか疑問に思います。

a) 32コア、クロック速度2.5GHzのCPU

または

b) 8コアでクロック速度が3.8GHzのCPU

Web アプリケーションの受信 HTTP 要求のそれぞれが空き Java スレッドによって処理されるという事実を考慮すると、同時に 4 倍の HTTP 要求を処理できるため、a) を選択するのが合理的かもしれません。ただし、その一方で、CPU b) は単一の HTTP 要求の処理をはるかに速く完了できます...

どう思いますか?

補足:

  • 物理マシンである必要があり、VM やクラウド ソリューションはこの場合選択肢になりません。
  • RAMは重要ではありません。サーバーには最終的に512GBのRAMが搭載されます。
  • キャッシュ: Java Web アプリケーションには広範なキャッシュ フレームワークが備わっているため、選択は実際には CPU に依存します。

答え1

要約:本当の答えはおそらく「RAM を増やす」でしょうが、質問の通り、答えは、もちろん、場合によります。とはいえ、2.5Ghz の 32 コアは、3.8Ghz の 8 コアにほぼ確実に勝ります。つまり、コアの数は 4 倍、クロック速度は 1.5 倍です。あまり公平な戦いではありません。

考慮すべき要素としては、トランザクション応答時間、同時ユーザー数、アプリケーション アーキテクチャなどがあります。

トランザクション応答時間 Java アプリケーションがほとんどのリクエストに数ミリ秒で応答する場合は、より多くのコアを用意してより多くの同時リクエストを処理するのがおそらく最善策です。ただし、アプリケーションが主に長時間実行される複雑なトランザクションを処理する場合は、より高速なコアのほうが有利になる可能性があります (または、そうでない場合もあります - 以下を参照)。

同時ユーザー数とリクエスト数 Java アプリケーションが多数の同時リクエストを受信する場合は、コア数を増やすと効果的でしょう。同時リクエストがそれほど多くない場合は、アイドル状態のコアを余分に購入する必要があるだけかもしれません。

アプリケーションアーキテクチャ アプリケーション サーバーがトランザクション時間のほとんどを Web サービス、データベース、kafaka/mq などからの応答の待機に費やしている場合、前述の長時間実行されるリクエストは、より高速なコアからあまり恩恵を受けません。20 ~ 30 秒のトランザクションを実行するアプリケーションを多数見てきましたが、これらのアプリケーションでは、応答時間のほんの一部がアプリケーション自体の処理に費やされ、残りの時間はデータベースや Web サービスからの応答の待機に費やされています。

また、アプリケーションのさまざまな部分がうまく連携していることを確認する必要があります。それぞれが 32 または 64 のスレッドでリクエストを処理し、JDBC プール内の 10 個の接続のうちの 1 つを待機するキュー (いわゆる Python の豚の問題) があっても、あまり役に立ちません。今少し計画と設計をしておくと、後でパフォーマンスのトラブルシューティングを行う手間が省けます。

最後にもう 1 つ、どのような CPU を比較しているのでしょうか。私が見つけた最も安価な 32 コア 2.5 GHz CPU は、8 コア 3.8 GHz CPU よりも少なくとも 3 倍から 4 倍高価です。

答え2

Java Web サーバーが適切に構成されている場合は、コアを増やす必要があります。

コア数や速度に関係なく、セマフォや同時アクセスなどの依存関係がまだ存在し、一部のスレッドが待機状態になります。ただし、OS (マルチスレッド) よりも CPU (コア) で管理する方が適切です。

いずれにせよ、2.5Ghz の 32 コアは、3.8Ghz の 8 コアよりも多くのスレッドをより効率的に処理します。

また、CPU が発する熱は周波数 (他の要素も含む) に依存し、直線的ではありません。つまり、3.8Ghz は 3.8/2.5 倍よりも多くの熱を発します (CPU の正確なタイプ/ブランドに基づいて確認する必要があります... 多くのサイトで詳細な情報が提供されています)。

答え3

リクエストの実行には約 100 ~ 200 ミリ秒かかり、そのほとんどは処理時間 (実際の CPU 実行と実際のメモリ アクセスを区別することは困難ですが) であり、I/O はほとんどなく、データベースの待機などがあるとのことです。

2 つの CPU それぞれで実際にどれくらい時間がかかるかをベンチマークする必要がありますが、遅い方の CPU (コアが 32 個) では 150 ミリ秒、速い方の CPU (コアが 8 個のみ) では 100 ミリ秒かかると仮定します。

すると、最初の CPU は 1 秒あたり最大 32/0.15 = 213 件のリクエストを処理できるようになります。

2 番目の CPU は、1 秒あたり最大 8/0.1 = 80 件のリクエストを処理できます。

そこで大きな疑問となるのが、1 秒あたりにどのくらいのリクエスト数を期待するかということです。1 秒あたり数十のリクエスト数に遠く及ばない場合は、最初の CPU は必要ありません。2 番目の CPU を使用すると、各リクエストの実行時間が短縮されます。1 秒あたり 100 を超えるリクエスト数が必要な場合は、最初の CPU が適しています (または、サーバーを複数用意する方が理にかなっている可能性があります)。

これは非常に大まかな推定値であることに注意してください。確実に知る唯一の方法は、実際の負荷で各サーバーをベンチマークすることです。前述のように、高速 CPU またはコア数の多い CPU では、メモリ アクセスがすぐに不足する可能性があります。ここでは、さまざまな CPU キャッシュのサイズと、各要求の「ワーキング セット」が非常に重要です。これは、システム コール、共有リソース、I/O のない、真に CPU に依存する作業を考慮した値です。

答え4

予備的注記
私も賛成します@おそらく役に立つ間違いなく役に立つ回答

tldr; 本当の答えはおそらく「RAMを増やす」でしょう

特にこの点。

警告
管理者というほどではありませんが、
ソフトウェア エンジニアリングの観点から見ると、そうかもしれません。

測定に代わるものはない

私たちが知っていること
つまり、この機械は

  • (エンタープライズ?)Javaベースのバックエンドアプリケーションを実行する予定
  • クライアントのリクエストを処理するHTTP APIを(ある程度のコンテキスト内で)公開する
  • おそらく何らかのデータベースが付属している
  • それ以外の点では、I/Oバウンドはあまりないと説明されている
  • サードパーティのサービスの可用性、遅延、スループットに依存しない

OPが描いている絵はそれほど漠然としたものではない。しかし同時に、答えを出すのに十分なデータからは程遠い。OPの個人的な状況に関する確か
に、32コアでクロック速度が2/3だとおそらく比較的小さな速度の利点で、コアの 1/4 よりも優れたパフォーマンスを発揮します。確かに、発生する熱は 4GHz のしきい値を超えるクロック速度ではうまくスケーリングされません。そして、盲目的に卵を 1 つのバスケットに入れる必要がある場合、私はいつでも 32 コアを選択します。

我々が知らないこと
それでもまだ多すぎる。

しかし、これらの単純な真実を超えて、より具体的で客観的な答えを求める仮説的な試みには非常に懐疑的である。もし可能であれば(そして単位時間あたりのオペレーションが妥当な懸念事項であると確信する十分な理由がある場合)、システムを実行する予定のハードウェアを入手し、エンドツーエンドで測定しテストする
情報に基づいた決定関連するそして信頼できるデータ。

OP は次のように書きました: RAMは重要ではない

ほとんどの場合、記憶はボトルネック。

確かに、OP主に尋ねているのはCPU コアとクロック速度そして、記憶は話題から外れることの限界点にあるように見えます。

しかし、私はそうは思いません。私には、この質問は誤った前提に基づいている可能性の方がはるかに高いように思えます。@OP、誤解しないでください。あなたの質問はトピックに沿っており、よく表現されており、あなたの懸念は明らかに本物です。あなたのユースケースでどの CPU が「より優れた」パフォーマンスを発揮するかという答えが、あなたにとってまったく関連性があるとは思えません。

メモリが重要な理由(CPUにとって)

メインメモリは非常に遅い歴史
的に、ハードドライブと比較して、RAM は「高速なタイプのストレージ」と考えられてきました。その比較の文脈では、それは今でも当てはまります。しかし、ここ数十年の間に、プロセッサの速度は DRAM のパフォーマンスよりもはるかに速い速度で一貫して成長してきました。この開発により、一般に「「プロセッサとメモリのギャップ」

プロセッサとメモリの速度のギャップ

プロセッサとメモリの速度のギャップ (出典: Carlos Carvalho、ミーニョ大学情報学部)

キャッシュラインの取得メインメモリからCPUレジスタへの書き込みには約100クロックサイクルかかります。時間の経過と共に、オペレーティングシステムはx86アーキテクチャの4つのコアのうちの1つにある2つのハードウェアスレッドのうちの1つを次のように報告します。忙しい
可用性このハードウェアスレッドに関しては、OSは嘘をついていない、それは待っているしかし、処理装置自体は、そこに向かって這い寄ってくるキャッシュラインを無視して、事実上のアイドル
この間、指示/操作/計算は実行されません。

+----------+---------------+---------------------------------------------------------------------------------------------------+
|  Type of |    size of    |                                Latency due to fetching a cache line                               |
| mem / op |     cache     +--------+--------+------------+--------------------------------------------------------------------+
|          |   (register)  |  clock |  real  | normalized |                            now I feel it                           |
|          |               | cycles |  time  |            |                                                                    |
+----------+---------------+--------+--------+------------+--------------------------------------------------------------------+
|   tick   |      16KB     |    1   | 0.25ns |     1s     |             Dinner is already served. Sit down, enjoy.             |
|          | *the* 64 Bits |        |        |            |                                                                    |
+----------+---------------+--------+--------+------------+--------------------------------------------------------------------+
|    L1    |      64KB     |    4   |   1ns  |     4s     |               Preparations are done, food's cooking.               |
|          |               |        |        |            |                 Want a cold one to bridge the gap?                 |
+----------+---------------+--------+--------+------------+--------------------------------------------------------------------+
|    L2    |     2048KB    |   11   |  ~3ns  |     12s    |        Would you be so kind as to help me dice the broccoli?       |
|          |               |        |        |            |    If you want a beer, you will have to go to the corner store.    |
+----------+---------------+--------+--------+------------+--------------------------------------------------------------------+
|    L3    |     8192KB    |   39   |  ~10ns |     40s    |    The car is in the shop, you'll have to get groceries by bike.   |
|          |               |        |        |            |             Also, food ain't gonna cook itself, buddy.             |
+----------+---------------+--------+--------+------------+--------------------------------------------------------------------+
|   DRAM   |     ~20GB     |   107  |  ~30ns |    2min    |      First year of college. First day of the holiday weekend.      |
|          |               |        |        |            |         Snow storm. The roommate's are with their families.        |
|          |               |        |        |            | You have a piece of toast, two cigarettes and 3 days ahead of you. |
+----------+---------------+--------+--------+------------+--------------------------------------------------------------------+

シリーズチップのレイテンシ数値Core-i7-9XX出典: スコット・マイヤーズ、2010年

結論 適切な測定が不可能な場合は、コアとクロック速度を議論するのではなく、余剰ハードウェア予算に対する最も安全な投資はCPUキャッシュサイズである

では、メモリが個々のハードウェア スレッドを定期的にアイドル状態にしているのであれば、より多くの ~カウベル~ コアが解決策になるのでしょうか?

理論的には、ソフトウェアが準備できれば、マルチ/ハイパースレッディングできた早くして

たとえば、過去数年間の納税申告書 (合計 8​​ 年分) を見ているとします。1 年 (行) あたり 12 個の月次値 (列) を保持しています。

現在、1 バイトには 256 個の個別の値 (8 つの個別の 2 進数として) を保持できます。それぞれ 2 つの状態を想定し、8^2 = 256異なる状態の組み合わせが生まれます。通貨に関係なく、給与額の上限を表すには 256 はやや低いように感じられます。さらに、議論のために、最小単位 (「セント」) は重要ではないと仮定しましょう (全員が主要単位の整数値を稼ぎます)。最後に、雇用主が上級管理職と一般従業員の給与格差を認識しており、選ばれた少数の従業員をまったく別の会計システムで管理していると仮定します。

したがって、この簡略化されたシナリオでは、前述のメモリ空間の 2 倍、つまり 2 バイト (または「ハーフワード」) をunsigned形式 (つまり から までの範囲を表す) で使用すると、[0, 2^16 = 65536)すべての従業員の月給の値を表現するのに十分であると仮定します。

したがって、選択した言語 / RDBS / OS では、均一なデータ サイズ (2 バイト / 16 ビット) の値を持つマトリックス (2 次元データ構造、「リストのリスト」) が保持されます。
たとえば、C++ では、これは になります。Javaでもののをstd::vector<std::vector<uint16_t>>使用すると思います。vectorvectorshort

さて、ここで賞品に関する質問:
インフレーション (またはアドレス空間に書き込むその他の任意の理由) のために、8 年間の値を調整したいとします。ここでは、16 ビット値の均一な分布を調べます。マトリックス内のすべての値を 1 回ずつアクセスし、読み取り、変更してから、アドレス空間に書き込む必要があります。
データをどのように走査するかは重要ですか?

答えは次のとおりです。はい、とてもそうです最初に行 (内部データ構造) を反復処理すると、同時実行環境でほぼ完璧なスケーラビリティが得られます。ここでは、追加のスレッドと、データの半分が 1 つに、残りの半分がもう 1 つに配置されることにより、ジョブが 2 倍の速度で実行されます。4 つのスレッド? パフォーマンスは 4 倍向上します。
ただし、最初に列を作成することを選択した場合2つのスレッドがタスクを実行します大幅に遅い主要なトラバーサル方向の選択によって生じた悪影響を軽減する (!) ためだけに、約 10 個の並列実行スレッドが必要になります。また、コードが単一の実行スレッドで実行される限り、違いを測定することはできませんでした。

+------+------+------+------+------+------+------+
| Year |  Jan |  Feb | Mar  | Apr  | ...  | Dec  |
+------+------+------+------+------+------+------+
| 2019 | 8500 | 9000 | 9000 | 9000 | 9000 | 9000 | <--- contiguous in memory
+------+------+------+------+------+------+------+
| 2018 | 8500 | 8500 | 8500 | 8500 | 8500 | 8500 | <--- 12 * 16Bit (2Byte)
+------+------+------+------+------+------+------+
| 2017 | 8500 | 8500 | 8500 | 8500 | 8500 | 8500 | <--- 3 * (4 * 16Bit = 64Bit (8Byte) 
+------+------+------+------+------+------+------+
| ...  | 8500 | 7500 | 7500 | 7500 | 7500 | 7500 | <--- 3 cache lines
+------+------+------+------+------+------+------+
| 2011 | 7500 | 7200 | 7200 | 7200 | 7200 | 7200 | <--- 3 lines, likely from the same
+------+------+------+------+------+------+------+      virtual memory page, described by 
                                                        the same page block.

OP は次のように書いています: a) 32 コアでクロック速度 2.5 Ghz の CPU、
または
b) 8 コアでクロック速度 3.8 Ghz の CPU

他の条件はすべて同じです:

-->キャッシュ サイズ、メモリ サイズ、ハードウェアの投機的プリフェッチ機能、並列化を実際に活用できる実行中のソフトウェアなど、クロック速度よりも重要なものを考慮してください。

--> サードパーティの分散システムに依存しなくても、実稼働環境では、本当に I/O 制約を受けていないことを確認してください。ハードウェアを社内に用意する必要があり、AWS / GCloud / Azure / Heroku / Whatever-XaaS-IsHipNowに任せられない場合は、DBを置くSSDにお金をかけましょう。ないデータベースをアプリケーションと同じ物理マシン上に配置する場合は、ネットワーク距離 (ここでも待ち時間を測定) が可能な限り短くなるようにしてください。

--> 疑いの余地なく並行処理用に構築された、有名で、検証済みの、最高級の「エンタープライズ レベル」の HTTP サーバー ライブラリを選択するだけでは十分ではありません。ルートで実行するサード パーティ ライブラリが十分であることを確認してください。社内コードも同様であることを確認してください。

この場合、VMやクラウドソリューションは選択肢ではない

それはわかります。
さまざまな正当な理由があります。

それはそうであるべきだ1つの物理マシン [...]
[...] 32 コア、クロック速度 2.5 Ghz の CPU

しかし、これはそれほどではありません。AWS
もAzureも分散システム、マイクロクラスタリング、負荷分散を発明したわけではありません。ベアメタルハードウェアでメガコーポレーションのようなリソースなしでセットアップするのはより困難ですが、できる自宅のリビングルームで K8 クラスターの分散メッシュを実行できます。また、定期的なヘルス チェックやピーク負荷時の自動プロビジョニングのためのツールも、セルフホスト プロジェクト向けに用意されています。

OP は次のように書きました: RAMは重要ではない

ここに ~仮定の~ 再現可能なシナリオがあります: RAM は安価で重要ではないので、zram をスワップ領域として有効にします。次に、頻繁なページングが発生しない、安定したメモリ集約型のタスクを実行します。深刻な LRU 反転のポイントに達すると、ファンがうるさくなり、CPU コアが熱くなります。これは、メモリ管理の処理 (スワップへのゴミの移動) で忙しいためです。

OP は次のように書きました: RAMは重要ではない

私が十分に明確に表現していない場合に備えて、この意見を再考すべきだと思います。

TL;DR?
32コア。
さらにより良い。

関連情報