Skip to content

Rebase browser port onto upstream, restore threaded build (#38) - #41

Open
thomasballinger wants to merge 1 commit into
endless-webfrom
threads
Open

Rebase browser port onto upstream, restore threaded build (#38)#41
thomasballinger wants to merge 1 commit into
endless-webfrom
threads

Conversation

@thomasballinger

Copy link
Copy Markdown
Owner

Rebases the browser port onto current upstream master and restores the threaded
build (#38). Six commits on top of master, which now tracks upstream
44375632f (v0.11.2 + 142 commits).

The claim to check: C++ changes for threading are now zero

source/TaskQueue.cpp and source/audio/Audio.cpp are byte-identical to
upstream. The whole threading change is build configuration:

  • Makefile: -pthread in COMMON_FLAGS, -s PTHREAD_POOL_SIZE=10
  • endless-sky.html: pass --tq-threads N to callMain

That last one uses a CLI flag upstream already has (main.cpp ->
TaskQueue::SetWorkerThreadCount), so no C++ patch is needed to keep the
worker count within the preallocated pool. Overflowing the pool makes
Emscripten create threads on demand, which needs the main thread to reach the
event loop -- and it may be blocked in the game loop when that happens.

Previously this cost 55 lines (TaskQueue.cpp +43, Audio.cpp +12).

Remaining C++ diff: 115 lines in 7 files

file lines why
LoadPanel.cpp 26 FS.syncfs after snapshot/delete
Files.cpp 20 hardcode paths to /, stub ZipFile
PlayerInfo.cpp 20 FS.syncfs after save/autosave
main.cpp 16 mount IDBFS at /saves
ImageBuffer.cpp 16
audio/Music.cpp 13 no libmad/FLAC++ in the web build
GameWindow.cpp 5 skip resolution warning, printf to console

Roughly 60 of those 115 lines are hand-rolled IDBFS save syncing, which
Emscripten's IDBFS { autoPersist: true } (3.1.61) could replace outright.
Not attempted here.

Also included

  • Sound effects fixed (Game Sound not working in Chrome or Firefox #40). Upstream moved the sound scan into
    Audio::LoadSounds(); a previous rebase guarded the whole call rather than
    just the thread spawn, so no sound was ever queued.
  • Asset hashing fix. endless-sky.js was hashed before its .wasm
    reference was rewritten into it, so two builds differing only in C++ shared a
    filename of identical length, and aws s3 sync --size-only skipped the
    upload. This silently shipped stale wasm.
  • Makefile is now a prerequisite of the link, so changing LINK_FLAGS
    actually relinks.
  • Style fixes so upstream's Check workflow passes.

Not ready to merge

Safari reloads the threaded build ("this page was reloaded because it used
significant memory"), at both 2GB and 1GB caps. Chrome is fine and loads
noticeably faster.

pthreads force the heap to be a SharedArrayBuffer, which cannot be relocated
on growth, so a maximum must be declared up front and engines reserve it.
Safari appears to commit rather than lazily map. The single-threaded build
declares no maximum in JS and grows lazily -- same INITIAL_MEMORY, very
different real footprint.

Measured peak (headless, --parse-assets): 637 MB, of which ~383 MB is
the preloaded asset bundle
resident in MEMFS for the whole session. Shrinking
that looks more promising than tuning flags, and would help the
single-threaded build too.

Emscripten supports pthreads, and Endless Sky's TaskQueue drives both sprite
loading and the Engine's per-frame calculation step, so running single-threaded
costs both startup time and frame pacing under load. Turning threads on removes
every Emscripten-specific workaround from TaskQueue.cpp and Audio.cpp -- their
diff against upstream drops to zero.

- Makefile: -pthread in COMMON_FLAGS, -s PTHREAD_POOL_SIZE=10
- endless-sky.html: pass --tq-threads N to callMain, using a flag upstream
  already has (main.cpp -> TaskQueue::SetWorkerThreadCount). Upstream sizes its
  pool from hardware_concurrency(), which in a browser can exceed
  PTHREAD_POOL_SIZE; overflowing it makes Emscripten create threads on demand,
  which needs the main thread to reach the event loop -- and it may be blocked
  in the game loop when that happens.
- source/TaskQueue.cpp, source/audio/Audio.cpp: revert to upstream.

Requires COOP/COEP headers for SharedArrayBuffer; the deploy already sets them.

NOT MERGED: Safari reloads the page ("this page was reloaded because it used
significant memory") on both emscripten 5.0.1 and 6.0.6, at 2GB, 1GB and even
512MB/1GB caps. pthreads force the heap to be a SharedArrayBuffer, which cannot
be relocated on growth, so a maximum must be declared up front and Safari
appears to commit it rather than lazily map it. Measured peak usage is only
~531-637MB, of which ~383MB is the preloaded asset bundle resident in MEMFS for
the whole session -- so shrinking that is the most promising route to making
this shippable. Chrome and Firefox are fine and load noticeably faster.
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.

1 participant