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:     num   pid   simulated time       PC            mem used    created
udb:        0 12064          0      0xffffffffffffffff  183.00K    15:09:15
udb:        1 12066      65536      0xffffffffffffffff  308.00K    15:09:15
udb:        2 12068     131072      0xffffffffffffffff  337.00K    15:09:15
udb:        3 12070     196608      0xffffffffffffffff  372.00K    15:09:15
udb:        4 12072     262144      0xffffffffffffffff  422.00K    15:09:15
udb:        5 12074     327680      0xffffffffffffffff  473.00K    15:09:15
udb:        6 12076    1376256      0xffffffffffffffff  850.00K    15:09:17
udb:   =>   7 12056    1480669      0x0000000000422fd0   11.96M    15:09:15
udb: Client: pid=12060; memory used=972.00K
udb: Total memory used: 15.78M
udb: Snapshot creation times: mean=2ms; max=3ms; previous=3ms
(udb)

The columns in the table are as follows:

  • num: 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.
  • pid: the process ID for the snapshot.
  • simulated time: the number of basic blocks (bbcount) that were executed by the debuggee (the “record child”) before the snapshot was created.
  • created: the wall-clock time at which the snapshot was created.
  • PC: the program counter value at which the snapshot was created. The combination of this value and the simulated time value uniquely refers to a single point in program history. If the value is 0xffffffffffffffff, the program counter for the snapshot in question is in internal UndoDB code rather than in the debuggee.
  • mem used: 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>