Clocks and Time
Time management is fundamental to Gears
. If you've been following along the tutorials, you have already scheduled tasks at regular intervals. In this tutorial, we will cover how time is being managed and how you can control it for simulations.
Time Abstraction
Gears
abstracts time through Clocks. Clocks provide a unified interface for getting the current time, whether you're working with real system time or controllable simulation time. Under the hood, EnviornmentEngine
will call the now
function on the active clock to get the current time.
Gears.now
— Functionnow(clock::Clock)
Returns the current time in the clock using Unitful to represent the unit of time.
Clock Types
MachineClock - Real System Time
MachineClock
uses your system's real time:
using Gears
clock = MachineClock()
println(now(clock)) # Current system time, 0.0 seconds
resume!(clock)
sleep(1.0)
pause!(clock)
println(now(clock)) # Current system time, 1.0 seconds
0.0 s
1.0152549743652344 s
When created, the MachineClock
is paused by default, and can be resumed and paused at any time.
Gears.MachineClock
— TypeMachineClock
A clock that uses the system time. The time is represented in seconds. Supports pausing and resuming to decouple logical time from system time. The start_time
, pause_start_time
, and total_paused_time
are all represented in seconds and are wall clock (unstretched) time. Whenever now
is called, the time is stretched by the stretch_factor
. This means that when the stretch_factor
is greater than 1, the time will progress faster than the wall clock time.
Fields
start_time::T
: The system time when the clock was created or last resetpaused::Bool
: Whether the clock is currently pausedtotal_paused_time::T
: Cumulative time spent pausedpause_start_time::Union{T, Nothing}
: System time when current pause started (if any)stretch_factor::F
: The factor by which to stretch the time
Stretch Factor
The MachineClock
has a stretch factor, which is a factor by which the time is stretched. This is useful for building real-time applications, where the time is stretched to make the simulation run faster or slower than the real time. The stretch factor is set to 1.0 by default. If the stretch factor is greater than 1.0, the time will progress faster than the real time. For example, if the stretch factor is 2.0, the time will progress twice as fast as real time. You can set the stretch factor when creating the clock:
using Gears
clock = MachineClock(stretch_factor = 2.0)
resume!(clock)
sleep(1.0)
pause!(clock)
println(now(clock)) # Current system time, 2.0 seconds
2.006309986114502 s
This is especially useful for debugging, and when you want to test if your agent has more/less computational resources available than on the machine you are running the simulation on.
Use MachineClock when:
- Building real-time applications
- You want to sync with wall clock time
- Running live simulations
VirtualClock - Controllable Time
VirtualClock
gives you complete control over time. In the VirtualClock
, you can advance time completely seperate from wall clock time:
clock = VirtualClock()
# Set initial time
set_time!(clock, 0.0s)
# Advance time manually
advance_time!(clock, 100ms)
println(now(clock)) # 0.1 s
advance_time!(clock, 50ms)
println(now(clock)) # 0.15 s
0.1 s
0.15000000000000002 s
Use VirtualClock when:
- Building deterministic simulations
- You need reproducible results
- Debugging timing issues
- Testing with specific time scenarios
Time Units
Gears uses Julia's Unitful.jl
for time units:
# All of these are equivalent
every(100ms) do dt; end
every(0.1s) do dt; end
every(100e-3s) do dt; end
Common time units:
ms
- millisecondss
- seconds
Integration with for_next()
In the previous tutorials, we used for_next(duration)
to advance time. However, when we are using a custom clock, we have fine-grained control over time advancement. This is reflected with the for_next(clock, duration)
function.
clock = VirtualClock()
for_next(clock, 100ms) do
# Do your updates here
advance_time!(clock, 10ms)
end
or:
clock = MachineClock()
for_next(clock, 100ms) do
# Do your updates here
end
For MachineClock
, for_next
will automatically resume the clock and pause it after the duration has passed. By using a custom clock, you get control over the time advancement in your simulations.
Next Steps
Now that you understand clocks and time control, explore:
- Schedulers - Configure job execution behavior
- Job Types - Different ways to trigger jobs