Global VM Lock

AppSignal for RubyThis feature requires version 3.3.9 or higher.
RubyThis feature requires version 3.2 or higher.
gvltoolsThis feature requires version 0.2 or higher.

The Ruby VM (Virtual Machine) schedules Ruby threads for execution. At any given point in time, only one thread at a time is allowed to interact with the state of the Ruby VM. The mechanism by which the Ruby interpreter ensures this is called the Global VM Lock (GVL).

Switching between threads has an overhead of its own. The metrics on the Global VM Lock allow you to see the time that a thread spends waiting for its turn to run, and the amount of threads that are awaiting execution at a given time. This can provide you with helpful insights in understanding performance issues in your application.

Installation

The gvltools library is only compatible with the official Ruby interpreter. JRuby is not supported.

For AppSignal to be able to obtain Global VM Lock metrics, you must add the gvltools library to your project:

shell
bundle add gvltools

Metrics

If the library is installed, when the AppSignal integration starts, it will automatically start collecting Global VM Lock metrics every minute.

A magic dashboard displaying these metrics will be automatically created. It will appear as "Ruby GVL" in your AppSignal dashboard list.

Ruby GVL Magic Dashoard creation

Waiting threads

A gvl_waiting_threads metric will be reported, whose value is the number of threads that are currently waiting to acquire the lock and resume execution.

To disable this metric, you can set the enable_gvl_waiting_threads configuration option to false.

Global timer

A gvl_global_timer metric will be reported, whose value is the cumulative time spent by all threads waiting to acquire the lock and resume execution over the last minute.

To disable this metric, you can set the enable_gvl_global_timer configuration option to false.

The overhead in the measurement of the global timer metric is estimated to be around 5%. Due to this, you may want to keep the global timer instrumentation disabled by default, to avoid the performance cost it incurs in your application, but enable it on demand, perhaps in a specific request or job that makes heavy use of threads. You can enable and disable this metrics manually through the gvltools library:

ruby
require "gvltools" GVLTools::GlobalTimer.enable # ... some code that uses threads ... GVLTools::GlobalTimer.disable

If enable_gvl_global_timer is set to false, the global timer metric won't be enabled on startup, but the minutely probe for the GVL metrics will still be active. This allows you to manually enable the metrics on demand and start receiving metrics without needing to restart your application.

Magic dashboard

A "GVL" magic dashboard will automatically be created when these metrics are received:

Ruby GVL magic dashboard