ruby/ruby — pull request #423 by tmm1 (2013-10-16 01:50:50+00:00)
Title: Add ObjectSpace.heap_dump to objspace.so

In large ruby applications it is quite tricky to track down the cause of increased memory usage, especially when a reference leak is present (a global/root object holding references to an increasing number of objects over time).

This patch adds a `ObjectSpace.heap_dump` to objspace.so. This new method dumps out the contents of the ruby heap as json, either to stdout or an optional file.

``` ruby
ObjectSpace.trace_object_allocations_start
GC.start
ObjectSpace.heap_dump
```

---

##### root objects

Objects referenced by roots are listed in ROOT entries:

```
{"type":"ROOT", "root":"vm", "references":["0x7f82f28d0640"]}
{"type":"ROOT", "root":"global_list", "references":["0x7f82f2833638", "0x7f82f282bf78"]}
{"type":"ROOT", "root":"global_tbl", "references":["0x7f82f28db428", "0x7f82f28db428", "0x7f82f28dac08", "0x7f82f28dab90", "0x7f82f28dab18", "0x7f82f28dab90", "0x7f82f28da898", "0x7f82f28da898", "0x7f82f28da898", "0x7f82f28da898", "0x7f82f28da898", "0x7f82f28d0640", "0x7f82f28d0640", "0x7f82f28d0640", "0x7f82f293b5f8", "0x7f82f293b5f8"]}
```

##### strings

STRING entries contain details about the strings size, class, shared/frozen/embedded status and outbound references:

```
{"address":"0x7f82f2828008", "type":"STRING", "class":"0x7f82f2829660", "frozen":true, "embedded":true, "bytesize":9, "value":"LoadError", "encoding":"US-ASCII"}
{"address":"0x7f82f2833e80", "type":"STRING", "class":"0x7f82f2829660", "embedded":true, "bytesize":5, "value":"Class", "encoding":"US-ASCII", "file":"-e", "line":1, "generation":6}
{"address":"0x7f82f2833778", "type":"STRING", "class":"0x7f82f2829660", "shared":true, "references":["0x7f82f2832f58"]}
{"address":"0x7f82f28399e8", "type":"STRING", "class":"0x7f82f2829660", "frozen":true, "bytesize":19, "capacity":120, "value":"block in initialize", "memsize":120}
```

##### hashes

```
{"address":"0x7f82f2859b58", "type":"HASH", "class":"0x7f82f28e1940", "size":0, "default":"0x7f82f2859b08", "references":["0x7f82f2859b08"], "memsize":192}
{"address":"0x7f82f285adf0", "type":"HASH", "class":"0x7f82f28e1940", "size":2, "references":["0x7f82f285adc8", "0x7f82f285acd8"], "memsize":192}
```

##### arrays

```
{"address":"0x7f82f2872068", "type":"ARRAY", "length":1, "embedded":true, "references":["0x7f82f2901c40"]}
{"address":"0x7f82f2890568", "type":"ARRAY", "length":56, "references":["0x7f82f2890dd8", "0x7f82f2890338", "0x7f82f288ba18", "0x7f82f288b2c0", "0x7f82f288ac58", "0x7f82f288a000", "0x7f82f28891a0", "0x7f82f2888598", "0x7f82f287af10", "0x7f82f2878530", "0x7f82f28780a8", "0x7f82f2873c10", "0x7f82f28737d8", "0x7f82f28734b8", "0x7f82f2873120", "0x7f82f2872e50", "0x7f82f29310a8", "0x7f82f2930388", "0x7f82f2930220", "0x7f82f292bd60", "0x7f82f292bc70", "0x7f82f292a528", "0x7f82f292a208", "0x7f82f2929e48", "0x7f82f290bdd0", "0x7f82f290bce0", "0x7f82f290bb28", "0x7f82f290b6f0", "0x7f82f290b5b0", "0x7f82f290b268", "0x7f82f290ae08", "0x7f82f290ad18", "0x7f82f28782b0", "0x7f82f29094e0", "0x7f82f2907258", "0x7f82f2906f10", "0x7f82f2906e20", "0x7f82f2906d58", "0x7f82f2906b50", "0x7f82f2906920", "0x7f82f2906678", "0x7f82f2906308", "0x7f82f2906060", "0x7f82f2905de0", "0x7f82f2905b10", "0x7f82f2905840", "0x7f82f2905430", "0x7f82f29051b0", "0x7f82f29050c0", "0x7f82f2904eb8", "0x7f82f2904e40", "0x7f82f2904dc8", "0x7f82f2904d50", "0x7f82f2904cd8", "0x7f82f29045a8", "0x7f82f2904288"], "memsize":448}
```

##### data

```
{"address":"0x7f82f2890dd8", "type":"DATA", "class":"0x7f82f28d02f8", "struct":"iseq", "references":["0x7f82f28906f8", "0x7f82f2890ec8", "0x7f82f28917b0", "0x7f82f292ac08", "0x7f82f292ac08", "0x7f82f28913f0"], "memsize":976}
{"address":"0x7f82f2963b20", "type":"DATA", "class":"0x7f82f28d9128", "struct":"time", "memsize":88}
```

##### nodes

```
{"address":"0x7f82f2960b50", "type":"NODE", "node_type":"NODE_CREF", "references":["0x7f82f282b7a8"]}
{"address":"0x7f82f293b648", "type":"NODE", "node_type":"NODE_BLOCK", "references":["0x7f82f293b670"]}
{"address":"0x7f82f293b670", "type":"NODE", "node_type":"NODE_CALL", "references":["0x7f82f293b698"]}
{"address":"0x7f82f293b698", "type":"NODE", "node_type":"NODE_CONST"}
```

##### classes and modules

```
{"address":"0x7f82f28280d0", "type":"CLASS", "class":"0x7f82f28280a8", "name":"ScriptError", "references":["0x7f82f2832e40", "0x7f82f28286e8"], "memsize":656}
{"address":"0x7f82f2829e58", "type":"MODULE", "class":"0x7f82f282b758", "name":"Comparable", "references":["0x7f82f2829e58", "0x7f82f2829e58", "0x7f82f2829e58", "0x7f82f2829e58", "0x7f82f2829e58", "0x7f82f2829e58", "0x7f82f28324b8"], "memsize":848}
{"address":"0x7f82f28504e0", "type":"ICLASS", "class":"0x7f82f2829e58", "references":["0x7f82f28324b8", "0x7f82f282b7a8"]}
```

##### other objects

```
{"address":"0x7f82f28328c8", "type":"OBJECT", "class":"0x7f82f2838188", "ivars":3, "references":["0x7f82f285b638"]}
```