スレッドは仮想メモリまたは実メモリを使用しますか?


10

Linuxサーバーを最適化して、プロセスごとに10,000スレッドを処理しようとしていましたが、現在は382スレッドしか処理していません。あたりとして、この記事で、次の式は、可能な全スレッドを調べるために使用されます。

number of threads = total virtual memory / (stack size*1024*1024)

つまり、スレッドはすべてのデータを仮想メモリに格納します。そして、私の知る限りでは、仮想メモリは、RAMやキャッシュではなくハードディスクに保存されているLinuxマシンのスワップスペースです。

だから私の質問は、スレッドがデータを処理/格納するために格納するためにハードディスクを使用するかどうかです。

はいの場合、これはパフォーマンスに影響しませんか?それらをRAMまたはキャッシュに置くことでパフォーマンスを向上させることはできますか?どうやって?

いいえの場合、スレッドはどのように機能しますか?

更新:

役に立たないの答えによると、仮想メモリは大まかに構成されたシステムです:

  • 物理メモリ(RAM)
  • アタッチしたスワップファイル
  • 仮想アドレスが物理メモリで使用できない場合に仮想アドレスを物理アドレスに変換し、ページフォールトを発行するためのハードウェアサポート
  • (カーネル)ソフトウェアサポート:ハードウェアが使用するルックアップテーブルを管理し、必要に応じてスワップからページをプルすることにより、これらのページフォールトを処理します。

したがって、仮想メモリ上にあるものはすべて、RAM(実メモリ)とハードディスク(スワップファイル)にまとめられます。そしてとしてジェームズ彼の答えの中で説明 HDDは、このようなLRUなどalgorithimsを使用してカーネルによって取られる対ラムの決定。


2
サーバーに10,000のCPU /コアが搭載されていない限り、時間を浪費しています。

@JarrodRoberson:それはなぜですか?
dragosrsupercool

3
10,000スレッドは、物事を拡大するのに適した方法ではありません。サーバーをクロールさせるには良い方法です。CPUまたはコアごとに複数のスレッドを使用すると、サーバーコンテキストが切り替わり、実行速度が遅くなることはありません。

具体的には、「Linuxサーバーを最適化しようとしている」と言った場合、何を最適化しようとしていますか?スループットの場合、CPUごとにマルチプレキシングおよびノンブロッキングI / Oを使用する1つのスレッドの方が優れている可能性があります。
役に立たない

回答:


12

私の知る限りでは、仮想メモリはLinuxマシンのスワップ領域です

いいえ、仮想メモリは大まかに次の要素で構成されるシステムです。

  • 物理メモリ(RAM)
  • アタッチしたスワップファイル
  • 仮想アドレスが物理メモリで使用できない場合に仮想アドレスを物理アドレスに変換し、ページフォールトを発行するためのハードウェアサポート
  • (カーネル)ソフトウェアのサポート:
    • そのハードウェアで使用されるルックアップテーブルの管理
    • オンデマンドのスワップからページをプルすることにより、これらのページフォールトを処理する

必要なときに仮想メモリがRAMに確実にキャッシュされるようにするのはカーネル次第です。独自のユーザースペースVMレイヤー(データベースでよく使用されるiiucなど)を作成しているのでない限り、心配しないでください。


わかりましたので、仮想メモリの仮定は間違っていました。とにかく簡単なフォローアップの質問です。スワップスペースがRAMよりも大きい場合、完全にロードされた最大スレッドのパフォーマンスに影響がありますか?
dragosrsupercool

@dragosrsupercool:スワップスペースは常に物理メモリより大きくなります。それ以外の場合は、仮想メモリを使用する必要があります。
ブライアンオークリー

1
@BryanOakley:それは必ずしも本当ではありません。一部のOSは、割り当てられたすべての仮想ページにスワップページを割り当てます(つまり、スワップは少なくとも物理サイズと同じでなければなりません)。他のOSは、物理メモリからページを移動する必要がある場合にのみ、スワップページを割り当てます(つまり、スワップが物理メモリより少ない場合があります)。前者の利点は、割り当てが成功した場合に、そのメモリのスワップアウトが常に成功することです。後者の利点は、比較的まれな状況を考慮して、巨大なスワップファイルを悲観的に割り当てる必要がないことです。
mcmcc

1
@dragosrsupercoolの場合、RAM が少なく、実際にページングしない限り、パフォーマンスはRAMの量、スワップ、またはそれらの比率の影響を受けません。sarはページングアクティビティiircについて教えてくれます(チェック済み:sar -BLinuxの場合)
役に立たない

@役に立たない:RAMを完全に利用し、ページングを開始しないまで、スレッドの数を増やしたい。
dragosrsupercool

14

スレッドが実際に実行されている場合、現在の命令、およびスレッドが使用している変数はすべて物理メモリ内にある必要があります。

ほとんどの(実際にはほぼすべての)プログラムは仮想メモリに常駐し、ほとんどのプログラムは変数の格納に仮想メモリを使用します。

ページと呼ばれるチャンクに編成された仮想アドレス(これらは通常、4096または8192バイトブロックです)。

仮想メモリの各ブロックは、いつでも、実際のメモリのどこか、またはディスク用に予約された「スワップスペース」に格納されます。

プログラムコードは仮想アドレスを処理し、仮想アドレスに分岐したり、仮想アドレスでストレージへのアクセスを要求したりすると、システム(通常はハードウェアレベル)がアドレス要求の現在の場所を特定し、仮想アドレスにマッピングします。アドレスが現在ディスク上にある場合は、アドレスを実メモリにページングしてから、アドレスをマップします。

明らかに、すべての物理メモリが使用中の場合、何かがページインされ、次に何かがページアウトされる必要があるため、システムは「最近使用されていない」ページを探し、これをディスクにコピーしてから、リクエストしたページをコピーします。

最近のシステムには、仮想ストレージに関連するいくつかの最適化とトリックがあります。

  • アドレスは「プロセスごと」にマップされるため、たとえば、Linuxボックス内のすべてのCプログラムは、「メイン」プロセスを同じアドレスで開始します。
  • これにより、32ビットの仮想アドレスを実際の64ビットのアドレスにマップできるため、マシン上で複数の32ビットプロセスが4GBをはるかに占有して使用できるようになります。
  • プロセスが終了するか、メモリが他の方法で「解放」されると、システムはページを空きとしてマークするだけで、スワップディスクにコピーされることはありません。
  • 同様に、ストレージの新しいブロックが要求されると、システムは実メモリの空きページを取得するだけで、ディスクIOは実行されません。
  • スリープおよび休止機能は、すべてのメモリを強制的にスワップスペースにコピーするので、すべての現在のプロセスと現在のメモリの内容をウェイクアップ時に再作成できます。

3
「Linuxボックス内のすべてのCプログラムは、[メイン]が同じアドレスで開始する」とは、アドレス空間のレイアウトのランダム化が考慮されていないようです。これは、さまざまなスタック破壊攻撃スキームを阻止するために、ますます使用されています。そうでなければ良い答えなので、+ 1。
CVn '10

7

まず第一に、あなたはその分野の知識を欠いているように思われるので、あなたはコンピュータメモリについてもっと読む必要があります。

実行のスレッドは、オペレーティングシステムでスケジュールできる最小の処理単位です。スレッドとプロセスの実装はオペレーティングシステムによって異なりますが、ほとんどの場合、スレッドはプロセス内に含まれています。複数のスレッドが同じプロセス内に存在し、メモリなどのリソースを共有できますが、異なるプロセスはこれらのリソースを共有しません。

したがって、スレッドは利用可能なメモリを使用します-利用可能なメモリの種類は何でも。開始できるスレッドの数は、メモリサイズとスレッドごとに必要なメモリの量によって異なります。スレッドが(スタックだけでなく)ヒープを使用する場合は、より多くのメモリが必要です。その場合、より少ないスレッドを開始できます。


@VJonvic:基本的なスレッドの説明の+1。
dragosrsupercool

6

あなたの質問への簡単な答えは、彼らは仮想メモリを使用することです。OSに関連する少数のプロセスを除いて、すべてが仮想メモリを使用します。

一方、スレッド(または任意のプロセス内の任意のスレッド)が実際に実行されているときは、物理メモリを使用しています。そのプロセスに関連付けられたメモリページは、プロセッサが作業を行う物理メモリにスワップインされます。


3

仮想メモリは、RAM スワップスペースの合計です。仮想とは、プログラムが認識するアドレスがRAMチップが認識するアドレスと異なることを意味します。スワップでメモリにアクセスする必要がある場合、OSはメモリを最初にRAMに移動します。スワッピングが不要な場合は、無効にしてください。十分なRAMがあれば、実際には必要ありません。

そうは言っても、10,000コアプロセッサがない限り、10,000スレッドに増やすことは、実際には「最適化」ではありません。すべてのコアを消費するのに十分なスレッドがあり、さらにそれらのスレッドがブロックされたときのためにスペアが1つまたは2つある場合、スレッドを追加すると、スイッチングオーバーヘッドとキャッシュミスのためにパフォーマンスが低下します。プログラムロジックが単純になる場合は、より多くのスレッドを使用することもできますが、パフォーマンスは犠牲になります。


はい、サーバーは32ビットのシングルコアマシンなので、10,000は多すぎます。実際、スレッドは完全なCPUではありません。これらはクローラースレッドであるため、サーバーの応答を待機する場合があります。私はCPUが完全に占有されているが、過負荷または過負荷ではないことを確認することを目指しています。しかし、CPUが解放されているか、完全に占有されているかを知る方法はまだわかりません。ツールやコマンドはありますか?
dragosrsupercool

topコマンドからその情報を取得できると思います。
カールビーレフェルト

@KarlBieledeldt:はい、それはまさに私が求めていたものでした。もう1つのフォローアップの質問:あるスレッドがURLのリクエストを送信し、他のスレッドがサーバーの応答を受信できる場合、私はクロールするというアイデアを思いついただけです。あまり多くのスレッドを使用しないとCPU使用率が高くなります。それは可能ですか?他のスレッドで応答を受信しながら1つのスレッドから要求を送信するようなものですか?
dragosrsupercool

2

Linuxサーバーを最適化して、プロセスごとに10,000スレッドを処理する

他の人が説明したように、これは一般的に間違っています。スレッドは、高価な資源であり、それは自身の持っている、特にので、コールスタック(通常は、メガバイト)を、それがカーネルによってタスクのスケジュールですので。スレッドは、開かれたファイル記述子よりもさらにコストがかかります

オペレーティングシステムを読む:3つの簡単なピース(無料でダウンロードできる教科書)。

経験則として、あなたは多くのスレッドを持ちたくない、そして確かに多くの実行可能なスレッドを持ちたくない。実行可能なスレッドの数は、通常、多くてもコアの数(またはその数倍)にする必要があるため、最大で約12になります。プロセス内のスレッド数はわずかに大きくなる可能性があります。したがって、非常に拡張性の高いサーバー(多くのプロセッサソケットとコアを備えている)がない限り、プロセス(デスクトップ上)に12を超える実行可能なスレッドと100のスレッド(ほとんどがアイドル状態)を持たせたくありません。 。

Linuxでは、スレッドとプロセスは非常によく似ており(どちらもclone(2)で作成できるため)、どちらもカーネルによってスケジュールされたタスクです。実際、カーネルスケジューラは、いくつかのマルチスレッドプロセス内のスレッド、またはシングルスレッドプロセスの単一のメインスレッド(その場合、その単一スレッドを "プロセス"と呼びます)、またはカーネルスレッドであるタスクをスケジュールします。デスクトップシステムで合計1,000を超えるスケジュール可能なタスクを実行したくない場合があります。

Linuxでは、プロセスは、同じ仮想アドレス空間を共有する(およびファイル記述子テーブルなどの他のいくつかのものを共有する)スレッドのグループです。一部のプロセスには1つのスレッドしかありません。

仮想アドレス空間がされて定義された通りウィキペディアで

「オペレーティングシステムがプロセスに提供する仮想アドレスの範囲のセット」

(ただし、この用語は普遍的ではなく、Microsoftの一部のドキュメントでは異なる互換性のない定義を使用していることを説明しているこの回答も参照してください)。

Linuxでは、いくつかのプロセスの仮想アドレス空間を理解するためにproc(5)が役立ちます。両方
cat /proc/self/mapscat /proc/$$/mapsターミナルで試してください。thispmap(1)ps(1)top(1)も参照してください。

すべてのユーザー空間プログラムは、いくつかのプロセスで実行され、仮想メモリを使用しているため、すべてのプロセスには独自の仮想アドレス空間があります。物理RAMはLinuxカーネルによって管理されるリソースであり、アプリケーションはRAMに直接アクセスできません(mmap(2) -ing を除く。mem(4)を/dev/mem参照)。

したがって、プロセスは直接 RAMを使用ません。仮想メモリを使用し、独自の仮想アドレス空間を持っています。カーネルの用途ページング物理RAMの管理するためのページを仮想アドレス空間とプロセスの提供抽象化を。いつでも(プロセスがアイドル状態のときでも、実行中の場合でも)カーネルはいくつかのページをページアウトできます(ディスク上でページをスワップするなど)。カーネルはMMUを構成しています(ディスクからページをフェッチするか、セグメンテーション違反をプロセスに伝達することにより、一部の割り込みハンドラーでページミスハードウェア例外を処理しています。signal (7)を参照してください)

システムスレッドの上にグリーンスレッドを配置することもできます(ただし、グリーンスレッドライブラリの実装とデバッグは困難です)。Goで使用されているゴルーチンを空想的な例として調べてください。setcontext(3)も参照してください。

場合によっては、システムがスラッシングを試すことがあります。これは、(すべてのプロセスで必要な)仮想メモリの合計が使用可能な物理RAMを(大きな要因で)超えた場合に発生します。その後、コンピュータが応答しなくなります。常駐セットのサイズデマンドページングワーキングセットメモリのオーバーコミットメントASLRについてお読みください。

Linux-の-forも参照フォーク(2) クローン(2) MMAP(2) のmadvise(2) posix_fadvise(2) MLOCK(2) はexecve(2) 資格情報(7) pthreadの(7)futex(7)capabilities(7)

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.