sirve que programar programa para ejecutar correr con compiler compilar compilador como archivo c linux gcc swap ld

que - Rendimiento del enlazador relacionado con el espacio de intercambio?



para que sirve gcc en linux (3)

No observo este comportamiento (con Debian / Sid / AMD64 en un escritorio de 8 Gb, gcc 4.6.2, binutils gold ld (GNU Binutils para Debian 2.22) 1.11). Aquí está el programa cambiado (mostrando su mapa de memoria con pmap ).

#include <string.h> #include <stdlib.h> #include <stdio.h> #define M 1000000 #define GIANT_SIZE (2000*M) size_t g_arr[GIANT_SIZE]; int main( int argc, char **argv){ int i; char cmd[80]; for(i = 0; i<10; i++){ printf("This should be zero: %d/n",g_arr[i*1000]); } sprintf (cmd, "pmap %d", (int)getpid()); system(cmd); exit(0); }

Aquí está su compilación:

% time gcc -v -O big.c -o big Using built-in specs. COLLECT_GCC=/usr/bin/gcc-4.6.real COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.6/lto-wrapper Target: x86_64-linux-gnu Configured with: ../src/configure -v --with-pkgversion=''Debian 4.6.2-4'' --with-bugurl=file:///usr/share/doc/gcc-4.6/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++,go --prefix=/usr --program-suffix=-4.6 --enable-shared --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.6 --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-plugin --enable-objc-gc --with-arch-32=i586 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu Thread model: posix gcc version 4.6.2 (Debian 4.6.2-4) COLLECT_GCC_OPTIONS=''-v'' ''-O'' ''-o'' ''big'' ''-mtune=generic'' ''-march=x86-64'' /usr/lib/gcc/x86_64-linux-gnu/4.6/cc1 -quiet -v -imultilib . -imultiarch x86_64-linux-gnu big.c -quiet -dumpbase big.c -mtune=generic -march=x86-64 -auxbase big -O -version -o /tmp/ccWThBP5.s GNU C (Debian 4.6.2-4) version 4.6.2 (x86_64-linux-gnu) compiled by GNU C version 4.6.2, GMP version 5.0.2, MPFR version 3.1.0, MPC version 0.9 warning: MPFR header version 3.1.0 differs from library version 3.1.0-p3. GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu" ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/4.6/../../../../x86_64-linux-gnu/include" #include "..." search starts here: #include <...> search starts here: /usr/lib/gcc/x86_64-linux-gnu/4.6/include /usr/local/include /usr/lib/gcc/x86_64-linux-gnu/4.6/include-fixed /usr/include/x86_64-linux-gnu /usr/include End of search list. GNU C (Debian 4.6.2-4) version 4.6.2 (x86_64-linux-gnu) compiled by GNU C version 4.6.2, GMP version 5.0.2, MPFR version 3.1.0, MPC version 0.9 warning: MPFR header version 3.1.0 differs from library version 3.1.0-p3. GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 Compiler executable checksum: 4b128876859f8f310615c7040fa3cb67 COLLECT_GCC_OPTIONS=''-v'' ''-O'' ''-o'' ''big'' ''-mtune=generic'' ''-march=x86-64'' as --64 -o /tmp/ccm7905b.o /tmp/ccWThBP5.s COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/4.6/:/usr/lib/gcc/x86_64-linux-gnu/4.6/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/4.6/:/usr/lib/gcc/x86_64-linux-gnu/ LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/4.6/:/usr/lib/gcc/x86_64-linux-gnu/4.6/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/4.6/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/4.6/../../../:/lib/:/usr/lib/ COLLECT_GCC_OPTIONS=''-v'' ''-O'' ''-o'' ''big'' ''-mtune=generic'' ''-march=x86-64'' /usr/lib/gcc/x86_64-linux-gnu/4.6/collect2 --build-id --no-add-needed --eh-frame-hdr -m elf_x86_64 --hash-style=both -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o big /usr/lib/gcc/x86_64-linux-gnu/4.6/../../../x86_64-linux-gnu/crt1.o /usr/lib/gcc/x86_64-linux-gnu/4.6/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/4.6/crtbegin.o -L/usr/lib/gcc/x86_64-linux-gnu/4.6 -L/usr/lib/gcc/x86_64-linux-gnu/4.6/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/4.6/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/4.6/../../.. /tmp/ccm7905b.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/x86_64-linux-gnu/4.6/crtend.o /usr/lib/gcc/x86_64-linux-gnu/4.6/../../../x86_64-linux-gnu/crtn.o gcc -v -O big.c -o big 0.07s user 0.01s system 90% cpu 0.089 total

y su ejecución:

% time ./big This should be zero: 0 This should be zero: 0 This should be zero: 0 This should be zero: 0 This should be zero: 0 This should be zero: 0 This should be zero: 0 This should be zero: 0 This should be zero: 0 This should be zero: 0 8835: ./big 0000000000400000 4K r-x-- /home/basile/tmp/big 0000000000401000 4K rw--- /home/basile/tmp/big 0000000000402000 15625000K rw--- [ anon ] 00007f2d15a44000 1512K r-x-- /lib/x86_64-linux-gnu/libc-2.13.so 00007f2d15bbe000 2048K ----- /lib/x86_64-linux-gnu/libc-2.13.so 00007f2d15dbe000 16K r---- /lib/x86_64-linux-gnu/libc-2.13.so 00007f2d15dc2000 4K rw--- /lib/x86_64-linux-gnu/libc-2.13.so 00007f2d15dc3000 20K rw--- [ anon ] 00007f2d15dc8000 124K r-x-- /lib/x86_64-linux-gnu/ld-2.13.so 00007f2d15fb4000 12K rw--- [ anon ] 00007f2d15fe4000 12K rw--- [ anon ] 00007f2d15fe7000 4K r---- /lib/x86_64-linux-gnu/ld-2.13.so 00007f2d15fe8000 4K rw--- /lib/x86_64-linux-gnu/ld-2.13.so 00007f2d15fe9000 4K rw--- [ anon ] 00007ffff5b5b000 132K rw--- [ stack ] 00007ffff5bff000 4K r-x-- [ anon ] ffffffffff600000 4K r-x-- [ anon ] total 15628908K ./big 0.00s user 0.00s system 0% cpu 0.004 total

Creo que la instalación de un GCC reciente (por ejemplo, un GCC 4.6 ) con un enlazador binutils Gold es importante para dichos programas.

No escucho ningún intercambio involucrado.

A veces es útil simular algo con un pequeño programa en C que usa una gran cantidad de memoria estática. Me di cuenta después de cambiar a Fedora 15 que el programa tardó mucho tiempo en compilarse. Estamos hablando de 30 s contra 0.1 s. Aún más extraño fue que ld (el enlazador) estaba maximizando la CPU y lentamente comenzó a comer toda la memoria disponible. Después de tocar un poco, logré encontrar una correlación entre este nuevo problema y el tamaño de mi archivo de intercambio. Aquí hay un programa de ejemplo para los propósitos de esta discusión:

#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); }

Este programa tiene una matriz gigante que tiene un tamaño declarado de aproximadamente 200 * 8MB = 1.6GB de memoria estática. La compilación de este programa requiere una cantidad de tiempo desmesurada:

[me@bleh]$ time gcc HugeTest.c real 0m12.954s user 0m6.995s sys 0m3.890s [me@bleh]$

13s Para un ~ 13 programa de línea C? Eso no está bien. El número de clave es el tamaño del espacio de memoria estática. Tan pronto como es más grande que el espacio de intercambio total, comienza a compilarse rápidamente de nuevo. Por ejemplo, tengo 5.3 GB de espacio de intercambio, por lo que cambiar GIANT_SIZE a (1000 * M) da la siguiente vez:

[me@bleh]$ time gcc HugeTest.c real 0m0.087s user 0m0.026s sys 0m0.027s

Ah, eso es más como eso! Para convencerme a mí mismo (y a ti mismo, si estás intentando esto en casa) ese espacio de intercambio era realmente el número mágico, traté de cambiar el espacio de intercambio disponible a un 19GB realmente masivo e intentar compilar la versión (1000 * M) otra vez :

[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

¡Ni siquiera se completó después de 4.5 minutos!

Claramente, el enlazador está haciendo algo mal aquí, pero no sé cómo evitar esto, aparte de reescribir el programa o jugar con el espacio de intercambio. Me encantaría saber si hay una solución, o si me encontré con algún error arcano.

Por cierto, todos los programas se compilan y ejecutan correctamente, independientemente de todo el negocio de intercambio.

Como referencia, aquí hay alguna información posiblemente relevante:

[]$ 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: cuando la memoria estática (grande) del programa de CA es ligeramente menor que el espacio de intercambio disponible, el enlazador tarda una eternidad en vincular el programa. Sin embargo, es bastante ágil cuando el espacio estático es un poco más grande que el espacio de intercambio disponible. ¿¡Que pasa con eso!?


Puedo reproducir esto en un sistema Ubuntu 10.10 ( GNU ld (GNU Binutils for Ubuntu) 2.20.51-system.20100908 ), y creo que tengo su respuesta. Primero, algo de metodología.

Después de confirmar que esto me sucede en una máquina virtual pequeña (512 MB de RAM, intercambio de 2 GB), desde aquí decidí que lo más fácil sería dirigirme a gcc y ver qué sucedía exactamente cuando todo se iba al infierno:

~# strace -f gcc swap.c

Iluminó lo siguiente:

vfork() = 3589 [pid 3589] execve("/usr/lib/gcc/x86_64-linux-gnu/4.4.5/collect2", ["/usr/lib/gcc/x86_64-linux-gnu/4."..., "--build-id", "--eh-frame-hdr", "-m", "elf_x86_64", "--hash-style=gnu", "-dynamic-linker", "/lib64/ld-linux-x86-64.so.2", "-o", "swap", "-z", "relro", "/usr/lib/gcc/x86_64-linux-gnu/4."..., "/usr/lib/gcc/x86_64-linux-gnu/4."..., "/usr/lib/gcc/x86_64-linux-gnu/4."..., "-L/usr/lib/gcc/x86_64-linux-gnu/"..., ...], [/* 26 vars */]) = 0 ... [pid 3589] vfork() = 3590 ... [pid 3590] execve("/usr/bin/ld", ["/usr/bin/ld", "--build-id", "--eh-frame-hdr", "-m", "elf_x86_64", "--hash-style=gnu", "-dynamic-linker", "/lib64/ld-linux-x86-64.so.2", "-o", "swap", "-z", "relro", "/usr/lib/gcc/x86_64-linux-gnu/4."..., "/usr/lib/gcc/x86_64-linux-gnu/4."..., "/usr/lib/gcc/x86_64-linux-gnu/4."..., "-L/usr/lib/gcc/x86_64-linux-gnu/"..., ...], [/* 27 vars */]) = 0 ... [pid 3590] lseek(13, 4096, SEEK_SET) = 4096 [pid 3590] read(13, "./4@/0/0/0/0/0>/4@/0/0/0/0/0N/4@/0/0/0/0/0/0/0/0/0/0/0/0/0"..., 4096) = 4096 [pid 3590] mmap(NULL, 1600004096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f1771931000 <system comes to screeching halt>

Parecería que, como podríamos haber sospechado, parece que ld está tratando de mmap anónimamente todo el espacio de la memoria estática de esta matriz (o posiblemente todo el programa, es difícil saberlo ya que el resto del programa es muy pequeño, todo cabría en ese 4096 extra).

Entonces todo está muy bien, pero ¿por qué funciona cuando excedemos el intercambio disponible en el sistema? Vamos a cambiar swapoff y correr strace -f otra vez ...

[pid 3618] lseek(13, 4096, SEEK_SET) = 4096 [pid 3618] read(13, "./4@/0/0/0/0/0>/4@/0/0/0/0/0N/4@/0/0/0/0/0/0/0/0/0/0/0/0/0"..., 4096) = 4096 [pid 3618] mmap(NULL, 1600004096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = -1 ENOMEM (Cannot allocate memory) [pid 3618] brk(0x60638000) = 0x1046000 [pid 3618] mmap(NULL, 1600135168, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = -1 ENOMEM (Cannot allocate memory) [pid 3618] mmap(NULL, 134217728, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0) = 0x7fd011864000 ...

Como era de esperar, parece hacer lo mismo que intentó la última vez, para mapear todo el espacio. pero el sistema ya no puede hacer eso, ¡falla! Lo intenta de nuevo, y falla nuevamente, luego hace algo inesperado ... avanza con menos memoria.

Extraño, supongo que será mejor que echemos un vistazo al código ld . Drat, no hace un mmap explícito. Esto debe provenir del interior de un viejo malloc . Tendremos que construir ld con algunos símbolos de depuración para rastrear esto. Desafortunadamente, cuando construí bin-utils 2.21.1 el problema desapareció. Por cierto, ¿ha sido arreglado en versiones más nuevas de bin-utils?


Torturé probado mi OpenSuse 11.4 (va por 12.1 en una semana)

Tengo 4GiB ram + 2GiB swap y no noté una desaceleración seria, el sistema podría estar causando problemas a veces, pero aun así el tiempo de compilación fue corto.

El más largo fue de 6 segundos, mientras que el intercambio pesado.

[tester@ulises ~]$ free -m total used free shared buffers cached Mem: 3456 3426 30 0 4 249 -/+ buffers/cache: 3172 284 Swap: 2055 1382 672 [tester@ulises ~]$ time cc -Wall -O test2.c test2.c: In function ‘main’: test2.c:13:2: warning: format ‘%d’ expects type ‘int’, but argument 2 has type ‘size_t’ real 0m6.501s user 0m0.101s sys 0m0.078s [tester@ulises ~]$ free -m total used free shared buffers cached Mem: 3456 3389 67 0 5 289 -/+ buffers/cache: 3094 362 Swap: 2055 1455 599 [tester@ulises ~]$ free -m total used free shared buffers cached Mem: 3456 3373 82 0 4 264 -/+ buffers/cache: 3104 352 Swap: 2055 1442 612 [tester@ulises ~]$ time cc -Wall -O test2.c test2.c: In function ‘main’: test2.c:13:2: warning: format ‘%d’ expects type ‘int’, but argument 2 has type ‘size_t’ real 0m1.122s user 0m0.086s sys 0m0.045s [tester@ulises ~]$ time cc -Wall -O test2.c test2.c: In function ‘main’: test2.c:13:2: warning: format ‘%d’ expects type ‘int’, but argument 2 has type ‘size_t’ real 0m0.095s user 0m0.047s sys 0m0.032s [tester@ulises ~]$ free -m total used free shared buffers cached Mem: 3456 3376 79 0 4 252 -/+ buffers/cache: 3119 336 Swap: 2055 1436 618 [tester@ulises ~]$ time cc -Wall -O test2.c test2.c: In function ‘main’: test2.c:13:2: warning: format ‘%d’ expects type ‘int’, but argument 2 has type ‘size_t’ real 0m0.641s user 0m0.054s sys 0m0.040s

Entre la ejecución, he cargado y descargado VM de Virtualbox Box, Eclipse, archivos pdf grandes, mi Firefox solo usando más de 800 MiB. No llegué al límite, de lo contrario, muchas aplicaciones serían destruidas por el sistema operativo. Tiene una preferencia por matar a Firefox .. :-)

También fui a la definición extrema:

#define M 1048576 #define GIANT_SIZE (20000*M)

e incluso entonces nada cambia significativamente.

[tester@ulises ~]$ time cc -Wall -O test2.c test2.c:7:14: warning: integer overflow in expression test2.c:7:8: error: size of array ‘g_arr’ is negative test2.c:7:1: warning: variably modified ‘g_arr’ at file scope test2.c: In function ‘main’: test2.c:13:2: warning: format ‘%d’ expects type ‘int’, but argument 2 has type ‘size_t’ real 0m0.661s user 0m0.043s sys 0m0.031s

Edición: Volví a probar el uso de Fedora16 en una máquina virtual con 512MiB RAM y 1.5GiB swap, y las cosas fueron similares, excepto por un mensaje de error en mi "versión máxima de estrés" donde 20000 megabytes fueron asignados a la matriz. El error dice que el tamaño de la matriz fue negativo.

[ricardo@localhost ~]$ time gcc -Wall test2.c test2.c:7:14: warning: integer overflow in expression [-Woverflow] test2.c:7:8: error: size of array ‘g_arr’ is negative test2.c:7:1: warning: variably modified ‘g_arr’ at file scope [enabled by default] test2.c: In function ‘main’: test2.c:13:2: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘size_t’ [-Wformat] real 0m1.053s user 0m0.050s sys 0m0.137s

La misma respuesta ocurre en opensuse 12.1 VM. El Fedora 16 instaló el verry lento y el hambre de memoria (durante la instalación tuve que usar 800Mib contra OpenSuse 512 MiB), no pude usar el swapoff en Fedora porque estaba usando mucho swap. No tuve lentitud ni problemas de memoria en OpenSuse 12.1 y. Ambos tienen esencialmente las mismas versiones de kernel, gcc, etc. Ambos usan instalaciones en stock con KDE como entorno de escritorio.

No pude reproducir tus problemas. Tal vez sea un problema relacionado con gcc. Intenta descargar una versión anterior como 4.5 y mira lo que sucede