메모리 할당과 해제.

systemfile의 이미지

5천만개의 데이터를 메모리로 리스트를 통해 읽어옵니다.
실제로 메모리에 올라오는 용량은 2043MB입니다.

top을 통해 모니터링을 하는데 malloc을 통해 메모리를 할당하는데 이것이 free가 되지 않습니다.

500메가 짜리 데이터는 잘 올라가서 free를 하는 방면 1G가 넘는 대용량을 메모리에 올려서 사용하고 free를 하면 해제가 되지 않습니다.

그런데 더욱 이상한것은 프로그램이 top을 통해 보면 메모리를 잡고 있지만 그 프로그램 안에서 다른 것을 메모리로 올릴 때는 할당되어있던 메모리를 그대로 사용하는 현상이 있습니다.

예를들면 1.5기가를 메모리에 올려 사용하고 해제를 하면 top에서 봤을때는 그 프로그램은 여전히 1.5기가를 가지고 있는데. 그 상태에서 2기가파일을 메모리에 올렸을때는 3.5가 되는것이 아니라. 2G가 됩니다.

즉 메모리는 해제가 되었는데 프로그램에 묶여있고 그 공간을 재활용하는 것 처럼 보이는데....

이건 무슨 조화일까요..ㅡㄴㅡa;;;

데이터가 점점 커져서 메모리로 올라가야할 데이터도 점점 커지는데......걱정입니다;

사용하고 있는 패키지는 레뎃 9.0입니다.

Necromancer의 이미지

max 2G로 알고 있는데...

일단은 커널 메모리 영역이 1G 정도 잡아먹고,
나머지 3G가 프로그램이 사용 가능한 영역입니다.
여기에 프로그램, 스택데이터, 환경변수 등이 들어가면
더 적어집니다.

제가 알기론 커널에서 메모리를 할당받는 brk()나
mmap()은 2기가 이상 못받습니다. (brk()는 1기가가
최대로 알고 있습니다.)

Written By the Black Knight of Destruction

systemfile의 이미지

MAX 2G의 문제는 아닌 듯 싶습니다.
테스트 삼아 리스트를 동시에 두개를 만들어 봤는데 메모리를 3G를 훌쩍 넘겨 사용하는군요. 역시 메모리 해제는 되지 않았지만...

총 4G의 메모리를 사용하는데...
80여%까지 사용하더니 프로그램이 스리슬적 죽네요.
세그먼트폴트라도 나면서 끝나주면 좋은데.;;

: D

cinsk의 이미지

free()를 불렀다고, 할당했던 메모리가 바로 system으로 반환될 거라고 생각하면 안됩니다. 그것은 순전히 C 라이브러리에서 malloc을 어떻게 구현했느냐에 따라 다르기 때문입니다. 일반적으로 요즈음 memory allocator는, 여러 개의 pool (list)을 만들고, 요구되는 메모리의 크기에 따라 반환되는 메모리를 적당한 pool에 위치시킵니다. 아주 큰 크기의 메모리를 요청하면 보통 mmap을 써서 메모리를 할당하곤 합니다. 역시 언제 시스템으로 반환되느냐는 C 라이브러리에 따라 다릅니다.

C 라이브러리의 memory allocator에 대한 정보를 얻거나 tuning하고 싶으면, SVID/XPG 인터페이스인 mallopt(3)이나 mallinfo(3)를 써 보기 바랍니다.

또한, 프로그램이 실제로 제대로 free했는지를 알아보기 위해서, glibc에서 제공하는 memusage utility를 써 보기 바랍니다.

ulra의 이미지

안녕하세요.
지금 고민이 프로그램이 돌다가 세그먼트 폴트로 죽습니다.
메모리 문제인것을 알아냈습니다만 워낙 많은 모듈에서 사용되어서
어떤 모듈을 거치고 난 후에 문제가 생겼는지 추적하기가 만만치 않네요.
그래서 어디서 할당 받아 어디, 어디서 사용하다가 메모리
침범 등이 생기는지 추적하고 또 관리하는 방법을 알고 싶습니다.
이런 메모리 할당 및 해제를 관리하는 기법이나 툴이 있는지요?
관리 기법이 알고 계시면 관리부분 소스를 올려주실 수 있는지요?
부탁드립니다.

OTL 즐!!!! (좌절 금지!!!)

ssehoony의 이미지

ulra wrote:
안녕하세요.
지금 고민이 프로그램이 돌다가 세그먼트 폴트로 죽습니다.
메모리 문제인것을 알아냈습니다만 워낙 많은 모듈에서 사용되어서
어떤 모듈을 거치고 난 후에 문제가 생겼는지 추적하기가 만만치 않네요.
그래서 어디서 할당 받아 어디, 어디서 사용하다가 메모리
침범 등이 생기는지 추적하고 또 관리하는 방법을 알고 싶습니다.
이런 메모리 할당 및 해제를 관리하는 기법이나 툴이 있는지요?
관리 기법이 알고 계시면 관리부분 소스를 올려주실 수 있는지요?
부탁드립니다.

valgrind 가 좋습니다.
검색해 보세요.
근데 ix86 linux 만 작동하는 것 같던데...
다른 플랫폼이라도 메모리 추적해주는 툴들이 있으니 그걸 사용하세요.

ulra의 이미지

답변주셔서 감사드립니다.

혹시 지금 담당 중이신 프로그램은 메모리 할당, 해제를 어떻게 관리하시는지
알려주실 수 있으신지요?
로그를 남긴다든지 아니면 메모리를 한번 할당 후 계속 재활용하신다든지
그런 기법들을 알고 싶습니다.

혹시 다른 고수님들도 지나가시다가 정보 좀 알려주세요. ^^

OTL 즐!!!! (좌절 금지!!!)

ssehoony의 이미지

제 경우는 동적할당은 느리기 때문에 거의 하지 않습니다.
가급적 모두 스택에 할당해서 해결을 하며, 그렇게 하기 힘든 경우 MAX 사이즈가 예상을 할 수 있는 경우 배열을 한번만 할당해서 사용합니다.
동적으로 변해야 하는 거라면 가급적 stl 사용하고, 이 외의 불가피한 경우에만 동적 할당을 사용합니다. (stl 역시 reserve() 를 활용하여 최대한 퍼포먼스에 배려를 합니다.)
동적으로 할당 했다면, 메모리 할당한 모듈이 메모리를 삭제한다는 원칙으로 코딩을 합니다.
즉, strdup 같은 함수는 절대 사용하지도 않고 그런식(함수 내부에서 할당하고, 함수 밖 다른 곳에서 해제 해야하는)으로 작동하는 함수를 만들지도 않습니다. strdup 를 처음 사용하는 사람들 중엔 해제를 본인이 해야 하는 걸 모르는 경우가 있습니다. 이런 우를 범하기 안겠다는 취지에서이지, strdup 가 문제가 있는 함수라는 건 아닙니다.

이런 메모리 할당 정책으로 해서, 데몬을 구현하는데 메모리 누수로 고생한 적도, 동적할당에 의한 포퍼먼스 저하도 없습니다.
그런데 고정 사이즈 배열을 사용을 많이 하다 보니, 개발 중에 가끔 골치아프게 하는 녀석이 버퍼 오퍼플로우였습니다. 이건 잘 못된 영역에 기록을 해도 세그폴트가 꼭 발생하는 것이 아니기 때문에 버그 잡기 힘들죠. 이를 해결하기 위해 사용하는 디버깅 툴 중에 가장 맘에 드는건 efence 였습니다.

그리고 assert 의 사용.
assert 는 서버에 사용하기에는 적합하지 않다고 보는 시각도 있긴 하지만, 잘 활용하면 디버깅 시간을 크게 단축할 수 있습니다.

solid code 라는 책을 읽어 보시는 것도 좋을 듯 하네요.

ulra의 이미지

ssehoony님이 말씀하신데로 제가 하기에는 프로그램을 모두 띁어 고쳐야한다는 문제가 있네요 ㅜ.ㅜ
제가 설계한 프로그램도 아니고 소스코드의 양이 많고 여기저기서 동적 할당을 하기 때문에 띁어 고치다가는 상당히 많은 시간이 걸릴 것 같습니다.
아무튼 답변주신 것 감사드립니다.

다른 분들도 지나가시다가 정보 좀 주세요 ^^;;

OTL 즐!!!! (좌절 금지!!!)

cinsk의 이미지

valgrind를 써 보기 바랍니다.

익명 사용자의 이미지

* ssehoony님의 동적할당 배제 및 스택을 활용하는 방법에 한표...

메모리 할당(관리) 영역에서, 멀티쓰레드 & 멀티프로세서(SMP;요즘 거의 이거지요? 가정용도?)라면 다음 글을 읽어보시고,( 진보를 위하여~)
한번 주워다가 써보시길. 글은 꼭 읽어보시고.
요지는 " SMP환경 Multi-thread programming에서 일반적인 할당방식보다 10배나은 성능을 보이는..."거 내가 만들었다. 좋다~ 라는 주장입니다.
http://www.garret.ru/~knizhnik/threadalloc/readme.html

심심한 사람은 이 홈페이지 주인의 기타 링크도 한번 쭉~ 보시길.
이 홈페이지 주인...... 개인적으로 참~ 멋진 사람으로 생각하고 있습니다.
개인 홈페이지에서 아주 오랜기간동안(?) 이런 작업을 수행하는것은 참 보기 드물었기에...귀감이 됩니다.
혼자서 참 많은것들을 했더군요. 몇년째 가끔 가서 보지만, 여전합니다. ㅎㅎ

amister의 이미지

physical memory와 virtual memory를 구분하셔야 합니다.

necromancer님의 얘기는 process address space에서의 얘기입니다. x86 linux의 경우 process address space의 1G가 kernel용으로 mapping되기 때문에 실제로 process가 활용할 수 있는 vm은 3G이고, 이 곳에 라이브러리나 데이터등이 올라가기 때문에 하나의 process가 사용할 수 있는 최대 메모리는 3G 미만이라고 보는것이 맞습니다.

하지만 physical memory는 더 많이 사용할 수 있습니다. OS에서 프로세스가 하나만 있는 것이 아니기 때문이죠. physical memory가 많으면 그저 디스크로 스왑되는 페이지들이 적어질 뿐입니다. 아무리 physical memory가 많다 해도 하나의 process가 가질 수 있는 address space는 변하지 않습니다.

amister의 이미지

malloc()의 경우, cinsk님 말씀대로 메모리를 실제로 어떻게 할당하고 해제하는지는 구현 의존적입니다. 어플리케이션 레벨에서 malloc()이 내부적으로 어떻게 동작하는지는 알 필요가 없죠. 그저 제대로 동작한다고 믿고 사용해야 할 뿐입니다.

실제로 malloc()을 사용하여 heap에 메모리를 할당하고 사용하는 경우, 실제로 요청한 메모리보다 좀 더 많은 사이즈를 할당한다는 것을 잊지 마세요. 따라서 작은 chunk들을 많이 할당하면 할 수록 메모리 공간 활용율은 떨어지고, locality가 떨어지기 때문에 page fault나 cache miss로 인한 성능저하가 많이 생깁니다. 따라서 데이터 수가 많고 각각의 사이즈가 작은 것들을 다룰 때는 데이터구조의 특성에 따라 여러가지 방법을 많이 고민해야 합니다.

예를 들어, 리스트의 형태로 메모리에 올렸는데 insert나 delete등이 거의 없고 read only라면 큰 메모리 하나를 할당하고 그 안에서 fixed memory pool 형태로 관리하는 것이 더 효율적일 것입니다. insert나 delete등이 많다면 list node의 사이즈를 크게 하여, 하나의 node안에 여러개의 element가 sorted array 형태로 들어가게 하여 list node 개수를 줄인다든지 하는 방식을 취할 수도 있겠죠.

이렇게 데이터구조가 사용되는 특성을 잘 파악하고 어떠한 식으로 구현할지는 개발자가 잘 정해서 할 수 밖에 없습니다. 특히 대용량 데이터의 경우는 말이죠.
일단 malloc()을 사용하여 어떻게든 잘 되도록 해보시고, 정 안된다면 최적화된 memory allocator를 구현해서 사용하셔야 할 것입니다.

익명 사용자의 이미지

ulra의 이미지

의견 주신 분들 감사드립니다. ^^
좋은 하루 되세요.

OTL 즐!!!! (좌절 금지!!!)

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.