Follow softwareverify on Twitter
0 items - $0.00

The fastest way to monitor billions of memory allocations

Ruby Memory Tracking API

The standard Ruby distribution provides a profiling API that allows you to determine function calls, function returns, line visits, class creation events and exception creation.

During the creation of our Ruby Memory Analysis software tool Ruby Memory Validator we had to reverse engineer our own memory monitoring hooks to monitor the creation and destruction of objects. We also had to work out how to create a heap dump and how to determine which objects reference which other objects.

Neither of these tasks is easy. The heap dump and object reference code is the hardest to create. With the recent 1.8.5 Ruby build the is_heap_pointer() static function (in gc.c) has been inlined making it impossible to identify a function that you can call to determine if an object is a valid Ruby object.

We have solved these problems for use in Ruby Memory Validator. However it would be very useful if some functions existed that made memory tracking easier to perform. With that in mind we have created a simple memory tracking API that can be used alongside the existing profiling API. We have deliberately avoided extending or modifying the existing profiling API, preferring to provide an additional API that can be encapsulated in as little code as possible.

The code for the API is provided in two source files (memtrack.h and memtrack.c) and a modified version of gc.c. If desired the contents of memtrack.c could be included in gc.c with very little effort. gc.c needed to be modified so that calls to memtrack code could be inserted and also to provide the heap walking and object reference functionality.

The Memory Tracking API

The memory tracking API comprises four functions, an enumeration and two function prototypes to define callbacks used by the functions.

Memory activity enumeration

Enumeration defining type of memory behaviour. Currently limited to allocation and deallocation. Could be extended to include GC starting, GC ending, etc.

typedef enum
{
    ROTA_ALLOCATE,
    ROTA_DEALLOCATE,
} ROTA_ACTION;

Memory activity notification callback

typedef void (*RUBY_OBJ_TRACKER)(VALUE       obj,		
                                 ROTA_ACTION action);	

Object tracing functions

void rb_set_object_tracing_hook(RUBY_OBJ_TRACKER func);

RUBY_OBJ_TRACKER rb_get_object_tracing_hook();

Heap dump and object reference callback

typedef int (*RUBY_HEAP_ROOTS)(VALUE obj, 
                               void  *userData);

Heap dump and object reference functions

Note that each function is passed a callback to call for each object found and a user data parameter that will be passed to the callback.

The rb_get_referenced_objects() function gets the list of all objects referenced by the parameter "obj"

void rb_get_heap_roots(RUBY_HEAP_ROOTS callback,
                       void            *userData);

void rb_get_referenced_objects(VALUE           obj,
                               RUBY_HEAP_ROOTS callback,
                               void            *userData);

Source Code

The source code files are here:

Ruby Binary

We provide here an updated binary for Ruby 1.8.5 that includes the source code mentioned above. We recommend that you install Ruby 1.8.5 using the Ruby 1-Click Installer then drop the Ruby DLL (msvcrt-ruby18.dll) into the Ruby install directory for the Ruby 1-Click Installer. Same procedure for 1.8.6 and 1.8.7 (when One-Click 1.8.7 is released)

Ruby Memory Validator Integration

If you use the modified Ruby binary with Ruby Memory Validator the new API functions will be automatically detected and used in preference to the reverse engineered methods we have created.

Go to Top ^^