特に少ないほど多いので、私はもっと多く、またはもっと少なく書くことができたと思います。
理由はシステムごとに異なる場合があります。でも; clibの場合:
各操作に使用される合計時間はその逆です。calloc
+反復の時間を計る場合。
すなわち:
Calloc arr1 : 0.494992654
Calloc arr2 : 0.000021250
Itr arr1 : 0.430646035
Itr arr2 : 0.790992411
Sum arr1 : 0.925638689
Sum arr2 : 0.791013661
Calloc arr1 : 0.503130736
Calloc arr2 : 0.000025906
Itr arr1 : 0.427719162
Itr arr2 : 0.809686047
Sum arr1 : 0.930849898
Sum arr2 : 0.809711953
calloc
その後、最初のmalloc
実行時間は2番目の実行時間よりも長くなります。つまりmalloc(0)
、前calloc
などの呼び出しは、同じプロセスで同様の呼び出しに使用される時間を均等にしmalloc
ます(以下の説明)。
ただし、複数の呼び出しを続けて行うと、これらの呼び出しの時間がわずかに短くなることがあります。
ただし、反復時間はフラットになります。
つまり、要するに; 使用されるシステムの合計時間は、最初に割り当てられた時間の中で最も長くなります。ただし、これはプロセスの制限で回避できないオーバーヘッドです。
たくさんのメンテナンスが行われています。いくつかのケースについて簡単に説明します。
ページの短い
プロセスがメモリを要求すると、仮想アドレス範囲が提供されます。この範囲は、ページテーブルによって物理メモリに変換されます。ページがバイトごとに変換されると、すぐに巨大なページテーブルが取得されます。これが、メモリ範囲がチャンクまたはページで提供される理由の1つです。ページサイズはシステムによって異なります。アーキテクチャは、さまざまなページサイズを提供することもできます。
上記のコードの実行を見て、/ proc / PID / statからの読み取りを追加すると、
これが実際に動作していることがわかります(特にRSSに注意してください)。
PID Stat {
PID : 4830 Process ID
MINFLT : 214 Minor faults, (no page memory read)
UTIME : 0 Time user mode
STIME : 0 Time kernel mode
VSIZE : 2039808 Virtual memory size, bytes
RSS : 73 Resident Set Size, Number of pages in real memory
} : Init
PID Stat {
PID : 4830 Process ID
MINFLT : 51504 Minor faults, (no page memory read)
UTIME : 4 Time user mode
STIME : 33 Time kernel mode
VSIZE : 212135936 Virtual memory size, bytes
RSS : 51420 Resident Set Size, Number of pages in real memory
} : Post calloc arr1
PID Stat {
PID : 4830 Process ID
MINFLT : 51515 Minor faults, (no page memory read)
UTIME : 4 Time user mode
STIME : 33 Time kernel mode
VSIZE : 422092800 Virtual memory size, bytes
RSS : 51428 Resident Set Size, Number of pages in real memory
} : Post calloc arr2
PID Stat {
PID : 4830 Process ID
MINFLT : 51516 Minor faults, (no page memory read)
UTIME : 36 Time user mode
STIME : 33 Time kernel mode
VSIZE : 422092800 Virtual memory size, bytes
RSS : 51431 Resident Set Size, Number of pages in real memory
} : Post iteration arr1
PID Stat {
PID : 4830 Process ID
MINFLT : 102775 Minor faults, (no page memory read)
UTIME : 68 Time user mode
STIME : 58 Time kernel mode
VSIZE : 422092800 Virtual memory size, bytes
RSS : 102646 Resident Set Size, Number of pages in real memory
} : Post iteration arr2
PID Stat {
PID : 4830 Process ID
MINFLT : 102776 Minor faults, (no page memory read)
UTIME : 68 Time user mode
STIME : 69 Time kernel mode
VSIZE : 2179072 Virtual memory size, bytes
RSS : 171 Resident Set Size, Number of pages in real memory
} : Post free()
ご覧のとおり、実際にメモリに割り当てられたページは、arr2
ページ要求の待機のために延期されています。これは反復が始まるまで続きます。malloc(0)
before
calloc
を追加すると、arr1
反復前にどちらの配列も物理メモリに割り当てられないことを登録できます。
ページが使用されない可能性があるため、要求に応じてマッピングを行う方が効率的です。これが、プロセスが実行するときにcalloc
十分な数のページが予約されているが、必ずしも実際に実際のメモリに割り当てられているとは限らない理由です。
アドレスが参照されると、ページテーブルが参照されます。アドレスが割り当てられていないページにある場合、システムはページフォールトを処理し、その後ページが割り当てられます。割り当てられたページの合計は、常駐セットサイズ(RSS)と呼ばれます。
配列の1/4を反復(タッチ)することで、配列を実験できます。ここでもmalloc(0)
、前に追加しましcalloc
た。
Pre iteration 1/4:
RSS : 171 Resident Set Size, Number of pages in real meory
for (i = 0; i < SIZE / 4; ++i)
arr1[i] = 0;
Post iteration 1/4:
RSS : 12967 Resident Set Size, Number of pages in real meory
Post iteration 1/1:
RSS : 51134 Resident Set Size, Number of pages in real meory
さらに高速化するために、ほとんどのシステムは、最新のN個のページテーブルエントリをトランスレーションルックアサイドバッファ(TLB)に追加でキャッシュします。
brk、mmap
プロセス(c|m|…)alloc
の場合、ヒープの上限は
brk()
またはによって拡張されsbrk()
ます。これらのシステムコールはコストがかかり、これを補うために、malloc
複数の小さな呼び出しを1つの大きなbrk()に収集します。
これはfree()
、ネガティブにも影響を及ぼしbrk()
ます。また、リソースが高価であり、より大きな操作として収集および実行されます。
巨大な要求のために; つまり、コードのように、malloc()
を使用しmmap()
ます。
これのしきい値は、によって構成可能mallopt()
であり、知識に基づいた値です。
コード内のを変更することを楽しむことができSIZE
ます。利用して使用すれば
malloc.h
、
struct mallinfo minf = mallinfo();
(いいえ、熟女ではありません)、これを表示できます(注Arena
とHblkhd
、…):
Initial:
mallinfo {
Arena : 0 (Bytes of memory allocated with sbrk by malloc)
Ordblks : 1 (Number of chunks not in use)
Hblks : 0 (Number of chunks allocated with mmap)
Hblkhd : 0 (Bytes allocated with mmap)
Uordblks: 0 (Memory occupied by chunks handed out by malloc)
Fordblks: 0 (Memory occupied by free chunks)
Keepcost: 0 (Size of the top-most releasable chunk)
} : Initial
MAX = ((128 * 1024) / sizeof(int))
mallinfo {
Arena : 0 (Bytes of memory allocated with sbrk by malloc)
Ordblks : 1 (Number of chunks not in use)
Hblks : 1 (Number of chunks allocated with mmap)
Hblkhd : 135168 (Bytes allocated with mmap)
Uordblks: 0 (Memory occupied by chunks handed out by malloc)
Fordblks: 0 (Memory occupied by free chunks)
Keepcost: 0 (Size of the top-most releasable chunk)
} : After malloc arr1
mallinfo {
Arena : 0 (Bytes of memory allocated with sbrk by malloc)
Ordblks : 1 (Number of chunks not in use)
Hblks : 2 (Number of chunks allocated with mmap)
Hblkhd : 270336 (Bytes allocated with mmap)
Uordblks: 0 (Memory occupied by chunks handed out by malloc)
Fordblks: 0 (Memory occupied by free chunks)
Keepcost: 0 (Size of the top-most releasable chunk)
} : After malloc arr2
次に、から減算sizeof(int)
しMAX
て次のようになります。
mallinfo {
Arena : 266240 (Bytes of memory allocated with sbrk by malloc)
Ordblks : 1 (Number of chunks not in use)
Hblks : 0 (Number of chunks allocated with mmap)
Hblkhd : 0 (Bytes allocated with mmap)
Uordblks: 131064 (Memory occupied by chunks handed out by malloc)
Fordblks: 135176 (Memory occupied by free chunks)
Keepcost: 135176 (Size of the top-most releasable chunk)
} : After malloc arr1
mallinfo {
Arena : 266240 (Bytes of memory allocated with sbrk by malloc)
Ordblks : 1 (Number of chunks not in use)
Hblks : 0 (Number of chunks allocated with mmap)
Hblkhd : 0 (Bytes allocated with mmap)
Uordblks: 262128 (Memory occupied by chunks handed out by malloc)
Fordblks: 4112 (Memory occupied by free chunks)
Keepcost: 4112 (Size of the top-most releasable chunk)
} : After malloc arr2
システムが宣伝どおりに機能することを登録します。割り当てのサイズがしきい値を下回っている場合sbrk
は使用され、メモリは内部で処理されます。malloc
それ以外のmmap
場合は使用されます。
この構造は、メモリの断片化などの防止にも役立ちます。
malloc
ファミリは一般的な使用法に最適化されているという点がポイントです。ただし
mmap
、特別なニーズに合わせて制限を変更できます。
mmapしきい値を変更する場合は、これに注意してください(100行以上を下る)。。
これは、タイミングを実行する前にarr1とarr2のすべてのページを埋める(タッチする)とさらに観察できます。
Touch pages … (Here with page size of 4 kB)
for (i = 0; i < SIZE; i += 4096 / sizeof(int)) {
arr1[i] = 0;
arr2[i] = 0;
}
Itr arr1 : 0.312462317
CPU arr1 : 0.32
Itr arr2 : 0.312869158
CPU arr2 : 0.31
以下も参照してください。
サブノート:
では、CPUは物理アドレスを知っていますか?いや。
記憶の世界では、多くのことに取り組む必要があります;)。このためのコアハードウェアは、メモリ管理ユニット(MMU)です。CPUまたは外部チップの統合された部分として。
オペレーティングシステムは、起動時にMMUを構成し、さまざまな領域(読み取り専用、読み取り/書き込みなど)のアクセスを定義して、一定レベルのセキュリティを提供します。
私たち人間が見るアドレスは、CPUが使用する論理アドレスです。MMUはこれを物理アドレスに変換します。
CPUのアドレスは、ページアドレスとオフセットの2つの部分で構成されています。[PAGE_ADDRESS.OFFSET]
そして、物理アドレスを取得するプロセスは、次のようになります。
.-----. .--------------.
| CPU > --- Request page 2 ----> | MMU |
+-----+ | Pg 2 == Pg 4 |
| +------v-------+
+--Request offset 1 -+ |
| (Logical page 2 EQ Physical page 4)
[ ... ] __ | |
[ OFFSET 0 ] | | |
[ OFFSET 1 ] | | |
[ OFFSET 2 ] | | |
[ OFFSET 3 ] +--- Page 3 | |
[ OFFSET 4 ] | | |
[ OFFSET 5 ] | | |
[ OFFSET 6 ]__| ___________|____________+
[ OFFSET 0 ] | |
[ OFFSET 1 ] | ...........+
[ OFFSET 2 ] |
[ OFFSET 3 ] +--- Page 4
[ OFFSET 4 ] |
[ OFFSET 5 ] |
[ OFFSET 6 ]__|
[ ... ]
CPUの論理アドレス空間は、アドレス長に直接リンクされています。32ビットアドレスプロセッサには、232バイトの論理アドレス空間があります。物理アドレス空間は、システムが許容できるメモリの量です。
断片化されたメモリの処理、再調整などもあります。
これにより、スワップファイルの世界に入ることができます。プロセスがより多くのメモリを要求した場合、物理的に利用可能です。他のプロセスの1つまたは複数のページがディスク/スワップに転送され、それらのページは要求しているプロセスによって「盗まれ」ます。MMUはこれを追跡します。したがって、CPUはメモリが実際にどこにあるかを心配する必要はありません。
これはさらに私たちを汚い記憶に導きます。
/ proc / [pid] / smapsからいくつかの情報を出力すると、より具体的には、配列の範囲は次のようになります。
Start:
b76f3000-b76f5000
Private_Dirty: 8 kB
Post calloc arr1:
aaeb8000-b76f5000
Private_Dirty: 12 kB
Post calloc arr2:
9e67c000-b76f5000
Private_Dirty: 20 kB
Post iterate 1/4 arr1
9e67b000-b76f5000
Private_Dirty: 51280 kB
Post iterate arr1:
9e67a000-b76f5000
Private_Dirty: 205060 kB
Post iterate arr2:
9e679000-b76f5000
Private_Dirty: 410096 kB
Post free:
9e679000-9e67d000
Private_Dirty: 16 kB
b76f2000-b76f5000
Private_Dirty: 12 kB
仮想ページが作成されると、システムは通常、ページのダーティビットをクリアします。
CPUがこのページの一部に書き込むと、ダーティビットが設定されます。したがって、ダーティビットでスワップされたページが書き込まれると、クリーンなページはスキップされます。