{"id":19795611,"url":"https://github.com/dkogan/memory_leak_instrumentation","last_synced_at":"2025-06-12T09:40:46.111Z","repository":{"id":136714505,"uuid":"43666863","full_name":"dkogan/memory_leak_instrumentation","owner":"dkogan","description":null,"archived":false,"fork":false,"pushed_at":"2020-04-16T18:32:15.000Z","size":40,"stargazers_count":13,"open_issues_count":0,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-05-01T03:36:05.605Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Perl","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dkogan.png","metadata":{"files":{"readme":"README.org","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2015-10-05T05:30:19.000Z","updated_at":"2024-02-18T13:58:46.000Z","dependencies_parsed_at":null,"dependency_job_id":"eb7a7e07-98a7-49c4-8953-18da1bc4b2e6","html_url":"https://github.com/dkogan/memory_leak_instrumentation","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/dkogan/memory_leak_instrumentation","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dkogan%2Fmemory_leak_instrumentation","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dkogan%2Fmemory_leak_instrumentation/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dkogan%2Fmemory_leak_instrumentation/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dkogan%2Fmemory_leak_instrumentation/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dkogan","download_url":"https://codeload.github.com/dkogan/memory_leak_instrumentation/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dkogan%2Fmemory_leak_instrumentation/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":259440220,"owners_count":22857873,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-12T07:16:51.857Z","updated_at":"2025-06-12T09:40:46.088Z","avatar_url":"https://github.com/dkogan.png","language":"Perl","funding_links":[],"categories":[],"sub_categories":[],"readme":"* Overview\n\nThis is a set of tools used to find memory leaks in long-running applications.\nThese tools use [[http://perf.wiki.kernel.org/][=perf=]] to instrument all memory allocations/deallocations. These\ntraces can then be analyzed to find allocated memory that was not properly\ncleaned up.\n\nThis was written to find memory leaks in emacs daemon sessions. The resulting\nbugs and mailing list posts:\n\n- https://lists.gnu.org/archive/html/emacs-devel/2015-09/msg00814.html\n- http://debbugs.gnu.org/cgi/bugreport.cgi?bug=21509\n- http://debbugs.gnu.org/cgi/bugreport.cgi?bug=21556\n- http://debbugs.gnu.org/cgi/bugreport.cgi?bug=21623\n\nSome of the tools are emacs-specific, but some are not. Note that this is all\nfairly rough, and the user would want to understand how each tool works to be\nable to use it effectively. This is also not well-documented yet, but the links\nabove, and the text below show examples.\n\n* Tools\n\n** Non-emacs-specific\n\n*** =reademacsvar.sh=\nExports some shell variables that all the scripts use to do their thing. Mostly\nthis is paths, etc.\n\n*** =plotmem.sh=\nUsed to generate a realtime plot of memory usage of a particular process. This\nlets us see the leaks as they happen.\n\n*** =probes.sh=\nCreates =perf= probes that we care about. This is all allocation/deallocations,\nand anything else we like.\n\n*** =record_alloc.sh=\nRuns =perf record= to record all allocations/deallocations.\n\n*** =parse_script.pl=\nReads the output of =perf script=, following all allocations. The output is a\nlist of all unexpected memory operations (calling =free()= on a pointer that\ndidn't come from =malloc()= for instance) and a list of all potentially leaky\nmemory (anything that was allocated but not freed). If we started logging some\ntime after the process has started, and finished logging before the process has\nfinished then both of these will have false positives:\n\n- We could see a =free()= of memory that was allocated before we started logging\n- We can report a leak for something that was =free()=-ed after we stopped\n  logging\n\nSo take all output with a grain of salt, and use your best judgement. The\nbacktraces come from =perf=. It reports code addresses, and not line numbers.\nYou can get the line numbers line this:\n\n#+begin_example\naddr2line -e LIBRARY ADDRESS\n#+end_example\n\nwhere =LIBRARY= and =ADDRESS= come from the =perf= backtrace.\n\n*** =plotleaks.sh=\nTakes the output of =parse_script.pl=, and makes a plot of potential leak sizes\nvs input line number. This is useful to quickly see the leaks. For instance,\nlet's say the emacs session we're tracing leaks 3072 bytes each time a new frame\nis created, and that we created 10 frames in a row while running =perf record=.\nThe plot this script produces would then show 10 points at 3072 evenly spaced\nthrough time. Leaks at the start of the session are most likely to be true ones\n(there was time to =free()= the memory), so I generally follow up anything that\nleaked lots of memory at the start.\n\n*** =follow_alloc.pl=\nReads the output of =perf script=, and filters out all memory operations that do\nnot refer to a particular allocation size. This is useful to focus on particular\nallocations identified by =plotleaks.sh=. So if =plotleaks.sh= shows lots of\nleaks of size 3072, we use this to cut down the log to show only the leaks we\ncare about.\n\n** Emacs-specific\n\n*** =daemon.sh=\nStarts up a new emacs daemon.\n\n*** =client.sh=\nCreates a new client frame.\n\n*** =kill.sh=\nKills the emacs daemon.\n\n*** =loopclient.sh=\nRepeatedly creates/destroys a client frame.\n\n*** =show_stderr.sh=\nShows the STDERR output of a process (emacs in this case). This is useful\nbecause the emacs daemon redirects its STDERR to =/dev/null=, but gdb printing\ncommands such as =pr= and =pp= write to STDERR, and we want to see this output.\n\n* General notes\n\nWhen running =perf record=, the =perf= process can be overloaded and drop events\nas a result (an error message says this). A larger buffer can help (=-m= option)\nat the expense of using more RAM. It also helps to make smaller logs (fewer\nthings to record, =fp= backtrace generation instead of =DWARF=; see below).\n\n=perf= can generate backtraces in two ways:\n- Using the frame-pointer. This is the preferred method, but it only works for\n  functions that have a frame pointer. All gcc optimization levels strip this\n  out, so rebuild with =-fno-omit-frame-pointer= if possible.\n- Using DWARF debug information. This doesn't require frame pointers, but needs\n  debug info. Another down side is that this generates much bigger =perf= logs,\n  and =perf= is more likely to drop events. Currently =perf= has a bug in that\n  it's not able to read the split debug information in Debian packages, so you\n  need this patch: http://lkml.iu.edu/hypermail/linux/kernel/1509.0/04006.html\n\nIf the binary application being instrumented is rebuilt, probes into that\napplication need to be deleted and re-added.\n\n* Example\n\nA usage example appears [[http://notes.secretsauce.net/notes/2015/10/05_memory-leak-debugging-tools.html][here]].\n\n* License\n\nReleased into the public domain. Do whatever you like.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdkogan%2Fmemory_leak_instrumentation","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdkogan%2Fmemory_leak_instrumentation","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdkogan%2Fmemory_leak_instrumentation/lists"}