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, only one thread at a time can be active and interact with the state of the Ruby VM.

The mechanism by which the Ruby interpreter ensures this is 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 a thread spends waiting for its turn to run, and the number of threads awaiting execution at a given time. These metrics can provide helpful insights for understanding performance issues in your application.

When AppSignal detects Global VM Lock metrics, it will create an Automated Dashboard, allowing you to monitor core metrics visually.

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

Once installed, the AppSignal integration will automatically collect Global VM Lock metrics every minute.

Automated dashboards

Automated dashboards will appear in the Dashboard section of AppSignal.

Ruby GVL Magic Dashboard creation

The Global VM Lock automated dashboard has the following graphs:

GraphMetric
Global timergvl_global_timer
Waiting threadsgvl_waiting_threads

AppSignal reports the following tags for Global VM Lock metrics:

NameDescription
hostnameThe name of the host that the metric was reported from
process_idThe ID of the process that the metric was reported from
process_nameThe name of the process that the metric was reported from

The process_id and process_name tags are only reported when using AppSignal for Ruby version 3.9.3 or newer.

Ruby GVL automated dashboard

Global timer graph

The global timer graph shows the time that threads spent waiting to be resumed during the last minute, that is, waiting for their code to be executed again.

Configuring global timer measurement

Measuring the global timer has an estimated performance overhead of 5%.

To prevent negative impacts on your application's performance, you may want to disable gvl_global_timer by default and enable it when needed for specific requests or thread-intensive jobs.

To disable this metric at start time, set the enable_gvl_global_timer configuration option to false.

Then, you can use the gvltools library to enable and disable the global timer measurement without having to restart your application:

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

Waiting threads graph

The waiting threads graph shows the number of threads waiting to be resumed at any given time. The graph does not include threads that are not ready to be resumed, such as threads that are sleeping or awaiting an I/O event.

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