ultralight-ux / Ultralight

Lightweight, high-performance HTML renderer for game and app developers.
https://ultralig.ht
4.69k stars 197 forks source link

ultralight::FileSystem class inefficiency #450

Open p0358 opened 2 years ago

p0358 commented 2 years ago

The FileSystem class only has

ul::RefPtr<ul::Buffer> UltralightFilesystem::OpenFile(const ul::String& file_path)

method, which expects the whole file to be read into a memory buffer at once, which is highly inefficient. If we look at AppCore, it becomes pretty apparent why it was designed this way:

https://github.com/ultralight-ux/AppCore/blob/e461eb11210b96ac954731978c46cc9df2313779/src/win/FileSystemWin.cpp#L146-L162

Basically a memory mapping of the file is being created, letting the OS handle caching/paging of this, and it's read out on demand. However one cannot expect filesystem classes of things like game engines to support things like this. On top of that, for playing things like videos, WebKit still seems to try making multiple requests (probably as normal HTTP video is loaded with multiparts), causing the whole file to be read out into memory over and over again, causing obvious inefficiency if the video is say 250 MB in size (simple game tutorial).

The FileSystem library should be modified in some way to optionally allow Ultralight, and by extension WebCore, to read out just a fragment of the file, or at the very least not keep requesting the whole huge video file everytime over again.

I think optionally supporting providing Open/Read/Close functions with some "file handle" (custom user pointer) would do, which Ultralight could attempt to use if they're provided, or fall back to the old function otherwise. Or at the very least have some "length" and "offset" parameters to OpenFile that would prevent reading the whole file if WebKit doesn't need it...

p0358 commented 2 years ago

It's basically impossible to play 250 MB video at all due to this, it keeps re-reading the whole file for every fragment, it takes ~60 seconds of unresponsive UI to even start playing the video, and then after first maybe 0.5 second of video was played, the render thread froze completely...

joskuijpers commented 2 months ago

The FMOD api might be an interesting inspiration.

on Open you return the file size as well, and Read() calls specify offset and size.

they also have an async api