mojavy.com

malloc+memsetとcallocの違いについて

March 05, 2014 at 09:25 PM | categories: os, programming |

malloccallocの違いは、表面的には引数の数とcallocは確保した領域を0で初期化するという点くらいですが、以下のコードを大きなnで実行すると、今時のOSだとmalloc + memsetのほうが大幅に遅くなる可能性があります。

void *p = malloc(n * sizeof(type));
memset(p, 0, n * sizeof(type));
void *p = calloc(n, sizeof(type));

カーネルはセキュリティ上の理由からメモリを0で初期化してからユーザプロセスに渡します。

しかし、仮想メモリをサポートしたシステムでは、実際にそのメモリに書き込みが発生するまでカーネルはread onlyな領域を複数プロセスで共有させることができるため、既に初期化してあるページであればこの処理を省略できる場合があります。

brkで拡張した領域は0で初期化されているので、callocは新規確保した領域は初期化を省略することができ、結果的にcallocを実行したタイミングでは初期化が実際にはほとんど発生しない、ということがありえます。

一方memsetの場合は実際にメモリへの書込みが発生する上、ページの共有もできなくなるためswapする可能性もあります。



ちなみに、(カーネルではなく)calloc自身が0初期化する処理と、memsetの処理は微妙に違います。 なぜなら、memsetは対象の領域がアラインされているかどうかについての情報なしに処理する必要があるので、境界部分は1byteずつやるしかありません。

じゃあmemsetのほうが遅いのかというと、コンパイラによってはアラインされていることを推測できる場合もあったり、callocはライブラリ関数なので移植性のために最適化しにくかったりするので、結局のところ微妙です。

参考: http://stackoverflow.com/questions/2688466/why-mallocmemset-is-slower-than-calloc


blog comments powered by Disqus

About Me

pic
mojavy

Recent posts






Categories



Badges