14

A私のマシンでは、 が定義されているかどうかに応じて、時間 A と時間 Bが入れ替わります (2 つcallocの が呼び出される順序が変わります)。

私は当初、これをページング システムに起因すると考えていました。mmap奇妙なことに、 の代わりに を使用すると、 calloc状況はさらに奇妙になります。予想どおり、両方のループに同じ時間がかかります。でわかるようstraceに、callocs は最終的に 2 つ mmapの s になるため、return-already-allocated-memory マジックは行われません。

Intel i7 で Debian テストを実行しています。

#include <stdlib.h>
#include <stdio.h>
#include <sys/mman.h>

#include <time.h>

#define SIZE 500002816

#ifndef USE_MMAP
#define ALLOC calloc
#else
#define ALLOC(a, b) (mmap(NULL, a * b, PROT_READ | PROT_WRITE,  \
                          MAP_PRIVATE | MAP_ANONYMOUS, -1, 0))
#endif

int main() {
  clock_t start, finish;
#ifdef A
  int *arr1 = ALLOC(sizeof(int), SIZE);
  int *arr2 = ALLOC(sizeof(int), SIZE);
#else
  int *arr2 = ALLOC(sizeof(int), SIZE);
  int *arr1 = ALLOC(sizeof(int), SIZE);
#endif
  int i;

  start = clock();
  {
    for (i = 0; i < SIZE; i++)
      arr1[i] = (i + 13) * 5;
  }
  finish = clock();

  printf("Time A: %.2f\n", ((double)(finish - start))/CLOCKS_PER_SEC);

  start = clock();
  {
    for (i = 0; i < SIZE; i++)
      arr2[i] = (i + 13) * 5;
  }
  finish = clock();

  printf("Time B: %.2f\n", ((double)(finish - start))/CLOCKS_PER_SEC);

  return 0;
}

私が得る出力:

 ~/directory $ cc -Wall -O3 bench-loop.c -o bench-loop
 ~/directory $ ./bench-loop 
Time A: 0.94
Time B: 0.34
 ~/directory $ cc -DA -Wall -O3 bench-loop.c -o bench-loop
 ~/directory $ ./bench-loop                               
Time A: 0.34
Time B: 0.90
 ~/directory $ cc -DUSE_MMAP -DA -Wall -O3 bench-loop.c -o bench-loop
 ~/directory $ ./bench-loop                                          
Time A: 0.89
Time B: 0.90
 ~/directory $ cc -DUSE_MMAP -Wall -O3 bench-loop.c -o bench-loop 
 ~/directory $ ./bench-loop                                      
Time A: 0.91
Time B: 0.92
4

5 に答える 5

10

mallocまた、の代わりにを使用してテストする必要がありcallocます。行うことの1つcallocは、割り当てられたメモリをゼロで埋めることです。

あなたの場合、calloc最後にarr1を割り当ててから割り当てると、それが最後に割り当てられてゼロで埋められたため、すでにキャッシュメモリにフォールトされていると思います。最初にcallocarr1を、次にarr2を実行すると、arr2がゼロで埋められると、arr1がキャッシュからプッシュされます。

于 2012-04-10T20:59:07.133 に答える
6

特に少ないほど多いので、私はもっと多く、またはもっと少なく書くことができたと思います。

理由はシステムごとに異なる場合があります。でも; 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();

(いいえ、熟女ではありません)、これを表示できます(注ArenaHblkhd、…):

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がこのページの一部に書き込むと、ダーティビットが設定されます。したがって、ダーティビットでスワップされたページが書き込まれると、クリーンなページはスキップされます。


于 2012-04-18T17:17:39.967 に答える
3

プロセス メモリ イメージがページ単位で拡張されるのは、単に問題です。

于 2012-04-10T20:57:58.140 に答える
3

簡潔な答え

初めてcalloc呼び出されると、明示的にメモリがゼロになります。次に呼び出されたときは、返されたメモリmmapがすでにゼロになっていると想定されていました。

詳細

必要に応じて自分で試すことができるという結論に達するために私がチェックしたことのいくつかを次に示します。

  1. calloc最初の通話の前に通話を挿入しALLOCます。この後、時間 A と時間 B の時間が同じであることがわかります。

  2. clock()関数を使用して、各ALLOC呼び出しにかかる時間を確認します。両方が使用している場合calloc、最初の呼び出しは 2 番目の呼び出しよりもはるかに時間がかかることがわかります。

  3. バージョンとバージョンtimeの実行時間を計測するために使用します。これを行ったところ、 の実行時間が一貫してわずかに短かったことがわかりました。callocUSE_MMAPUSE_MMAP

  4. strace -tt -Tシステムコールが行われた時間と、それにかかった時間の両方を示しています。出力の一部を次に示します。

トレース出力:

21:29:06.127536 mmap(NULL, 2000015360, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fff806fd000 <0.000014>
21:29:07.778442 mmap(NULL, 2000015360, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fff093a0000 <0.000021>
21:29:07.778563 times({tms_utime=63, tms_stime=102, tms_cutime=0, tms_cstime=0}) = 4324241005 <0.000011>

mmap最初の呼び出しには数秒かかったことがわかりますが、次のシステム コールまでに0.000014約数秒かかりました。1.5その後、2 番目のmmap呼び出しに数秒かかり、数百マイクロ秒後に呼び出し0.000021が続きました。times

また、 を使用してアプリケーション実行の一部をステップ実行しgdbたところ、 への最初の呼び出しcallocで が多数呼び出され、 へmemsetの 2 番目の呼び出しでは が呼び出されcallocなかったことがわかりましたmemset。興味のある方は、calloc こちら( を探してください)のソース コードを参照してください。__libc_calloc最初の呼び出しで実行しているのに、その後の呼び出しを実行していない理由についてcallocmemsetわかりません。しかし、これがあなたが尋ねた行動を説明していると確信しています。

ゼロ化された配列がパフォーマンスを向上させた理由については、配列がmemset非常に大きいため、値がキャッシュではなく TLB にロードされたためだと推測されます。あなたが尋ねたパフォーマンスの違いの具体的な理由は、calloc実行時の2つの呼び出しの動作が異なることです。

于 2012-04-18T21:50:21.977 に答える
2

概要:配列の割り当てにかかる時間を分析すると、時間差が説明されます。最後に割り当てられたcallocにはもう少し時間がかかりますが、他の(またはmmapを使用する場合はすべて)ほとんど時間がかかりません。メモリ内の実際の割り当ては、おそらく最初にアクセスしたときに延期されます。

Linux の内部メモリ割り当てについてはよくわかりません。しかし、スクリプトを少し変更して実行しました。3 番目の配列と、配列操作ごとに追加の反復を追加しました。そして、配列を割り当てる時間が考慮されていなかったというOld Proの発言を考慮しました。

結論: calloc を使用すると、割り当てに mmap を使用するよりも時間がかかります (mmap virtualy は、メモリを割り当てるときに時間を使用しません。おそらく、最初にアクセスしたときに後で延期されます)。全体的なプログラム実行のために。

とにかく、最初の注意点として、メモリ割り当てはヒープではなくメモリマッピング領域で行われます。これを確認するために、プロセス (/proc//maps) のメモリ マッピングを確認できるように、クイック n' ダーティ ポーズを追加しました。

あなたの質問に、callocで最後に割り当てられた配列は実際にメモリに割り当てられているようです(延期されていません)。arr1 と arr2 はまったく同じように動作するようになりました (最初の反復は遅く、その後の反復は高速です)。Arr3 は、メモリが以前に割り当てられたため、最初の反復で高速です。A マクロを使用する場合、この恩恵を受けるのは arr1 です。私の推測では、カーネルが最後の calloc のためにメモリ内の配列を事前に割り当てていると思います。なんで?わかりません...1つの配列だけでもテストしました(したがって、arr2とarr3のすべての出現を削除しました)。arr1の10回の反復すべてで(ほぼ)同じ時間です。

malloc と mmap はどちらも同じように動作し (結果は以下に示していません)、最初の反復は遅く、その後の反復は 3 つの配列すべてで高速です。

注: すべての結果は、さまざまな gcc 最適化フラグ (-O0 から -O3) にわたって一貫していたため、動作の根本がある種の gcc 最適化に由来するようには見えません。

注 2: GCC 4.6.3 を使用した Ubuntu Precise Pangolin (カーネル 3.2) でのテスト実行

#include <stdlib.h>
#include <stdio.h>
#include <sys/mman.h>

#include <time.h>

#define SIZE 500002816
#define ITERATION 10

#if defined(USE_MMAP)
#  define ALLOC(a, b) (mmap(NULL, a * b, PROT_READ | PROT_WRITE,  \
                          MAP_PRIVATE | MAP_ANONYMOUS, -1, 0))
#elif defined(USE_MALLOC)
#  define ALLOC(a, b) (malloc(b * a))
#elif defined(USE_CALLOC)
#  define ALLOC calloc
#else
#  error "No alloc routine specified"
#endif

int main() {
  clock_t start, finish, gstart, gfinish;
  start = clock();
  gstart = start;
#ifdef A
  unsigned int *arr1 = ALLOC(sizeof(unsigned int), SIZE);
  unsigned int *arr2 = ALLOC(sizeof(unsigned int), SIZE);
  unsigned int *arr3 = ALLOC(sizeof(unsigned int), SIZE);
#else
  unsigned int *arr3 = ALLOC(sizeof(unsigned int), SIZE);
  unsigned int *arr2 = ALLOC(sizeof(unsigned int), SIZE);
  unsigned int *arr1 = ALLOC(sizeof(unsigned int), SIZE);
#endif
  finish = clock();
  unsigned int i, j;
  double intermed, finalres;

  intermed = ((double)(finish - start))/CLOCKS_PER_SEC;
  printf("Time to create: %.2f\n", intermed);

  printf("arr1 addr: %p\narr2 addr: %p\narr3 addr: %p\n", arr1, arr2, arr3);

  finalres = 0;
  for (j = 0; j < ITERATION; j++)
  {
    start = clock();
    {
      for (i = 0; i < SIZE; i++)
        arr1[i] = (i + 13) * 5;
    }
    finish = clock();

    intermed = ((double)(finish - start))/CLOCKS_PER_SEC;
    finalres += intermed;
    printf("Time A: %.2f\n", intermed);
  }

  printf("Time A (average): %.2f\n", finalres/ITERATION);


  finalres = 0;
  for (j = 0; j < ITERATION; j++)
  {
    start = clock();
    {
      for (i = 0; i < SIZE; i++)
        arr2[i] = (i + 13) * 5;
    }
    finish = clock();

    intermed = ((double)(finish - start))/CLOCKS_PER_SEC;
    finalres += intermed;
    printf("Time B: %.2f\n", intermed);
  }

  printf("Time B (average): %.2f\n", finalres/ITERATION);


  finalres = 0;
  for (j = 0; j < ITERATION; j++)
  {
    start = clock();
    {
      for (i = 0; i < SIZE; i++)
        arr3[i] = (i + 13) * 5;
    }
    finish = clock();

    intermed = ((double)(finish - start))/CLOCKS_PER_SEC;
    finalres += intermed;
    printf("Time C: %.2f\n", intermed);
  }

  printf("Time C (average): %.2f\n", finalres/ITERATION);

  gfinish = clock();

  intermed = ((double)(gfinish - gstart))/CLOCKS_PER_SEC;
  printf("Global Time: %.2f\n", intermed);

  return 0;
}

結果:

USE_CALLOC の使用

Time to create: 0.13
arr1 addr: 0x7fabcb4a6000
arr2 addr: 0x7fabe917d000
arr3 addr: 0x7fac06e54000
Time A: 0.67
Time A: 0.48
...
Time A: 0.47
Time A (average): 0.48
Time B: 0.63
Time B: 0.47
...
Time B: 0.48
Time B (average): 0.48
Time C: 0.45
...
Time C: 0.46
Time C (average): 0.46

USE_CALLOC と A を使用

Time to create: 0.13
arr1 addr: 0x7fc2fa206010
arr2 addr: 0xx7fc2dc52e010
arr3 addr: 0x7fc2be856010
Time A: 0.44
...
Time A: 0.43
Time A (average): 0.45
Time B: 0.65
Time B: 0.47
...
Time B: 0.46
Time B (average): 0.48
Time C: 0.65
Time C: 0.48
...
Time C: 0.45
Time C (average): 0.48

USE_MMAP の使用

Time to create: 0.0
arr1 addr: 0x7fe6332b7000
arr2 addr: 0x7fe650f8e000
arr3 addr: 0x7fe66ec65000
Time A: 0.55
Time A: 0.48
...
Time A: 0.45
Time A (average): 0.49
Time B: 0.54
Time B: 0.46
...
Time B: 0.49
Time B (average): 0.50
Time C: 0.57
...
Time C: 0.40
Time C (average): 0.43
于 2012-04-16T13:18:26.400 に答える