Skip to content

Restore some decode throughput lost since April - #1058

Open
JustinTArthur wants to merge 1 commit into
happycube:mainfrom
JustinTArthur:restore-decode-throughput
Open

Restore some decode throughput lost since April#1058
JustinTArthur wants to merge 1 commit into
happycube:mainfrom
JustinTArthur:restore-decode-throughput

Conversation

@JustinTArthur

@JustinTArthur JustinTArthur commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Checklist

  • I have searched the open pull requests to confirm this change has not already been submitted.
  • My branch is up to date with the target branch.
  • I have tested my changes and all existing tests pass.
  • I have updated documentation where necessary.
  • My code follows the project's coding standards (see CONTRIBUTING.md).

Description

Four independent decoder/demodulator performance regressions roughly halved throughput (including downstream in vhs-decode) and this tries to bring a little performance back.

  1. LoadFFmpeg/LoadLDF rewind buffer (biggest one). Appending to and trimming the rewind buffer copies the bytes twice each read. 8a42fec raised LoadFFmpeg's window from 2MB to 16MB, which turned ~4MB of memcpy per 61KB read into ~32MB. Demodulator threads starve waiting on the big copy.

  2. scale_field lost @njit(cache=True). Was dropped in 163408c, I'm guessing an artifact of runtime kernel overrides while testing the change.

  3. Sinc LUT's inter-phase interpolation doesn't change anything. sinc_phase_count is 2**16, so the nearest tabulated phase is already accurate below float32 precision. Interpolating between the phases is costly when this math is encountered frequently.

  4. Wasteful np.concatenate on block record arrays. nb_concatenate was dropped in 980f3a2 and cf2e13e but the replacement had an expensive deep traversal of block structure.

Motivation

When vhs-decode 0.4.0 launched with these regressions, users brought up the slow performance in the Domesday86 Discord.

Changes Made

  1. Fixed with a bytearray and compaction only once the window has grown to twice its target size. The combination of those two is was better than just either one.
  2. Added the cache=True back. @eshaz: let me know if you'd wanted to make tap counts or something else runtime-alterable.
  3. Dropped the linear interpolation to just publish the nearest phase. Depends on the LUT staying this large.
  4. Custom concatenation function. @happycube I asked an AI to determine why the numba flow had to be dropped, and it hinted you might have run into can't unbox heterogeneous list; this should be faster than the numba kernel anyway.

Testing

  • All existing tests pass (pytest --output-on-failure)
  • Tested manually with a barrage of LaserDisc (and VHS w/ patched vhs-decode) sources in both NTSC and PAL. TBC output was identical.

Four independent decoder/demodulator performance regressions
roughly halved throughput (including downstream in vhs-decode)

1. LoadFFmpeg/LoadLDF rewind buffer (the bigger one)
   Appending to and trimming the rewind buffer copies the bytes twice each
   read. 8a42fec raised LoadFFmpeg's window from 2MB to 16MB, which
   turned ~4MB of memcpy per 61KB read into ~32MB. Demodulator threads
   starve waiting on the big copy.

   Fixed with a bytearray and compaction only once the window has grown
   to twice its target size.

2. scale_field lost @njit(cache=True)
   Was dropped in 163408c, I'm guessing an artifact of runtime kernel
   overrides while testing the change.

3. Sinc LUT's inter-phase interpolation doesn't change anything
   sinc_phase_count is 2**16, so the nearest tabulated phase is already
   accurate below float32 precision. Interpolating between the phases was
   costly.

4. Wasteful np.concatenate on block record arrays
   nb_concatenate was dropped in 980f3a2 and cf2e13e but the
   replacement had an expensive deep traversal of block structure.
@JustinTArthur
JustinTArthur force-pushed the restore-decode-throughput branch from 432d5c5 to 32132b3 Compare July 31, 2026 22:31
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