Snapshots

Snapshots capture the state of a process at a particular time in its execution.

Reverse execution is implemented by replaying a process’s execution from previously captured snapshots. Since the replay is guaranteed to be deterministic (due to the event log), when a snapshot is played forwards it will eventually reach the next snapshot.

In order to minimise their overhead snapshots are created by forking the original process. This means they benefit from Linux’s copy-on-write support and hence each snapshot only holds copies of data for ranges of memory subsequently modified by the original process.

_images/snapshots.png

Viewing snapshot information

You can view snapshot information in UndoDB using the uinfo snapshots command:

(udb) uinfo snapshots
udb:  number                        recording time      pid   memory   created
udb:       0                  1:0x00007f139a72f003    30060  744.00K  12:59:10
udb: =>    1             30,411:0x00007f139a434a76    30052   50.65M  12:59:10
udb: Nanny: pid=30056; memory used=2.16M
udb: Total memory used: 53.53M
udb: Snapshot creation times: mean=1ms; max=2ms; previous=2ms

The columns in the table are as follows:

  • number: an identifier that is used to refer to each snapshot. The snapshots are ordered chronologically in simulated time, not wall-clock time. So depending on the navigation path through the history of the debuggee, new snapshots will be created and/or deleted in locations other than at the end of the list.
  • recording time: the notional execution time of the snapshot. Generally, points at the next instruction to be executed if execution restarts from the given snapshot.
  • created: the wall-clock time at which the snapshot was created.
  • pid: the process ID for the snapshot.
  • memory: the memory used by each snapshot, as determined by the “proportional set size” (PSS) documented in proc(5).

One of the snapshots has an arrow pointing to it (=>), and this is the snapshot that is currently being used for replay.

Configuring snapshots

It’s possible to configure the number of snapshots; this is a trade-off between memory overhead and performance of reverse commands:

  • Reducing the number of snapshots will reduce the memory overhead, however it is also likely to mean reverse commands are slower.
  • Increasing the number of snapshots will increase the memory overhead, however it is also likely to mean reverse commands are faster.

Note

Given that reverse execution involves jumping to the last snapshot and playing it forward, fewer snapshots means that the distance between snapshots will typically be greater and hence more re-execution is required to perform reverse execution.

The maximum number of snapshots can be set using the --undodb-snapshots argument, which has a default value of 35. For example:

udb --undodb-snapshots 20 <args>