Skip to content
Geode benchmarks

Run 74d6b2a5

Date
Build
0.6.1Same load, save, release and hop code as 0.6.0. 0.6.1 only adds checks on op names and descriptions.
Used in the results page
Yes
Geode source
1c0a3221774d8f93266705d413deee65c2cb0384

Load, save and release

Live Roblox servers

Each run loads five fresh profiles, saves each, releases each after a change, loads them again and releases them again, with the steps on one key at least 8 seconds apart. Times are seconds from calling the library until its DataStore request finished.

Load, new profile

TimeSeconds per sample. The median, lowest and highest, the samples and how many failed.

Median (the upright tick) and min to max of every sample (the bar). Medians less than one timing step (16.7 ms (1/60 s)) apart are ties.

Table: Time
Time
SubjectMedianMinMaxnFailedTie with
Geode249 ms216 ms266 ms50ProfileService
Geode, mailbox = true266 ms182 ms299 ms50ProfileStore
ProfileStore266 ms216 ms283 ms50Geode, mailbox = true
ProfileService249 ms183 ms283 ms50Geode
DataStore2, Standard saving66 ms65 ms82 ms50–
DataStore requestsRequests the library sent for the key during the step, retries included, as the bench's stand-in for DataStoreService counted them.

Requests per sample, by method. A range means the count varied between samples. 2 methods used.

DataStore requests
SubjectUpdateAsyncGetAsyncnCounts
Geode1–5Same in every sample
Geode, mailbox = true115Same in every sample
ProfileStore1–5Same in every sample
ProfileService1–5Same in every sample
DataStore2, Standard saving–15Same in every sample

Load, stored profile

TimeSeconds per sample. The median, lowest and highest, the samples and how many failed.

Median (the upright tick) and min to max of every sample (the bar). Medians less than one timing step (16.7 ms (1/60 s)) apart are ties.

Table: Time
Time
SubjectMedianMinMaxnFailedTie with
Geode199 ms166 ms216 ms50–
Geode, mailbox = true265 ms216 ms282 ms50ProfileService
ProfileStore233 ms233 ms266 ms50–
ProfileService251 ms199 ms283 ms50Geode, mailbox = true
DataStore2, Standard saving16 ms16 ms16 ms50–
DataStore requestsRequests the library sent for the key during the step, retries included, as the bench's stand-in for DataStoreService counted them.

Requests per sample, by method. A range means the count varied between samples. 2 methods used.

DataStore requests
SubjectUpdateAsyncGetAsyncnCounts
Geode1–5Same in every sample
Geode, mailbox = true115Same in every sample
ProfileStore1–5Same in every sample
ProfileService1–5Same in every sample
DataStore2, Standard saving–15Same in every sample

Save

TimeSeconds per sample. The median, lowest and highest, the samples and how many failed.

Median (the upright tick) and min to max of every sample (the bar). Medians less than one timing step (16.7 ms (1/60 s)) apart are ties.

Table: Time
Time
SubjectMedianMinMaxnFailedTie with
Geode182 ms165 ms216 ms50ProfileStore
Geode, mailbox = true200 ms166 ms233 ms50ProfileService
ProfileStore166 ms133 ms266 ms50Geode
ProfileService200 ms150 ms250 ms50Geode, mailbox = true
DataStore2, Standard saving282 ms199 ms316 ms50–
DataStore requestsRequests the library sent for the key during the step, retries included, as the bench's stand-in for DataStoreService counted them.

Requests per sample, by method. A range means the count varied between samples. 1 method used.

DataStore requests
SubjectUpdateAsyncnCounts
Geode15Same in every sample
Geode, mailbox = true15Same in every sample
ProfileStore15Same in every sample
ProfileService15Same in every sample
DataStore2, Standard saving15Same in every sample

Release

TimeSeconds per sample. The median, lowest and highest, the samples and how many failed.

Median (the upright tick) and min to max of every sample (the bar). Medians less than one timing step (16.7 ms (1/60 s)) apart are ties.

Table: Time
Time
SubjectMedianMinMaxnFailedTie with
Geode200 ms183 ms266 ms50ProfileStore
Geode, mailbox = true250 ms232 ms266 ms50–
ProfileStore199 ms183 ms250 ms50Geode
ProfileService218 ms198 ms233 ms50DataStore2, Standard saving
DataStore2, Standard saving233 ms232 ms266 ms50ProfileService
DataStore requestsRequests the library sent for the key during the step, retries included, as the bench's stand-in for DataStoreService counted them.

Requests per sample, by method. A range means the count varied between samples. 1 method used.

DataStore requests
SubjectUpdateAsyncnCounts
Geode15Same in every sample
Geode, mailbox = true15Same in every sample
ProfileStore15Same in every sample
ProfileService15Same in every sample
DataStore2, Standard saving15Same in every sample

Server hops

Live Roblox servers

Two Luau Execution tasks at once play the old and the new server. The old server loads a profile, saves 777, waits 8 seconds, then changes it to 888 (999 when it keeps the profile) without saving. Times are seconds from the new server's load call until it has the data.

Old server releases

The old server releases when the new one starts loading, the way a server releases when a player leaves for another one.

Saw the final saveHops in which the new server saw 888, the old server's last change.
Saw the final save
SubjectSaw the final save
Geode3 of 3
Geode, mailbox = true3 of 3
ProfileStore3 of 3
ProfileService3 of 3
DataStore2, Standard saving0 of 3
TimeSeconds per sample. The median, lowest and highest, the samples and how many failed.

Median (the upright tick) and min to max of every sample (the bar). Medians less than one timing step (16.7 ms (1/60 s)) apart are ties.

Table: Time
Time
SubjectMedianMinMaxnFailedTie with
Geode0.57 s0.48 s0.62 s30–
Geode, mailbox = true0.55 s0.50 s0.67 s30–
ProfileStore5.38 s0.63 s5.50 s30–
ProfileService7.23 s7.22 s7.25 s30–
DataStore2, Standard saving0.02 s0.02 s0.02 s30–
DataStore requestsRequests the library sent for the key during the step, retries included, as the bench's stand-in for DataStoreService counted them.

Requests per sample, by method. A range means the count varied between samples. 3 methods used.

DataStore requests
SubjectUpdateAsyncGetAsyncGetAsync past the cachenCounts
Geode2–13Same in every sample
Geode, mailbox = true2213Same in every sample
ProfileStore1 to 2––3Varied between samples
ProfileService2––3Same in every sample
DataStore2, Standard saving–1–3Same in every sample

Old server keeps it

The old server never releases on its own. 999 means the library got it to hand the profile over with its last change, 777 means the new server went ahead without it.

Value seenWhat the new server read, and how often.
Value seen
SubjectValue seen
Geode999 in 1 of 1
Geode, mailbox = true999 in 1 of 1
ProfileStore999 in 1 of 1
ProfileService999 in 1 of 1
DataStore2, Standard saving777 in 1 of 1
TimeSeconds per sample. The median, lowest and highest, the samples and how many failed.

Median (the upright tick) and min to max of every sample (the bar). Medians less than one timing step (16.7 ms (1/60 s)) apart are ties.

Table: Time
Time
SubjectMedianMinMaxnFailedTie with
Geode0.65 s0.65 s0.65 s10–
Geode, mailbox = true0.63 s0.63 s0.63 s10–
ProfileStore5.47 s5.47 s5.47 s10–
ProfileService21.30 s21.30 s21.30 s10–
DataStore2, Standard saving0.02 s0.02 s0.02 s10–
DataStore requestsRequests the library sent for the key during the step, retries included, as the bench's stand-in for DataStoreService counted them.

Requests per sample, by method. A range means the count varied between samples. 3 methods used.

DataStore requests
SubjectUpdateAsyncGetAsyncGetAsync past the cachenCounts
Geode2–11Same in every sample
Geode, mailbox = true2211Same in every sample
ProfileStore2––1Same in every sample
ProfileService4––1Same in every sample
DataStore2, Standard saving–1–1Same in every sample

Throttling

Live Roblox servers

A burst of 160 or 161 UpdateAsync calls on throwaway keys uses up the server's request budget, then the library loads, saves and releases one profile back to back. One sample per run.

Load

TimeSeconds per sample. The median, lowest and highest, the samples and how many failed.

Shown as a range only: the shortest and longest sample, no median.

Table: Time
Time
SubjectMinMaxnFailed
Geode32.82 s32.82 s10
Geode, mailbox = true33.70 s33.70 s10
ProfileStore31.20 s31.20 s10
ProfileService31.22 s31.22 s10
DataStore2, Standard saving31.07 s31.07 s10
DataStore requestsRequests the library sent for the key during the step, retries included, as the bench's stand-in for DataStoreService counted them.

Requests per sample, by method. A range means the count varied between samples. 2 methods used.

DataStore requests
SubjectUpdateAsyncGetAsyncnCounts
Geode1–1Same in every sample
Geode, mailbox = true111Same in every sample
ProfileStore2–1Same in every sample
ProfileService1–1Same in every sample
DataStore2, Standard saving–611Same in every sample

Save

TimeSeconds per sample. The median, lowest and highest, the samples and how many failed.

Shown as a range only: the shortest and longest sample, no median.

Table: Time
Time
SubjectMinMaxnFailed
Geode1.13 s1.13 s10
Geode, mailbox = true1.23 s1.23 s10
ProfileStore0.18 s0.18 s10
ProfileService0.13 s0.13 s10
DataStore2, Standard saving1.08 s1.08 s10
DataStore requestsRequests the library sent for the key during the step, retries included, as the bench's stand-in for DataStoreService counted them.

Requests per sample, by method. A range means the count varied between samples. 1 method used.

DataStore requests
SubjectUpdateAsyncnCounts
Geode11Same in every sample
Geode, mailbox = true11Same in every sample
ProfileStore11Same in every sample
ProfileService11Same in every sample
DataStore2, Standard saving11Same in every sample

Release

TimeSeconds per sample. The median, lowest and highest, the samples and how many failed.

Shown as a range only: the shortest and longest sample, no median.

Table: Time
Time
SubjectMinMaxnFailed
Geode0.25 s0.25 s10
Geode, mailbox = true0.25 s0.25 s10
ProfileStore0.17 s0.17 s10
ProfileService7.05 s7.05 s10
DataStore2, Standard saving0.12 s0.12 s10
DataStore requestsRequests the library sent for the key during the step, retries included, as the bench's stand-in for DataStoreService counted them.

Requests per sample, by method. A range means the count varied between samples. 1 method used.

DataStore requests
SubjectUpdateAsyncnCounts
Geode11Same in every sample
Geode, mailbox = true11Same in every sample
ProfileStore11Same in every sample
ProfileService11Same in every sample
DataStore2, Standard saving11Same in every sample

Geode edit time

Lune, Geode only

Geode only, in Lune against Geode's test universe on the machine that runs the bench, not on a Roblox server. One loaded profile with the same data as the other suites takes batches of 1000 profile:increment("coins") calls, after one batch that isn't counted. Each edit runs through the profile's transaction pipeline and is recorded for the next save, without a DataStore request. One sample per batch.

Increment

Time per editMicroseconds per edit, from a batch's time divided by its edits.

Median (the upright tick) and min to max of every sample (the bar).

Table: Time per edit
Time per edit
SubjectMedianMinMaxn
Geode10.97 µs10.79 µs11.29 µs5

Libraries

LibraryVersionCommitLicence
ProfileStoreno releases, latest commit on main (2025-07-31)MadStudioRoblox/ProfileStore@45c9847Apache-2.0
ProfileServiceno releases, latest commit on master (2024-10-13)MadStudioRoblox/ProfileService@d736800Apache-2.0
Lapisv0.3.3nezuo/lapis@f140acaMIT
Promisev4.0.0, the version Lapis 0.3.3 asks forevaera/roblox-lua-promise@2c6f433MIT
DataStore2ds2-1.4.0Kampfkarren/Roblox@ab81664custom: copying and changing allowed, changes to a published game's copy must be shared

Couldn't run

Lapis, Load, save and release
RunService.PostSimulation didn't fire in this task, and Lapis sends its DataStore requests from that event
Lapis, Server hops
RunService.PostSimulation didn't fire in this task, and Lapis sends its DataStore requests from that event
Lapis, Throttling
RunService.PostSimulation didn't fire in this task, and Lapis sends its DataStore requests from that event