libc가 홀딩하고 있는 free 메모리를 시스템에 반납할 수 있는 방법이 있나요?

superkkt의 이미지

안녕하세요.

리눅스 커널 2.6 이상 환경에서 개발하고 있고, 프로그램이 데이터를 만드는 중에는 상당히 많은 양의 메모리를 반복적으로 할당받고 반납하는 형태로 구성되어 있습니다.

그런데 이런 과정을 오래 거치고 나면 예상치보다 더 많은 메모리를 사용하는 문제가 발생하고 있는데요. valgrind로 확인한 바로는 메모리 릭은 없었는데, mallopt()를 통해서 구한 데이터를 분석해보니 코드에서는 free된 메모리인데 libc가 다음번 할당을 위해 홀딩한채로 시스템에 반납하지 않는 메모리가 늘어나고 있었습니다.

프로그램이 계속 연산을 하는 동안에는 위와 같이 동작해도 문제가 없는데, 연산을 끝내서 데이터가 완성되면 다른 작업을 위해 최대한 메모리를 많이 확보해야 합니다. 그래서 명시적으로 libc가 홀딩하고 있는 free 메모리를 모두 시스템에 반납하길 원하는데요. 이런 방법이 있을까요?

bushi의 이미지

glibc 의 fastbin 을 말씀하시는 거라면 mallinfo.smblks 와 mallinfo.fsmblks 로 확인하실 수 있고,
이를 cleanup 할 수 있는 명시적인 수단은 없는 것으로 알고 있습니다.

엎어진 김에 쉬어간다고, google-perftools 의 tcmalloc 을 고려해보세요.
속도에 대단한 자신감이 있어선지 몰라도... 자잘한 꼼수들이 없더군요.

OTL

superkkt의 이미지

답변 감사합니다. 말씀하신대로 cleanup 할 수 있는 명시적인 수단을 찾고 있습니다. 알려주신 tcmalloc은 지금 사용해 보았는데 속도나 메모리 단편화로 인한 사용량 증가문제도 glibc에 비해서 상당히 좋은 편이네요. 그런데 tcmalloc은 웹사이트 경고문구에 적힌대로 메모리를 전혀 시스템에 반환하지 않는게 저한테는 좀 문제가 있습니다. 저는 메모리 사용량을 최대한 줄여야 하기 때문에 사용하지 않는 메모리를 시스템에 반환하는 방법이 필요한데 다른 방법들도 더 찾아봐야겠습니다.

======================
BLOG : http://superkkt.com

======================
BLOG : http://superkkt.com

molla의 이미지

왜 free memory 에 집착하시는지 잘 이해가 안 갑니다.
현재 OS 들은 Virtual Memory 를 이용하고 swap 영역을 이용하고 있기 때문에, A process 가 1G memory 를 사용하고 있다고 해서 실제 physical memory 를 1G 사용하고 있다고 할 수는 없습니다.
따라서 이미 반납한 memory 라면 별로 신경 안 쓰셔도 됩니다.
물론 처음에 swap 영역 할당하고 하는데 조금 시간이 더 걸릴 수는 있습니다. 하지만 저 영역을 다 OS 에게 반납했다 하더라도, 다음번에 다시 memory 를 요청하면 다시 OS 에서 VM 을 할당하고 하는 overhead 도 무시할 수 없습니다.
즉 A process 가 일시적으로 memory를 무진장 사용해 2G를 사용했다가 다 반납하고 현재는 100M 만 있으면 된다. 그리고 앞으로 두번다시 memory 사용량이 올라갈 일이 없다. 라면 가급적 남은 memory 영역을 OS 에게 반납하는 것이 좋겠습니다만, 그렇지 않다면 굳이 반납하게 만들 필요가 없어 보입니다.

그리고, 대부분의 malloc 계열 library 들은 heap 을 할당받기 위해 (s)brk 를 사용합니다. 이 API 는 manual 을 참조해 보시면 아시겠지만, 선형적으로 증가 or 감소합니다. 이 이야기는 특정 영역 부분만 OS 에게 반납할 방법이 없다! 라는 것을 의미합니다. 그리고 일부(?) malloc manual 을 잘 보시면, 사용자가 직접 (s)brk 를 사용하는 것에 대해서 나오는 것도 있습니다. 이런 것들을 잘 읽어 보시면 (s)brk 로 새 영역을 받아오는 것은 허용하지만, 줄이는 것은 안된다고 나옵니다. 이는 malloc 이 (s)brk 로 받은 영역을 반납하는 경우는 없다는 것을 반증(?)하는 것이지요.

뭐 이야기가 조금 딴데로 샜습니다. 여튼 저런 것을 정 피하고자 하신다면, 별도의 malloc 함수를 사용하시면 될 듯 합니다. glibc 에서 사용한 doug lea의 malloc 등을 조금 손봐, (s)brk 대신 mmap 을 이용하여 heap 을 할당하도록 바꾸시면 됩니다. 물론 free 된 영역은 munmap 을 이용하여 반납하도록 만드셔야 겠지요. 하지만 이 방식의 단점은 위에도 적었지만, (s)brk 방식보다 매우 느립니다! mmap/munmap 이 상대적으로 느린 것도 있을 테고, 상대적으로 (s)brk 보다 더 자주 불려야 한다는 점도 있을 것입니다. 만약 해당 process 가 최대 얼만큼 memory 를 사용하게 될 지 미리 안 다면 비교적 간단하게 할 수 있을 듯 합니다. (미리 그보다 큰 영역을 mmap 으로 할당받은 뒤 그 영역을 doug lea 의 malloc 을 이용하여 할당해주거나 반납하게 하고, 모든 작업이 완료되면 한번에 munmap 으로 반납하게 만들어 주면 됩니다. mmap/munmap 의 회수도 매우 줄어 성능저하도 거의 없을 것입니다.)

ps. 실제로 제가 저 짓을 했습니다. 제 경우는 다른 process 때문이라기 보다는, 사용한 program 이 서버형식이라 관리자가 신경질적으로 사용 memory 를 모니터링 하면서 태클을 걸어 어쩔 수가 없었던 경우였습니다. ㅠ.ㅠ

superkkt의 이미지

즉 A process 가 일시적으로 memory를 무진장 사용해 2G를 사용했다가 다 반납하고 현재는 100M 만 있으면 된다. 그리고 앞으로 두번다시 memory 사용량이 올라갈 일이 없다. 라면 가급적 남은 memory 영역을 OS 에게 반납하는 것이 좋겠습니다만, 그렇지 않다면 굳이 반납하게 만들 필요가 없어 보입니다.

--> 네, 말씀하신 상황이 맞습니다. 그리고 A 프로세스가 데이터를 만들고 메모리에 남아있는 상태에서 B 프로세스가 또 같은 작업을 해야하기 때문에 A가 사용하지 않는 메모리는 반드시 시스템에 반납되도록 해야 합니다. 프로그램의 메모리 할당 패턴에 맞춰서 mmap으로 메모리 할당자를 만들까 고민 중입니다.

======================
BLOG : http://superkkt.com

======================
BLOG : http://superkkt.com

Hyun의 이미지

그렇다면 A process가 작업을 끝난 후 A process를 죽게 만들면 안되나요? 할일이 없는데 왜 살려두는지... 아니면 작업을 프로세스 단위로 만들면 간단할 꺼 같은데...


나도 세벌식을 씁니다
superkkt의 이미지

개발 중인 프로그램이 in-memory database 입니다. 데이터를 만들 때 여러 연산들을 해야해서 메모리를 많이 사용하고요. 데이터가 다 만들어지면 데이터 크기만큼만 메모리를 사용하면서 쿼리를 처리해야 하는데 연산과정에서 사용했던 메모리들이 시스템으로 반납이 안되는 문제 때문에 질문을 올렸습니다.

======================
BLOG : http://superkkt.com

======================
BLOG : http://superkkt.com

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.