Trace allocations of R vectors using bpftrace
| #!/usr/bin/env bpftrace | |
| /* | |
| * ralloc - Print allocations of R vectors. | |
| * | |
| * Copyright 2020 Aaron Jacobs | |
| * Licensed under the MIT License or the Apache License, version 2.0. | |
| */ | |
| BEGIN | |
| { | |
| printf("Tracing R allocations each second... hit Ctrl-C to exit.\n\n"); | |
| printf(" TIME %8s %8s %8s %8s %8s %8s ", | |
| "VECSXP", "LGLSXP", "INTSXP", "REALSXP", "STRSXP", "RAWSXP"); | |
| printf("%8s %8s\n", "CHARSXP", "OTHER"); | |
| } | |
| uprobe:/usr/lib/R/lib/libR.so:Rf_allocVector3 | |
| { | |
| /* | |
| * Rf_allocVector3() takes the SEXPTYPE as its first argument, which | |
| * we can decode as an unsigned integer. | |
| * | |
| * The various SEXPTYPEs can be found in <Rinternals.h>, and are | |
| * reproduced below: | |
| * | |
| * NILSXP 0 nil = NULL | |
| * SYMSXP 1 symbols | |
| * LISTSXP 2 lists of dotted pairs | |
| * CLOSXP 3 closures | |
| * ENVSXP 4 environments | |
| * PROMSXP 5 promises: [un]evaluated closure arguments | |
| * LANGSXP 6 language constructs (special lists) | |
| * SPECIALSXP 7 special forms | |
| * BUILTINSXP 8 builtin non-special forms | |
| * CHARSXP 9 "scalar" string type (internal only)g | |
| * LGLSXP 10 logical vectors | |
| * INTSXP 13 integer vectors | |
| * REALSXP 14 real variables | |
| * CPLXSXP 15 complex variables | |
| * STRSXP 16 string vectors | |
| * DOTSXP 17 dot-dot-dot object | |
| * ANYSXP 18 make "any" args work. | |
| * VECSXP 19 generic vectors | |
| * EXPRSXP 20 expressions vectors | |
| * BCODESXP 21 byte code | |
| * EXTPTRSXP 22 external pointer | |
| * WEAKREFSXP 23 weak reference | |
| * RAWSXP 24 raw bytes | |
| * S4SXP 25 S4, non-vector | |
| * NEWSXP 30 fresh node created in new page | |
| * FREESXP 31 node released by GC | |
| * FUNSXP 99 Closure or Builtin or Special | |
| */ | |
| @allocs[arg0]++; | |
| } | |
| interval:s:1 | |
| { | |
| $other = @allocs[0] + @allocs[6] + @allocs[15] + @allocs[20]; | |
| time("%H:%M:%S "); | |
| printf("%8d %8d %8d %8d %8d %8d ", @allocs[19], @allocs[10], | |
| @allocs[13], @allocs[14], @allocs[16], @allocs[24]); | |
| printf("%8d %8d\n", @allocs[73], $other); | |
| delete(@allocs[19]); | |
| delete(@allocs[10]); | |
| delete(@allocs[13]); | |
| delete(@allocs[14]); | |
| delete(@allocs[16]); | |
| delete(@allocs[24]); | |
| delete(@allocs[73]); | |
| delete(@allocs[15]); | |
| delete(@allocs[0]); | |
| delete(@allocs[6]); | |
| delete(@allocs[20]); | |
| } | |
| END | |
| { | |
| /* | |
| * This is just to prevent leftover map contents from being printed when the | |
| * program exits. We could also use clear(), but I'm interested in what is not | |
| * caught by this program in its current form. | |
| */ | |
| delete(@allocs[19]); | |
| delete(@allocs[10]); | |
| delete(@allocs[13]); | |
| delete(@allocs[14]); | |
| delete(@allocs[16]); | |
| delete(@allocs[24]); | |
| delete(@allocs[73]); | |
| delete(@allocs[15]); | |
| delete(@allocs[0]); | |
| delete(@allocs[6]); | |
| delete(@allocs[20]); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment