Skip to content

feat: replace concurrent scheduler with sequential scheduler#887

Merged
rmrt1n merged 3 commits into
mainfrom
ryan/sequential
Apr 20, 2026
Merged

feat: replace concurrent scheduler with sequential scheduler#887
rmrt1n merged 3 commits into
mainfrom
ryan/sequential

Conversation

@rmrt1n
Copy link
Copy Markdown
Contributor

@rmrt1n rmrt1n commented Apr 13, 2026

TL;DR

The PR title sums it up basically.

Rationale

Entity operations (create, destroy, etc.) aren't concurrent safe and require locks to synchronize. The concurrent scheduler brings better performance when systems touch different components, but when it comes to entity operations, all systems effectively become sequential. Tested on Rampage, a sequential scheduler cuts down tick execution time by roughly half just from the lack of lock contention.

Copy link
Copy Markdown
Contributor Author

rmrt1n commented Apr 13, 2026


How to use the Graphite Merge Queue

Add the label graphite/merge to this PR to add it to the merge queue.

You must have a Graphite account in order to use the merge queue. Sign up using this link.

An organization admin has enabled the Graphite Merge Queue in this repository.

Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue.

This stack of pull requests is managed by Graphite. Learn more about stacking.

@rmrt1n rmrt1n requested a review from winton-library April 13, 2026 10:32
Copy link
Copy Markdown
Contributor

@winton-library winton-library left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left some comments, I think it's only worth to take a look if the new architecture for cardinal is still a long way to go.

Comment thread pkg/cardinal/system.go Outdated
Comment thread pkg/cardinal/debug.go
_ context.Context,
_ *connect.Request[cardinalv1.GetStateRequest],
) (*connect.Response[cardinalv1.GetStateResponse], error) {
worldState, err := d.world.world.ToProto()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking about this ToProto function. I check the caller and it boils down to snapshot use and debug.

Since the snapshot path runs on the tick goroutine itself (after Tick() returns), there's no data-integrity issue there because nothing is mutating state while it serializes. But GetState runs on the HTTP handler goroutine with no lock. Doesn't that mean it can return an inconsistent state for the engineer's debugging session?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah ur right, I'm reworking snapshots, will take a look at this again in the future. added to backlog for now.

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 19, 2026

❌ 2 Tests Failed:

Tests completed Failed Passed Skipped
180 2 178 4
View the top 2 failed test(s) by shortest run time
::TestMain
Stack Traces | 0s run time
to reproduce: TEST_SEED=0x69e4b270
panic: test timed out after 10m0s
	running tests:
		TestArchetype_ModelFuzz (10m0s)

goroutine 44 [running]:
testing.(*M).startAlarm.func1()
	.../hostedtoolcache/go/1.25.5.../src/testing/testing.go:2682 +0x345
created by time.goFunc
	.../hostedtoolcache/go/1.25.5.../src/time/sleep.go:215 +0x2d

goroutine 1 [chan receive, 9 minutes]:
testing.tRunner.func1()
	.../hostedtoolcache/go/1.25.5.../src/testing/testing.go:1891 +0x451
testing.tRunner(0xc0000b2a80, 0xc0001adc70)
	.../hostedtoolcache/go/1.25.5.../src/testing/testing.go:1940 +0x123
testing.runTests(0xc0000122a0, {0xed04a0, 0x14, 0x14}, {0x7?, 0xc000049440?, 0xed9f20?})
	.../hostedtoolcache/go/1.25.5.../src/testing/testing.go:2475 +0x4b4
testing.(*M).Run(0xc0000ab0e0)
	.../hostedtoolcache/go/1.25.5.../src/testing/testing.go:2337 +0x63a
main.main()
	_testmain.go:93 +0x9b

goroutine 8 [runnable]:
math/rand/v2.(*Rand).uint64n(0xc00003f200, 0x1)
	.../hostedtoolcache/go/1.25.5.../rand/v2/rand.go:81 +0xc5
math/rand/v2.(*Rand).IntN(...)
	.../hostedtoolcache/go/1.25.5.../rand/v2/rand.go:195
github..../cardinal/internal/ecs.TestArchetype_ModelFuzz(0xc0000b2c40)
	.../internal/ecs/archetype_internal_test.go:86 +0x14b5
testing.tRunner(0xc0000b2c40, 0xa44f20)
	.../hostedtoolcache/go/1.25.5.../src/testing/testing.go:1934 +0xea
created by testing.(*T).Run in goroutine 1
	.../hostedtoolcache/go/1.25.5.../src/testing/testing.go:1997 +0x465
FAIL	github..../cardinal/internal/ecs	600.022s
github.com/argus-labs/world-engine/pkg/cardinal/internal/ecs::TestArchetype_ModelFuzz
Stack Traces | 0s run time
=== RUN   TestArchetype_ModelFuzz
=== PAUSE TestArchetype_ModelFuzz
=== CONT  TestArchetype_ModelFuzz

To view more test analytics, go to the Test Analytics Dashboard
📋 Got 3 mins? Take this short survey to help us improve Test Analytics.

@rmrt1n rmrt1n merged commit 8688719 into main Apr 20, 2026
8 checks passed
@rmrt1n rmrt1n deleted the ryan/sequential branch April 20, 2026 16:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants