2010-03-17 3 views
5

방금 ​​C로 시작하여 malloc()free()으로 성능 문제에 대한 지식이 거의 없습니다. 내 질문은 이것입니다 : 을 호출 한 다음 while 루프 내에있는 free() 루프를 호출하면 반복 횟수가 예를 들어 20 회 반복되는데 비해 루프가 free()이 아닌 루프보다 느리게 실행됩니까? 루프가 발생합니까?C 프로그래밍 : 루프 내 malloc 및 무료

실제로 버퍼에 메모리를 할당하고, 파일에서 가변 길이 문자열을 읽고, 일부 문자열 연산을 수행 한 다음 매 반복마다 버퍼를 지우는 첫 번째 방법을 사용하고 있습니다. 내 방법으로 인해 많은 오버 헤드가 발생한다면 같은 결과를 얻는 더 좋은 방법을 물어보고 싶습니다.

+5

당신이 그것을 내부의 malloc을 호출하는 경우 당신은 루프 외부 무료로 호출 할 수 없습니다, 또는 당신은 모든 메모리하지만 마지막 반복에서의 malloc을 누설 수 있습니다. 그러나 malloc 대신 realloc을 사용하고 외부에서는 free를 사용할 수 있습니다. – Cascabel

+0

@ Jefromi : 나는 그 코멘트에 답을해야한다고 생각합니다. –

+2

당신의 영어 실력은 훌륭합니다. 사실 대부분의 초보자들보다 영어 실력이 좋습니다. –

답변

13

확실히 느리다. (하지만 당신은 그렇지 않으면 당신은 메모리 누수를 얻을 수 mallocfree의 수의 균형을 필요로 기억합니다.)

길이가 다릅니다 경우, 버퍼 크기를 확장 할 realloc를 사용할 수 있습니다.

void* v = malloc(1024); 
size_t bufsize = 1024; 

while(cond) { 
    size_t reqbufsize = get_length(); 
    if (reqbufsize > bufsize) { 
     bufsize = reqbufsize * 2; 
     v = realloc(v, bufsize); 
    } 
    // you may shrink it also. 

    do_something_with_buffer(v); 
} 

free(v); 
+2

+1 -하지만'bufsize = reqbufsize * 2;'는 약간 과감하다고 생각하지 않습니까? : P –

+0

아마도. 'std :: vector'의 MSVC2k8 구현은 재배치 할 때 버퍼를 150 % 증가시킵니다. –

+4

@BillyONeal : 실제로는 일을하는 꽤 일반적인 방법입니다. – Dinah

3

버퍼의 최대 길이를 알고 있거나 합당한 최대 값을 설정할 수 있다면 반복 할 때마다 동일한 버퍼를 사용할 수 있습니다. 그렇지 않으면 당신이하고있는 일이 잘되어야합니다.

0

malloc 및 무료 구현에 따라 다릅니다.

귀하의 질문에 응답하는 가장 좋은 방법은 ... 벤치 마크를 구축하는 것입니다

1

버퍼가 필요한지 여부에 따라 다릅니다.

반복 할 때마다 지워야하나요? 아니면 끝 부분에 \0 문자로 끝 부분을 표시하면 충분합니까? 결국 다양한 라이브러리 호출이 다양한 str을 사용합니다.

정말로 삭제해야하는 경우 bzero()을 사용할 수 있습니다. 확실히 모든 반복에서 malloc'ing 및 free'ing은 자원을 낭비합니다. 버퍼를 행복하게 다시 사용할 수 있기 때문입니다.

for 루프를 병렬 처리하는 경우, 즉 루프를 병렬 처리하는 경우, 즉이를 사용하는 여러 개의 동시 스레드가있는 경우 다른 문제가 발생합니다.

단순하고 실제적인 예 : 양동이를 사용하여 물을 운반하십시오. 그 양동이로 여러 번 여행 할 필요가 있다고 가정 해 봅시다. 집어 들고 사용하고 내려 놓고 다시 집어 사용하십시오. 가능한 한 여러 번 버킷을 다시 사용할 수 있습니다. 다른 한편으로는 당신과 더 많은 사람들이 버킷을 사용해야 할 경우 버킷에 대한 액세스를 구성하거나 더 많은 버킷이 필요합니다.

최근 제안 : 지금은 공연에 대해 걱정할 필요가 없습니다. 그들은 초기 최적화가 모든 악의 뿌리라고 말하면 곧 이유를 이해하게 될 것입니다.

먼저 문제를 이해하십시오. 버려 질 수있는 코드를 작성하십시오. 실험. 두 번째로 테스트하십시오. 그것이 당신이 필요로하는 것을 확실히하십시오. 셋째, 최적화하십시오. 루프를 1 만 번 실행하고 소요 시간을 측정하십시오. 그런 다음 malloc을 바깥쪽으로 이동하고 다시 측정하십시오 (UNIX에서는 쉘 명령 time을 사용하십시오). 네 번째로, 첫 번째 실험은 작업 코드가 아닌 try-retry 패치의 엉망 일 가능성이 높기 때문에 다시 작성하십시오.

린스, 반복.

ps : 잠시 재미있게 보내십시오. 흥미롭고 좌절하지 않아야합니다.

1

일반적으로 루프 바깥으로 이동할 수있는 모든 항목이 있어야합니다. 왜 한번 할 수있을 때 같은 행동을 반복합니까?

Justin Ethier가 맞습니다. 가장 큰 문자열에 편안하게 맞는 버퍼를 할당하고 다시 사용하십시오.

6

20 번 반복하면 malloc/free의 성능에 대해 걱정할 필요가 없습니다.

훨씬 더 많으면 (몇 자리수), 코드를 프로파일 링하고 느린 것을 이해할 때까지는 최적화에 대해 생각하지 않아야합니다.

마지막으로 버퍼를 비우려면 먼저 버퍼를 지울 필요가 없습니다. 저스틴에서 제안한 최대 버퍼를 사용하여 루프 외부에서 malloc/free를 이동하더라도 버퍼를 명시 적으로 지울 필요가 없습니다.

6

당신이 내부의 malloc을 호출하는 경우는 루프 밖에서 무료로 호출 할 수 없습니다 : 당신은 num_files 번 malloc 된 것이다,하지만 한 번 해제

char * buffer; 
for (int i = 0; i < num_files; i++) { 
    buffer = malloc(proper_length(i)); 
    // do some things with buffer 
} 
free(buffer); 

- 당신은 마지막으로 모두에서 메모리를 유출 !

는 두 가지 선택이있다 - 루프 이전의 malloc (또는 배열을 사용하는) 당신이 모든 작동, 또는 realloc을 사용하는 크기를 알고있는 경우 :

char * buffer = NULL; 
for (int i = 0; i < num_files; i++) { 
    buffer = realloc(proper_length(i)); 
    // do some things with buffer 
} 
free(buffer); 
0

프로세스 더 잘합니다. 일부 의사 코드 유무 :

#define BLOCK_SIZE 1024 // or about the bigger size of your strings. 

char *buffer = (char *) malloc(BLOCK_SIZE) 

for(int i=0; i<20; i++) 
{ 
    while (more bytes left to read) 
    { 
    read full string or BLOCK_SIZE bytes at max // most calls work this way 
    proces bytes in buffer 
    } 
} 

free(buffer);