Иногда бывает полезно макетировать что-то с небольшой программой на C, которая использует большой кусок статической памяти. Я заметил, что после перехода на Fedora 15 программа заняла много времени компиляции. Мы говорим о 30s против 0.1s. Еще более странным было то, что ld ( компоновщик) максимизировал процессор и медленно начал есть все доступные Память. После некоторых попыток я справился найти корреляцию между этой новой проблемой и размером моего свопа файл. Вот пример программы для целей этого обсуждения:
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#define M 1000000
#define GIANT_SIZE (200*M)
size_t g_arr[GIANT_SIZE];
int main( int argc, char **argv){
int i;
for(i = 0; i<10; i++){
printf("This should be zero: %d\n",g_arr[i]);
}
exit(1);
}
Эта программа имеет гигантский массив с объявленным размером около 200 * 8 МБ = 1,6 ГБ статической памяти. Компиляция этой программы требует чрезмерное количество времени:
[[email protected]]$ time gcc HugeTest.c
real 0m12.954s
user 0m6.995s
sys 0m3.890s
[[email protected]]$
13s Для 13-строчной программы C!? Это не так. Номер ключа - это размер статического пространства памяти. Как только он будет больше, чем общее пространство подкачки, оно начинает быстро компилироваться. Например, я имеют 5,3 Гбайт пространства подкачки, поэтому изменение GIANT_SIZE на (1000 * M) дает следующее время:
[[email protected]]$ time gcc HugeTest.c
real 0m0.087s
user 0m0.026s
sys 0m0.027s
А, это больше нравится! Чтобы еще больше убедить себя (и себя, если вы пытаетесь сделать это дома), что место подкачки было действительно волшебным номер, я попытался изменить доступное пространство подкачки на действительно массивное 19GB и попытаться скомпилировать версию (1000 * M):
[[email protected]]$ ls -ali /extraswap
5986 -rw-r--r-- 1 root root 14680064000 Jul 26 15:01 /extraswap
[[email protected]]$ sudo swapon /extraswap
[[email protected]]$ time gcc HugeTest.c
real 4m28.089s
user 0m0.016s
sys 0m0.010s
Это не закончилось даже через 4,5 минуты!
Очевидно, что компоновщик делает что-то неправильно здесь, но я не знаю, как чтобы обойти это иначе, чем переписывать программу или возиться с местом подкачки. Мне бы хотелось узнать, есть ли решение, или если у меня есть наткнулся на какую-то загадочную ошибку.
Кстати, все программы компилируются и выполняются корректно, независимо от всего своп-бизнеса.
Для справки, вот, возможно, релевантная информация:
[]$ ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 27027
max locked memory (kbytes, -l) 64
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) 1024
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
[]$ uname -r
2.6.40.6-0.fc15.x86_64
[]$ ld --version
GNU ld version 2.21.51.0.6-6.fc15 20110118
Copyright 2011 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License version 3 or (at your option) a later version.
This program has absolutely no warranty.
[]$ gcc --version
gcc (GCC) 4.6.1 20110908 (Red Hat 4.6.1-9)
Copyright (C) 2011 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
[]$ cat /proc/meminfo
MemTotal: 3478272 kB
MemFree: 1749388 kB
Buffers: 16680 kB
Cached: 212028 kB
SwapCached: 368056 kB
Active: 489688 kB
Inactive: 942820 kB
Active(anon): 401340 kB
Inactive(anon): 803436 kB
Active(file): 88348 kB
Inactive(file): 139384 kB
Unevictable: 32 kB
Mlocked: 32 kB
SwapTotal: 19906552 kB
SwapFree: 17505120 kB
Dirty: 172 kB
Writeback: 0 kB
AnonPages: 914972 kB
Mapped: 60916 kB
Shmem: 1008 kB
Slab: 55248 kB
SReclaimable: 26720 kB
SUnreclaim: 28528 kB
KernelStack: 3608 kB
PageTables: 63344 kB
NFS_Unstable: 0 kB
Bounce: 0 kB
WritebackTmp: 0 kB
CommitLimit: 21645688 kB
Committed_AS: 11208980 kB
VmallocTotal: 34359738367 kB
VmallocUsed: 139336 kB
VmallocChunk: 34359520516 kB
HardwareCorrupted: 0 kB
AnonHugePages: 151552 kB
HugePages_Total: 0
HugePages_Free: 0
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB
DirectMap4k: 730752 kB
DirectMap2M: 2807808 kB
TL; DR: Когда (большая) статическая память программы c немного меньше, чем доступное пространство подкачки, компоновщик навсегда связывает программу. Тем не менее, это довольно быстро, когда статическое пространство немного больше, чем доступное пространство подкачки. Что с этим!?