どうもあまり有名ではないらしいので、ここで書いてみる。

http://mkosaki.blog46.fc2.com/blog-entry-241.html
で書いた事とほぼ同じだけれど。

Linuxにおいて、CPU負荷を測定するベンチマークでは以下の環境変数を設定すると往々にして性能があがる。

% setenv MALLOC_TRIM_THRESHOLD_ -1
% setenv MALLOC_MMAP_MAX_ 0

MALLOC_TRIM_THRESHOLD_ はOSに未使用になったメモリを返却する契機をあらわしていて、-1は決して返却しない事を表す。
MALLOC_MMAP_MAX_ は最大mmap数で0は決してmmapせず、どんなに大きなメモリでもbrkを使ってメモリを取る事を意味する。

で、性能に効くのは(たいてい)MALLOC_MMAP_MAX_のほう。
glibcはアンチフラグメンテーションの観点から一定以上(たしかデフォルト1M)の大きさのmallocは内部で直接mmap呼び出しをするように変換される。
で、これがある種の状況下では、2重の意味で悪い効果をもたらす。

1.キャッシュコンフリクト
  まあ、実装がへこいのですがmmap呼び出すときにキャッシュカラーリングのコードが
  はいってないんです。
  なので、戻り値アドレスが全部ページバウンダリにそろってしまっています。
  なので複数スレッドがmalloc復帰値を同じようなアクセスパターンでアクセスしていくと
  がんがんキャッシュコンフリクトします。

2.munmapネック
  mmapしたやつはbrkでとったやつと違い、フリーリスト管理はせずに、アプリがfree(3)を
  呼んだら、すぐさまOSにmunmapする実装になっています。
  で、特に大規模SMPにおいて、munmapはmmapと違ってlazyに処理できないので、
  非常にコストが高い操作である。と
  大抵のアーキで全CPUに割り込みとばして空間そぎ落として返事がくるのをじっと
  まっているので。
  かつ、Linuxにおいてドライバが数ミリ秒ぐらい割禁とかするのはめずらしくないので、
  一番遅いCPUに引っ張られてますます遅くなる。

もちろん、この環境変数を設定するとヒープフラグメンテーションが進みやすくなるので365日動き続ける業務アプリで設定するものは考え物であるが、ベンチマークの数字的には結構効果があるので、ベンチマーク屋さんは、オマジナイ代わりに試してみる価値はある。





こまったときのおまじない
おまじない代わり! ランキング!