프로세스 메모리 최적화 (1)

5467 단어
하나.데이터 세그먼트
데이터 세그먼트에는 bss와 데이터 두 개의 세그먼트가 포함되어 있는데 그 중에서 데이터 세그먼트는 0이 아닌 전역 변수를 저장하는 데 사용되고 bss세그먼트는 0이 되거나 초기화되지 않은 전역 변수를 저장하는 데 사용된다.
왜 0을 두 절로 구분합니까?bss절의 경우 파일에 변수의 초기값 0을 저장할 필요가 없고, Loader는 내용이 0인 페이지 페이지만 사용하기 때문에 이 섹션은 파일의 공간을 차지하지 않습니다.그러나 데이터 바이트의 경우 파일에 변수의 초기 값을 저장해야 하기 때문에 파일 크기를 차지해야 한다. 이 변수에 접근할 때 페이지 고장을 일으키고 파일에 대응하는 초기 값을 메모리에 불러와 초기화를 완성한다.
다음은bss와data가 프로그램에 미친 영향을 분석한다.
bss.c
소스 코드:
#include <stdio.h>
int bss[1024*1024]={0};
int main(int argc,char *argv[]){
bss[0]=1;    
printf("pid=%d,bss=%lx
",getpid(),bss); pause(); return 0; }
실행 파일 크기:
-rwxr-xr-x1 taisimin taisimin 6932 2011-12-07 15:37 bss단 분포:
Program Headers:   Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align   PHDR           0x000034 0x08048034 0x08048034 0x00120 0x00120 R   0x4   INTERP         0x000154 0x08048154 0x08048154 0x00013 0x00013 R   0x1       [Requesting program interpreter:/lib/ld-linux.so.2]   LOAD           0x000000 0x08048000 0x08048000 0x0058c 0x0058c R E 0x1000   LOAD           0x000f0c 0x08049f0c 0x08049f0c 0x00110 0x400134 RW  0x1000
가상 메모리 사용:
08048000-08049000 r-xp 00000000 08:01 9836831    /home/taisimin/linux/optimization/process/bss 08049000-0804a000 r--p 00000000 08:01 9836831    /home/taisimin/linux/optimization/process/bss 0804a000-0804b000 rw-p 00001000 08:01 9836831    /home/taisimin/linux/optimization/process/bss 0804b000-0844b000 rw-p 00000000 00:00 0    【heap】
data.c 
소스:
#include <stdio.h>
int data[1024*1024]={2};
int main(int argc,char *argv[]){
data[0]=1;    
printf("pid=%d,data=%lx,
",getpid(),data); pause(); return 0; }

실행 가능한 파일 크기:
-rwxr-xr-x1 taisimin taisimin 42011272 2011-12-07 15:38 데이터 세그먼트 분포:
Program Headers:   Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align   PHDR           0x000034 0x08048034 0x08048034 0x00120 0x00120 R   0x4   INTERP         0x000154 0x08048154 0x08048154 0x00013 0x00013 R   0x1       [Requesting program interpreter:/lib/ld-linux.so.2]   LOAD           0x000000 0x08048000 0x08048000 0x00590 0x00590 R E 0x1000   LOAD           0x000f0c 0x08049f0c 0x08049f0c 0x400134 0x40013c RW  0x1000
가상 메모리 사용:
08048000-08049000 r-xp 00000000 08:01 9836830    /home/taisimin/linux/optimization/process/data 08049000-0804a000 r--p 00000000 08:01 9836830    /home/taisimin/linux/optimization/process/data 0804a000-0844b000 rw-p 00001000 08:01 9836830    /home/taisimin/linux/optimization/process/data 40000000-4001c000 r-xp 00000000 08:01 7475104    /lib/i386-linux-gnu/ld-2.13.so
위의 데이터를 통해 알 수 있듯이
1. bss의 실행 파일 크기가 작습니다.
2.bss의 데이터 세그먼트는 정상적이지만 Stack 세그먼트에서 4MB의 소모가 많고 데이터의 데이터 세그먼트는 4MB의 소모가 많으며 Stack 세그먼트의 소모가 없다.이것은 loader가 bss절에 stack의 메모리 공간을 사용하고 데이터절에 대해서는 파일의 맵 방식으로 메모리를 비추기 때문이다.
둘.변수가 있는 메모리 영역
다음 예는 다음과 같습니다.
var.c
#include <stdio.h>
#define b 10
#define c "123"

int bss[10]={0};
int data[10]={1};
const int a=10;
static int d;
char *s1="hello,world
"; char s2[]="hellow,world
"; int main(int argc,char *argv[]){ return 0; }

nm -f sysv var 명령을 사용하여 변수가 있는 환심을 사려면 다음과 같이 하십시오.
Symbols from var: Name                  Value   Class        Type         Size     Line  Section __bss_start         |0804a07c|   A  |            NOTYPE|        |     |*ABS* __data_start        |0804a020|   D  |            NOTYPE|        |     |.data _edata              |0804a07c|   A  |            NOTYPE|        |     |*ABS* _end                |0804a0cc|   A  |            NOTYPE|        |     |*ABS* _fini               |0804847c|   T  |              FUNC|        |     |.fini _fp_hw              |08048498|   R  |            OBJECT|00000004|     |.rodata _init               |080482bc|   T  |              FUNC|        |     |.init _start              |08048320|   T  |              FUNC|        |     |.text a                   |080484a0|   R  |            OBJECT|00000004|     |.rodata bss                 |0804a0a0|   B  |            OBJECT|00000028|     |.bss completed.6155      |0804a080|   b  |            OBJECT|00000001|     |.bss d                   |0804a0c8|   b  |            OBJECT|00000004|     |.bss data                |0804a040|   D  |            OBJECT|00000028|     |.data data_start          |0804a020|   W  |            NOTYPE|        |     |.data dtor_idx.6157       |0804a084|   b  |            OBJECT|00000004|     |.bss frame_dummy         |080483b0|   t  |              FUNC|        |     |.text main                |080483d4|   T  |              FUNC|0000000a|     |.text s1                  |0804a068|   D  |            OBJECT|00000004|     |.data s2                  |0804a06c|   D  |            OBJECT|0000000e|     |.data
const 변수는 rodata 섹션에 저장됩니다. 즉, 최종적으로text 섹션에 저장됩니다.
한편, s1, s2, 데이터는 모두 데이터 섹션에 저장되고bss는bss섹션에 저장된다.
셋.데이터 세그먼트 최적화
1. 전역 성형 변수를 줄이는 것은 4B만 줄이는 것이 아니다. 왜냐하면 리눅스에서 페이지로 메모리를 분배하기 때문이다.
2. 데이터 세그먼트 최적화가 가져오는 영향은 유한하다. 특히 사용자 프로그램이지만 동적 라이브러리의 데이터 세그먼트를 최적화하면 그 역할이 뚜렷하다. 만약에 하나의 동적 라이브러리가 100개의 프로세스에 의해 집행되고 모든 프로세스가 집행될 때 메모리에 100개의 동적 라이브러리의 데이터 세그먼트가 포함된다. 만약에 성형 전역 변수를 줄일 수 있다면 이론적으로 4B*100=400B의 메모리 크기를 줄일 것이다.
일반적인 최적화 방법:
1. nm-f sysv xx |grep -w를 사용합니다.데이터 (.bss) 방식으로 각 소절의 변수를 검사합니다.
2. const 방식으로 읽기만 하는 전역 변수를 수식하여 코드 섹션으로 옮기고 코드 섹션의 공유 메모리 방식으로 메모리 사용을 줄인다

좋은 웹페이지 즐겨찾기