Производительность линкера связана с пространством подкачки?

Иногда полезно смоделировать что-то с помощью небольшой программы на C, которая использует большой кусок статической памяти. Я заметил, что после перехода на Fedora 15 программа занимает много времени, чтобы компиляции. Речь идет о 30 с против 0,1 с. Еще более странным было то, что 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 ГБ статической памяти. Компиляция этой программы занимает неумеренное количество времени:

[me@bleh]$ time gcc HugeTest.c 

real    0m12.954s
user    0m6.995s
sys 0m3.890s

[me@bleh]$

13 секунд для ~13-строчной программы на C!? Это неправильно. Ключевым числом является размер статической памяти. Как только он становится больше, чем общего пространства подкачки, программа снова начинает компилироваться быстро. Например, у меня у меня 5,3 ГБ пространства подкачки, поэтому изменение GIANT_SIZE на (1000*M) дает следующее следующее время:

[me@bleh]$ time gcc HugeTest.c 

real    0m0.087s
user    0m0.026s
sys 0m0.027s

Ах, вот это уже лучше! Чтобы еще больше убедить себя (и себя, если вы пробуете это дома), что пространство подкачки действительно является магическим число, я попробовал изменить доступное пространство подкачки на действительно огромное 19 ГБ и снова попытался скомпилировать версию (1000*M):

[me@bleh]$ ls -ali /extraswap 
5986 -rw-r--r-- 1 root root 14680064000 Jul 26 15:01 /extraswap
[me@bleh]$ sudo swapon /extraswap 
[me@bleh]$ 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 немного меньше, чем доступное пространство подкачки, компоновщику требуется вечность, чтобы скомпоновать программу. Однако он работает довольно быстро, когда статическая память немного больше, чем доступное пространство подкачки. Что с этим!?

43
задан Rooke 13 February 2017 в 19:21
поделиться