README (4325B)
1 Logalloc is a replace-malloc library for Firefox (see 2 memory/build/replace_malloc.h) that dumps a log of memory allocations to a 3 given file descriptor or file name. That log can then be replayed against 4 Firefox's default memory allocator independently or through another 5 replace-malloc library, allowing the testing of other allocators under the 6 exact same workload. 7 8 To get an allocation log the following environment variable when starting 9 Firefox: 10 MALLOC_LOG=/path/to/log-file 11 or 12 MALLOC_LOG=number 13 14 When MALLOC_LOG is a number below 10000, it is considered as a file 15 descriptor number that is fed to Firefox when it is started. Otherwise, 16 it is considered as a file name. 17 18 As those allocation logs can grow large quite quickly, it can be useful 19 to pipe the output to a compression tool. 20 21 MALLOC_LOG=1 would send to Firefox's stdout, MALLOC_LOG=2 would send to 22 its stderr. Since in both cases that could be mixed with other output 23 from Firefox, it is usually better to use another file descriptor 24 by shell redirections, such as: 25 26 MALLOC_LOG=3 firefox 3>&1 1>&2 | gzip -c > log.gz 27 28 (3>&1 copies the `| gzip` pipe file descriptor to file descriptor #3, 1>&2 29 then copies stderr to stdout. This leads to: fd1 and fd2 sending to stderr 30 of the parent process (the shell), and fd3 sending to gzip.) 31 32 Each line of the allocations log is formatted as follows: 33 <pid> <tid> <function>([<args>])[=<result>] 34 where <args> is a comma separated list of values. The number of <args> and 35 the presence of <result> depend on the <function>. 36 37 Example log: 38 18545 18545 malloc(32)=0x7f90495120e0 39 18545 18545 calloc(1,148)=0x7f9049537480 40 18545 18545 realloc(0x7f90495120e0,64)=0x7f9049536680 41 18545 18545 posix_memalign(256,240)=0x7f9049583300 42 18545 18545 jemalloc_stats() 43 18545 18545 free(0x7f9049536680) 44 45 This log can be replayed with the logalloc-replay tool in 46 memory/replace/logalloc/replay. However, as the goal of that tool is to 47 reproduce the recorded memory allocations, it needs to avoid as much as 48 possible doing its own allocations for bookkeeping. Reading the logs as 49 they are would require data structures and memory allocations. As a 50 consequence, the logs need to be preprocessed beforehand. 51 52 The logalloc_munge.py script is responsible for that preprocessing. It simply 53 takes a raw log on its stdin, and outputs the preprocessed log on its stdout. 54 It replaces pointer addresses with indexes the logalloc-replay tool can use 55 in a large (almost) linear array of allocation tracking slots (prefixed with 56 '#'). It also replaces the pids with numbers starting from 1 (such as the 57 first seen pid number is 1, the second is 2, etc.). 58 59 The above example log would become the following, once preprocessed: 60 1 1 malloc(32)=#1 61 1 1 calloc(1,148)=#2 62 1 1 realloc(#1,64)=#1 63 1 1 posix_memalign(256,240)=#3 64 1 1 jemalloc_stats() 65 1 1 free(#1) 66 67 The logalloc-replay tool then takes the preprocessed log on its stdin and 68 replays the allocations printed there, but will only replay those with the 69 same process id as the first line (which normally is 1). 70 71 As the log files are simple text files, though, it is easy to separate out 72 the different processes log with e.g. grep, and feed the separate processes 73 logs to logalloc-replay. 74 75 The logalloc-replay program won't output anything unless jemalloc_stats 76 records appears in the log. You can expect those to be recorded when going 77 to about:memory in Firefox, but they can also be added after preprocessing. 78 79 Here is an example of what one can do: 80 81 gunzip -c log.gz | python logalloc_munge.py | \ 82 awk '$1 == "2" { print $0 } !(NR % 10000) { print "2 1 jemalloc_stats()" }' | \ 83 ./logalloc-replay 84 85 The above command replays the allocations of process #2, with some stats 86 output every 10000 records. 87 88 The logalloc-replay tool itself being hooked with replace-malloc, it is possible 89 to set LD_PRELOAD/DYLD_INSERT_LIBRARIES/MOZ_REPLACE_MALLOC_LIB and replay a log 90 through a different allocator. For example: 91 92 LD_PRELOAD=libreplace_jemalloc.so logalloc-replay < log 93 94 Will replay the log against jemalloc4 (which is, as of writing, what 95 libreplace_jemalloc.so contains). 96 97 The log files can also be used for other analysis. The logalloc_stats.py 98 script will tally the allocation requests for small, large and huge 99 allocations (as configured on a system with 4KiB pages). 100