# Building a faster Playdate timer

🌳 _Evergreen_

_Planted_
_2 years ago_ _Planted 11/17/2024 9:53 pm_

While doing some early profiling of [Suborbital Salvage](/content/games/suborbital-salvage/index.html), I noticed that [native Playdate timers](https://sdk.play.date/2.6.1/Inside%20Playdate.html#C-timer) were eating up a non-trivial amount of time.

Since Suborbital used timers for a lot of timing-related animations and behaviors, I started at looking for a faster replacement. In the end I added [a timer class](https://github.com/GamesRightMeow/playbit/blob/main/playbit/timer.lua) to [Playbit](https://github.com/GamesRightMeow/playbit) which [leverages data-locality](https://gameprogrammingpatterns.com/data-locality.html) to speed up iterations over timers.

It lacks some features that the native Playdate timer has (auto reverse, delay, onComplete callback) but if you're just using it for basic timer this will free up some cycles.

# Comparison

For both `new()` and `update()` comparisons, the benchmark script creates 100 timers and then updates them all 100 times. These were collected from SDK 2.6.0 on a REV B Playdate.

```
playbit.timer.new=31ms
playdate.timer.new=68ms
playbit.timer.update=178ms
playdate.timer.updateTimers=543ms
```

For creation, the Playbit timer is ~55% **faster** than the native timer.

For updates, the Playbit timer is ~67% **faster** than the native timer.

# Benchmarks script

```lua
local startTime = playdate.getCurrentTimeMilliseconds()
for i = 1, 100 do
  playbit.timer.new(1500)
end
local endTime = playdate.getCurrentTimeMilliseconds()
print("playbit.timer.new="..(endTime - startTime).."ms")

local startTime = playdate.getCurrentTimeMilliseconds()
for i = 1, 100 do
  playdate.timer.new(1500)
end
local endTime = playdate.getCurrentTimeMilliseconds()
print("playdate.timer.new="..(endTime - startTime).."ms")

local startTime = playdate.getCurrentTimeMilliseconds()
for i = 1, 100 do
  playbit.timer.update(0.33)
end
local endTime = playdate.getCurrentTimeMilliseconds()
print("playbit.timer.update="..(endTime - startTime).."ms")

local startTime = playdate.getCurrentTimeMilliseconds()
for i = 1, 100 do
  playdate.timer.updateTimers()
end
local endTime = playdate.getCurrentTimeMilliseconds()
print("playdate.timer.updateTimers="..(endTime - startTime).."ms")
```
