Memory leak в самописном коде

Igor Sysoev is at rambler-co.ru
Sun Jan 8 18:19:44 MSK 2006


On Sun, 8 Jan 2006, Alexey N. Kovyrin wrote:

> Вероятнее всего, вопрос этот адресую Игорю... но задать решил здесь, чтобы 
> для будущих поколений сохранилось :-)
>
> Итак: написал я модуль для генерации и вставки баннеров в страницы юзеров 
> фрихостинга - очень доволен производительностью! (апачу ооочень далеко до 
> такой)
> Вот только где-то у меня утекает память... при посещаемости около 600-700 тыс 
> уников в сутки утекает примерно 100-150 мб в сутки.
>
> В баннерном модуле память выделяется только в двух местах:
>
> 1) топ-баннер (код генерируется динамически функцией generate_top_banner и 
> складывается в память, полученную через ngx_palloc):
>
> /******* Top banner *******/
>   b = ngx_calloc_buf(r->pool);
>   if (b == NULL) {
>       return NGX_ERROR;
>   }
>
>   if (generate_top_banner(r, in, &top_banner, &top_banner_len) < 0) {
>       return NGX_ERROR;
>   }
>
>   b->memory = 0;
>   b->temporary = 1;
>   b->last_buf = 0;
>   b->pos = top_banner;
>   b->last = top_banner + top_banner_len - 1;
>
>   head.buf = b;
>   head.next = in;
>
>   /* Find last node */
>   cur = in;
>   while (cur->next) cur = cur->next;
>
> 2) боттом-баннер (код лежит в статическом char[] массиве внутри модуля):
>
> /******* Bottom banner *******/
>   b = ngx_calloc_buf(r->pool);
>   if (b == NULL) {
>       return NGX_ERROR;
>   }
>
>   b->memory = 1;
>   b->last_buf = 1;
>   b->pos = bottom_banner;
>   b->last = bottom_banner + sizeof(bottom_banner) - 1;
>
>   tail.buf = b;
>   tail.next = NULL;
>   cur->next = &tail;
>   cur->buf->last_buf = 0;
>   cur->buf->sync = 1;
>
>
> Работу с буфферами я разбирал только на примерах других модулей... потому 
> сомневаюсь в правильности использования API для работы с памятью...
>
> Игорь, помогите, пожалуйста.
>
>
> P.S. пока писал, вспомнил, что ngx_palloc есть еще в одном модуле... модуле 
> статистики... но там, вроде бы, не должно быть ошибки:
>
>   xml_packet = ngx_palloc(r->pool, xml_packet_len);
>   if (!xml_packet) {
>       return NGX_ERROR;
>   }
>
>   xml_packet_len = snprintf(xml_packet, xml_packet_len, xml_message, 
> host.data, content_type.data, user_ip.data, file_size);
>   if (xml_packet_len < 1) {
>       ngx_pfree(r->pool, xml_packet);
>       return NGX_ERROR;
>   }
>
>   ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "STATS_PACKET: 
> '%s'", xml_packet);
>
>   // Send stats packet
>   if (sendto(udp_sock, xml_packet, xml_packet_len, 0, &udp_sock_addr, 
> udp_sock_addr_len) < 0) {
>       ngx_pfree(r->pool, xml_packet);
>       return NGX_ERROR;
>   }
>
>   ngx_pfree(r->pool, xml_packet);
>   return NGX_OK;

ngx_pfree() вызывать не нужно, так как он умеет освобождать только
большие куски памяти. По окончании запроса вся память, выделенная из r->pool,
освобождается. А ngx_pfree() используется, например, в gzip-фильтре
по окончании сжатия для освобождения буферов, выделенных для zlib.
Это около 100-300К, и их можно освободить, чтобы не занимать эту память
во время передачи ответа клиенту.

А memory leak скорее всего в generate_top_banner() - там нужно
всю память выделять через ngx_palloc(r->pool, ...).


Игорь Сысоев
http://sysoev.ru





More information about the nginx-ru mailing list