9

さまざまなオペレーティング システムでのメモリ管理に問題があります。

私のプログラムは、数 GB のメモリを必要とする処理を行うサーバーです。その後、別のリクエストが到着するまで数時間待機する間、ほとんどのメモリを解放します。

AIX と Solaris では、次のような動作が見られます。

メモリを解放しても、メモリがオペレーティング システムに戻されません。プロセスが使用する仮想メモリの量は常に増加し、減少することはありません。物理メモリについても、限界まで同じことが言えます。したがって、スリープモードでもこのメモリをすべて使用しているように見えます。

このメモリを OS に戻すことができるのはいつですか? どうすれば作れますか?

Linux は違います。時々メモリを返すようですが、いつ、どのように返すのかわかりません。たとえば、リクエスト前のプロセスが 100MB で、ピーク時には 700MB であり、すべてを解放した後は 600MB に減少したというシナリオがあります。私には理解できません。Linux が OS にメモリを返還するのであれば、なぜすべてを返さないのでしょうか?

4

5 に答える 5

13

glibc ライブラリ (通常、Linux の標準 C ライブラリとして使用されます) は、sbrk() または mmap() を使用する 2 つの方法でメモリを割り当てることができます。十分な大きさの割り当てには mmap() を使用します。

sbrk() で割り当てられたメモリは、簡単に放棄することはできません (特別な場合にのみ、glibc が試みさえしないことがわかっている限り)。mmap() で割り当てられたメモリは、munmap() を使用して返すことができます。

OS にメモリを返せることに依存している場合は、malloc() の代わりに直接 mmap() を使用できます。しかし、小さなブロックをたくさん割り当てると効率が悪くなります。mmap() の上に独自のプール アロケータを実装する必要がある場合があります。

于 2012-08-21T08:56:57.527 に答える
5

ほとんどの場合、プロセスが終了するまでメモリはシステムに返されません。オペレーティング システムとランタイム ライブラリによっては、メモリがシステムに返される可能性がありますが、これを確実に行うための信頼できる方法はわかりません。

処理に数 GB のメモリが必要な場合は、サーバーにリクエストを待機させてから、データを処理するための新しいプロセスを生成します。パイプを使用してサーバーと通信できます。処理が完了したら、結果を返し、生成されたプロセスを終了します。

于 2012-08-21T08:57:11.473 に答える
2

メモリが割り当てられる(そしておそらくOSに戻される)方法はlibcにあると思います。使用しているプログラミング言語/ライブラリ スタックが原因である可能性があります。

glibc はヒープの一番上に断片化されていないメモリを返すと思います。プロセスは、常に使用する 10MB のデータを割り当てる場合があります。その後、処理に使用する 500MB のデータが割り当てられます。その後、処理後も保持されるデータの小さな断片 (処理の結果である可能性があります) が割り当てられます。その後、さらに 500MB が割り当てられます。メモリ レイアウトは次のとおりです。

|10MB使用|500MB処理|1MB結果|500MB処理| = 合計 1011 MB

1000MB が解放されると、メモリ レイアウトは次のようになります。

|10MB使用|500MB解放|1MB結果|500MB解放| glibc は最後にメモリを返す可能性があります... |10MB 使用|500MB 解放|1MB 結果| = 511 MB 「使用中」でも、そのうち 11 MB しか使用されていません。

すべてのメモリが解放されるようにするには、さらに調査を行う必要があります (個別のメモリ プールが思い浮かびます)。

于 2012-08-21T08:28:10.823 に答える
0

これを行うための唯一の信頼できる移植可能な方法は、リクエストを処理する新しいプロセスを生成することだと思います。プロセスが終了すると、OS は関連するすべてのメモリを取得します。

残念ながら、このプロセスの生成とプロセス間通信に関連する非効率性があります(多くの処理を行っていることに注意してください-これがプロセス間通信にかなりのデータ要件があることを意味するかどうかはわかりません)。ただし、必要なメモリ動作が得られます。同一のJVM バイナリ イメージを生成する場合、OS は実際の JVM によって消費されるメモリを複製しないことに注意してください。

于 2012-08-21T08:32:09.230 に答える
0

ページネーションがどのように機能するかを確認する必要があります。getpagesize() より小さい場合、メモリを返すことはできません。

于 2013-02-06T10:12:54.827 に答える