Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[POC] [WIP] Remove MediaSourceContentInitializer, add CoreInterface #1627

Open
wants to merge 4 commits into
base: dev
Choose a base branch
from

Conversation

peaBerberian
Copy link
Collaborator

@peaBerberian peaBerberian commented Jan 13, 2025

Based on #1630 as performance regression is the main risk here

This is a proof-of-concept where I try to put in common the "content initialization" logic for our "multithread" mode and our monothreaded mode.

The idea is to replace that mode-specific code to a very thin layer (here called CoreInterface) between our "init" code (always running in main thread) and our "core" code (in a WebWorker in "multithread" mode) which would handle both modes:

  • in multithreaded mode, it would be the part doing postmessage calls and onmessage registering for thread communication

  • in monothreaded mode, it would just do the same thing through a very simple EventEmitter-like approach

Or written another way: "multithread" and single-threaded mode would now share the same logic beside the communication system used at the frontier between the main-thread and potential worker.

The end goal is to remove a lot of code, and to reduce the difference between the multithreaded and monothreaded logic, so our tests (integration, manual tests etc.) actually almost test the two in one go.

There might be some performance lost due to steps we are now performing unnecessarily when in monothreaded mode (e.g. we serialize the Manifest structure even though it's not needed when a single thread is used, we create another PlaybackObserver on the core even though the main thread one could be re-used etc.). To see if that lead to a visible difference and if it does, it shouldn't be that hard to work-around.

@peaBerberian peaBerberian added work-in-progress This Pull Request or issue is not finished yet poc Proof Of Concept - This is just an attempt to ponder on labels Jan 13, 2025
@peaBerberian peaBerberian force-pushed the poc/common-init branch 5 times, most recently from 7569943 to 47b4bf7 Compare January 13, 2025 18:22
@peaBerberian peaBerberian force-pushed the poc/common-init branch 3 times, most recently from a203984 to d97c89e Compare January 13, 2025 18:55
@peaBerberian peaBerberian added the skip-performance-checks Performance tests are not run on this PR label Jan 13, 2025
@peaBerberian peaBerberian added skip-performance-checks Performance tests are not run on this PR and removed skip-performance-checks Performance tests are not run on this PR labels Jan 13, 2025
@peaBerberian peaBerberian force-pushed the poc/common-init branch 3 times, most recently from c632c93 to 33ce62e Compare January 22, 2025 09:40
@canalplus canalplus deleted a comment from github-actions bot Jan 22, 2025
@canalplus canalplus deleted a comment from github-actions bot Jan 22, 2025
@peaBerberian peaBerberian removed skip-performance-checks Performance tests are not run on this PR work-in-progress This Pull Request or issue is not finished yet poc Proof Of Concept - This is just an attempt to ponder on labels Jan 22, 2025
@peaBerberian peaBerberian force-pushed the poc/common-init branch 3 times, most recently from b0b30e6 to f480912 Compare February 3, 2025 16:03
This is a proof-of-concept where I try to put in common the "content
initialization" logic for our "multithread" mode and our monothreaded
mode.

The idea is to replace that mode-specific code to a very thin layer
(here called `CoreInterface`) between our "init" code (always running in
main thread) and our "core" code (in a WebWorker in "multithread" mode)
which would handle both modes:

  - in multithreaded mode, it would be the part doing `postmessage` calls
    and `onmessage` registering for thread communication

  - in monothreaded mode, it would just do the same thing through a very
    simple EventEmitter-like approach

Or written another way: "multithread" and single-threaded mode would now
share the same logic beside the communication system used at the frontier
between the main-thread and potential worker (respectively
`src/main_thread` code and `src/core` code).

The end goal is to remove a lot of code, and to reduce the difference
between the multithreaded and monothreaded logic, so our tests
(integration, manual tests etc.) actually almost test the two in one go.

There might be some performance lost due to steps we are now performing
unnecessarily when in monothreaded mode (e.g. we serialize the Manifest
structure even though it's not needed when a single thread is used, we
create another PlaybackObserver on the core even though the main thread
one could be re-used etc.). To see if that lead to a visible difference
and if it does, it shouldn't be that hard to work-around.
Copy link

github-actions bot commented Feb 3, 2025

Automated performance checks have been performed on commit aa614e4f3029dcc1ed6eda420b88f044190c0b47 with the base branch dev.

Tests results

✅ Tests have passed.

Performance tests 1st run output

No significative change in performance for tests:

Name Mean Median
loading 20.84ms -> 21.57ms (-0.727ms, z: 3.83166) 28.65ms -> 28.65ms
seeking 12.01ms -> 16.80ms (-4.786ms, z: 2.80468) 11.40ms -> 11.40ms
audio-track-reload 26.12ms -> 26.70ms (-0.574ms, z: 8.98213) 38.25ms -> 39.15ms
cold loading multithread 48.49ms -> 48.21ms (0.278ms, z: 8.48755) 70.95ms -> 69.90ms
seeking multithread 10.70ms -> 18.08ms (-7.382ms, z: 0.60560) 10.50ms -> 10.50ms
audio-track-reload multithread 26.44ms -> 26.06ms (0.374ms, z: 4.52291) 38.70ms -> 38.25ms
hot loading multithread 15.60ms -> 15.48ms (0.123ms, z: 3.88274) 22.50ms -> 22.35ms

If you want to skip performance checks for latter commits, add the skip-performance-checks label to this Pull Request.

@canalplus canalplus deleted a comment from github-actions bot Feb 4, 2025
@canalplus canalplus deleted a comment from github-actions bot Feb 4, 2025
@canalplus canalplus deleted a comment from github-actions bot Feb 4, 2025
@peaBerberian peaBerberian added low-latency Relative to low-latency (live playback close to the live edge) Priority: 3 (Low) This issue or PR has a low priority. labels Feb 26, 2025
peaBerberian added a commit that referenced this pull request Feb 27, 2025
I propose here to make our `MULTI_THREAD` feature, one the main feature
brought in our `v4.0.0`, a stable (i.e. not `experimental` anymore) one.

At Canal+ Group, it has been the main way to rely on the RxPlayer for
more than a year (with gains in terms of adaptive stability and
performances), and with #1627, we're in the process of making the
multi-thread code path the main one that will be relied on (with an
adaptation to support the default monothread one).

Removing the `experimental` label would encourage applications to rely
on this feature more, which would bring both its advantages to them and
align them more with what we're used to internally at Canal+.

We've never changed its API but still kept its "experimental" label
mainly to let us update its API, especially for the following issues:

1. For now it only supports DASH streaming, which is directily included
   with the worker code.

   The issue with supporting more streaming protocols is that we don't
   want to include those other rarely-used ones in every applications
   using the feature, and that we're still unsure how a feature
   switching concept could be relied on together with `MULTI_THREAD`
   (as the feature code to inject should be sometimes injected to the
   worker which runs in another thread - adding communication issues).

2. For a long time, I was not sure if we should directly include the
   "embedded worker" file in the `MULTI_THREAD` feature (as 95% of
   applications should want that) or if we let this as a supplementary
   step to let the application do more advanced things if it wants
   (worker transpiled to ES5, stored on a CDN somewhere and loaded
   lazily etc.).

   For now I chose the more flexible one as I think that this
   supplementary step is not a huge added complexity to its API.

3. It has some limitations (DASH-only, no `manifestLoader` or
   `segmentLoader`, [platform compatible to
   WebWorkers](https://caniuse.com/?search=webworker)), which is why we
   often advised people to rely on both `MULTI_THREAD` and on the
   main-thread `DASH` feature as a security fallback if those
   limitations aren't respected.

   This means more complexity in how the player may run and much more
   code being loaded (for what is most times unnecessarily
   duplicated code).

Keeping the API experimental would let us maybe find a way to fix or reduce
those issues at some point, but I think the gain of making it stable
(encouraging more people to use it and to report issues/needs on this)
make it up for the issues of doing it (less freedom to update its API).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
low-latency Relative to low-latency (live playback close to the live edge) Priority: 3 (Low) This issue or PR has a low priority.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant