heap-profiler 0.5.0 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/tests.yml +7 -33
- data/.rubocop.yml +3 -0
- data/Gemfile.lock +4 -2
- data/README.md +15 -1
- data/bin/generate-report +13 -0
- data/ext/heap_profiler/heap_profiler.cpp +12 -3
- data/ext/heap_profiler/simdjson.cpp +3472 -409
- data/ext/heap_profiler/simdjson.h +24123 -33047
- data/lib/heap_profiler/analyzer.rb +27 -1
- data/lib/heap_profiler/cli.rb +62 -9
- data/lib/heap_profiler/diff.rb +1 -0
- data/lib/heap_profiler/index.rb +1 -0
- data/lib/heap_profiler/reporter.rb +7 -5
- data/lib/heap_profiler/results.rb +53 -9
- data/lib/heap_profiler/runtime.rb +2 -2
- data/lib/heap_profiler/version.rb +1 -1
- metadata +3 -4
- data/.travis.yml +0 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: aca11eaccc68d8f62bd6ca0150f55ec43efa688ec9904682945b838c6b181afc
|
4
|
+
data.tar.gz: f46324b582fd4b4f840debd5efdf9418218d60e58ed84697848c4664b084523c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 825b314692a3a2f9673f5935fa66e42555ea35f9c72527e74fca906a32b90d24d6a7fc8247b5112b4c9d70baf03c3192938c770137833862380ed814f9863566
|
7
|
+
data.tar.gz: 2667a8bcdc9722114309a5136d58dbed32f06a964ed396940aebc7825a50b20f8fd85e8a73f4ae5103cb8e652b518db96101ccbe53cdf76147e3fffb02b52ad3
|
data/.github/workflows/tests.yml
CHANGED
@@ -6,25 +6,12 @@ jobs:
|
|
6
6
|
name: Rubocop
|
7
7
|
runs-on: ubuntu-latest
|
8
8
|
steps:
|
9
|
-
-
|
10
|
-
|
11
|
-
|
12
|
-
- name: Setup Ruby
|
9
|
+
- uses: actions/checkout@v3
|
10
|
+
- name: Set up Ruby
|
13
11
|
uses: ruby/setup-ruby@v1
|
14
12
|
with:
|
15
13
|
ruby-version: '2.5'
|
16
|
-
|
17
|
-
uses: actions/cache@v1
|
18
|
-
with:
|
19
|
-
path: vendor/bundle
|
20
|
-
key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}
|
21
|
-
restore-keys: |
|
22
|
-
${{ runner.os }}-gems-
|
23
|
-
- name: Install gems
|
24
|
-
run: |
|
25
|
-
bundle config path vendor/bundle
|
26
|
-
bundle install --jobs 4 --retry 3
|
27
|
-
|
14
|
+
bundler-cache: true
|
28
15
|
- name: Run linters
|
29
16
|
run: |
|
30
17
|
bin/rubocop -c .rubocop.yml
|
@@ -33,27 +20,14 @@ jobs:
|
|
33
20
|
runs-on: ubuntu-latest
|
34
21
|
strategy:
|
35
22
|
matrix:
|
36
|
-
ruby: [ '2.5', '2.6', '2.7', '3.0' ]
|
23
|
+
ruby: [ '2.5', '2.6', '2.7', '3.0', '3.1' ]
|
37
24
|
name: Ruby ${{ matrix.ruby }} Tests
|
38
25
|
steps:
|
39
|
-
-
|
40
|
-
|
41
|
-
|
42
|
-
- name: Setup Ruby
|
26
|
+
- uses: actions/checkout@v3
|
27
|
+
- name: Set up Ruby
|
43
28
|
uses: ruby/setup-ruby@v1
|
44
29
|
with:
|
45
30
|
ruby-version: ${{ matrix.ruby }}
|
46
|
-
|
47
|
-
uses: actions/cache@v1
|
48
|
-
with:
|
49
|
-
path: vendor/bundle
|
50
|
-
key: ${{ runner.os }}-${{ matrix.ruby }}-gems-${{ hashFiles('**/Gemfile.lock') }}
|
51
|
-
restore-keys: |
|
52
|
-
${{ runner.os }}-${{ matrix.ruby }}-gems-
|
53
|
-
- name: Install gems
|
54
|
-
run: |
|
55
|
-
bundle config path vendor/bundle
|
56
|
-
bundle install --jobs 4 --retry 3
|
57
|
-
|
31
|
+
bundler-cache: true
|
58
32
|
- name: Run tests
|
59
33
|
run: bundle exec rake
|
data/.rubocop.yml
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
heap-profiler (0.
|
4
|
+
heap-profiler (0.7.0)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: https://rubygems.org/
|
@@ -18,7 +18,7 @@ GEM
|
|
18
18
|
rake-compiler (1.1.1)
|
19
19
|
rake
|
20
20
|
regexp_parser (2.0.3)
|
21
|
-
rexml (3.2.
|
21
|
+
rexml (3.2.5)
|
22
22
|
rubocop (1.8.1)
|
23
23
|
parallel (~> 1.10)
|
24
24
|
parser (>= 3.0.0.0)
|
@@ -37,6 +37,8 @@ GEM
|
|
37
37
|
unicode-display_width (2.0.0)
|
38
38
|
|
39
39
|
PLATFORMS
|
40
|
+
arm64-darwin-21
|
41
|
+
arm64-darwin-22
|
40
42
|
x86_64-darwin-19
|
41
43
|
x86_64-darwin-20
|
42
44
|
x86_64-linux
|
data/README.md
CHANGED
@@ -41,6 +41,20 @@ To then analyse the profile, run the `heap-profiler` command against the directo
|
|
41
41
|
Note that on large applications this can take a while, but if you are profiling a production
|
42
42
|
application, you can download the profile directory and do the analysis on another machine.
|
43
43
|
|
44
|
+
### Options
|
45
|
+
|
46
|
+
```
|
47
|
+
Usage: heap-profiler <directory_or_heap_dump> OPTIONS
|
48
|
+
|
49
|
+
OPTIONS
|
50
|
+
|
51
|
+
-r, --retained-only Only compute report for memory retentions.
|
52
|
+
-m, --max=NUM Max number of entries to output. (Defaults to 50)
|
53
|
+
--batch-size SIZE Sets the simdjson parser batch size. It must be larger than the largest JSON document in the heap dump, and defaults to 10MB.
|
54
|
+
```
|
55
|
+
|
56
|
+
|
57
|
+
|
44
58
|
```bash
|
45
59
|
$ heap-profiler path/to/report/directory
|
46
60
|
Total allocated: 3.72 kB (36 objects)
|
@@ -229,7 +243,7 @@ If you can, you should enable allocation tracing as early as possible during you
|
|
229
243
|
|
230
244
|
```ruby
|
231
245
|
require 'objspace'
|
232
|
-
ObjectSpace.trace_object_allocations_start
|
246
|
+
ObjectSpace.trace_object_allocations_start
|
233
247
|
```
|
234
248
|
|
235
249
|
Then to dump the heap:
|
data/bin/generate-report
CHANGED
@@ -6,6 +6,17 @@ require 'fileutils'
|
|
6
6
|
require 'date'
|
7
7
|
|
8
8
|
class SomeCustomStuff
|
9
|
+
def initialize
|
10
|
+
@root = 1
|
11
|
+
end
|
12
|
+
|
13
|
+
def foo
|
14
|
+
@foo = 1
|
15
|
+
end
|
16
|
+
|
17
|
+
def bar
|
18
|
+
@bar = 2
|
19
|
+
end
|
9
20
|
end
|
10
21
|
|
11
22
|
$freed_objects = [+"i am free", +"i am free too"]
|
@@ -18,6 +29,8 @@ if ARGV[1] == '--empty'
|
|
18
29
|
HeapProfiler.report(dir) {}
|
19
30
|
else
|
20
31
|
HeapProfiler.report(dir) do
|
32
|
+
SomeCustomStuff.new.tap(&:foo).tap(&:bar)
|
33
|
+
SomeCustomStuff.new.tap(&:bar)
|
21
34
|
$retained_objects = [
|
22
35
|
+"I am retained",
|
23
36
|
+"I am retained",
|
@@ -7,7 +7,7 @@ using namespace simdjson;
|
|
7
7
|
|
8
8
|
static VALUE rb_eHeapProfilerError, rb_eHeapProfilerCapacityError, sym_type, sym_class,
|
9
9
|
sym_address, sym_value, sym_memsize, sym_imemo_type, sym_struct, sym_file,
|
10
|
-
sym_line, sym_shared, sym_references, id_uminus;
|
10
|
+
sym_line, sym_shared, sym_references, sym_edge_name, id_uminus;
|
11
11
|
|
12
12
|
typedef struct {
|
13
13
|
dom::parser *parser;
|
@@ -190,8 +190,11 @@ static VALUE make_ruby_object(dom::object object)
|
|
190
190
|
}
|
191
191
|
|
192
192
|
std::string_view _class;
|
193
|
-
if (
|
194
|
-
|
193
|
+
if (type != "IMEMO") {
|
194
|
+
// IMEMO "class" field can sometime be junk
|
195
|
+
if (!object["class"].get(_class)) {
|
196
|
+
rb_hash_aset(hash, sym_class, INT2FIX(parse_address(_class)));
|
197
|
+
}
|
195
198
|
}
|
196
199
|
|
197
200
|
uint64_t memsize;
|
@@ -233,6 +236,11 @@ static VALUE make_ruby_object(dom::object object)
|
|
233
236
|
rb_hash_aset(hash, sym_references, references);
|
234
237
|
}
|
235
238
|
}
|
239
|
+
} else if (type == "SHAPE") {
|
240
|
+
std::string_view edge_name;
|
241
|
+
if (!object["edge_name"].get(edge_name)) {
|
242
|
+
rb_hash_aset(hash, sym_edge_name, make_string(edge_name));
|
243
|
+
}
|
236
244
|
}
|
237
245
|
|
238
246
|
std::string_view file;
|
@@ -299,6 +307,7 @@ extern "C" {
|
|
299
307
|
sym_type = ID2SYM(rb_intern("type"));
|
300
308
|
sym_class = ID2SYM(rb_intern("class"));
|
301
309
|
sym_address = ID2SYM(rb_intern("address"));
|
310
|
+
sym_edge_name = ID2SYM(rb_intern("edge_name"));
|
302
311
|
sym_value = ID2SYM(rb_intern("value"));
|
303
312
|
sym_memsize = ID2SYM(rb_intern("memsize"));
|
304
313
|
sym_struct = ID2SYM(rb_intern("struct"));
|