Vanilagy / mp4-muxer

MP4 multiplexer in pure TypeScript with support for WebCodecs API, video & audio.
https://vanilagy.github.io/mp4-muxer/demo
MIT License
419 stars 32 forks source link

Using private methods has some performance impact #72

Open alxvasilev opened 1 week ago

alxvasilev commented 1 week ago

Looking at the provided bundles, I discovered that some of the frequently executed code is full of calls to private property access check helpers, which are generated by esbuild. I tried to have these removed, and the properties/methods treated as usual, assuming names starting with # are backward compatible. I tried with esbuild and with webpack + typescript, but couldn't achieve that without bumping the target ES version to >= 2022 (I have zero experience with esbuild, though). Having the target as ES2022 or ESNEXT solved this problem, but leaves other "too-modern" features as well, such as optional chanining, which is unacceptable in my case. I noticed that the webpack-built bundle with the checks has a noticeable increase in CPU usage, while your pre-built bundle seems to be just a tad slower, almost within the measurement error. The test I did was encoding a 720p video stream of 16-30fps and audio chunks sent to the muxer every 20ms, which makes about 60-70 calls to addAudio/VideoChunk per second. Overall, you may want to have a look at these accessor calls, as they really look like unnecessary overhead and I'm not sure if they are worth any performance penalty.

Vanilagy commented 1 week ago

Oh wait, really? I mean I always thought these private property accessors read a bit weird, but at least they minify well. It's definitely more expensive than the untransformed version, but is the impact really so great? Do you have any concrete measurements? I would assume that the actual time spent in the muxer code is very little compared to, yknow, the amount of work it takes to encode a video. Of course if there's an actual performance hit, that's something I need to address because I care about performance.

alxvasilev commented 2 days ago

It's very tricky to do exact measurements, but here is my attempt. What I did is measured the average and minimum CPU load of the Chrome process that runs my web application (in Chrome's task manager), while it is recording audio only. The reason it's audio-only is to eliminate the significant measurement noise of CPU-heavy video encoding, while leaving the majority of muxer calls, as audio packets are generated at approx twice the rate of video packets (50 per second). Just for comparison, I created a third case, where I also removed all validations of input parameters in addAudioChunk() and addAudioChunkRaw():

The results are:

original npm package:    avg 73%, min 68%
no privacy checks:       avg 65%, min 60%
no priv & no validate:   avg 63%  min 58%

As you can see, removing the privacy checks resulted in ~8% less CPU load. The various input param validations have a much smaller overhead of ~2%