Skip to content

Instantly share code, notes, and snippets.

@atheriel
Last active April 6, 2020 12:09
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save atheriel/20f41cef79a9d13435a644d2ae3ff4cd to your computer and use it in GitHub Desktop.
Save atheriel/20f41cef79a9d13435a644d2ae3ff4cd to your computer and use it in GitHub Desktop.
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