whatwg / fs

File System Standard
https://fs.spec.whatwg.org/
Other
237 stars 20 forks source link

Possibility of sync version of `createSyncAccessHandle()` #100

Closed tomayac closed 9 months ago

tomayac commented 1 year ago

The current createSyncAccessHandle() method is asynchronous. Since we don’t universally have JSPI on all platforms/browsers yet, obtaining a FileSystemSyncAccessHandle can be unergonomic from a Wasm context. We hear developer demand for a synchronous version of createSyncAccessHandle() (obviously tied to Worker contexts). Is this feasible?

a-sully commented 1 year ago

This was discussed quite a bit on #7 (the issue to make all the methods on the SyncAccessHandle sync). We came to the following conclusion (from https://github.com/whatwg/fs/issues/7#issuecomment-1226562961):

To summarize, it seems like there's a very strong argument for making all the methods of the SyncAccessHandle sync, but the argument for making createSyncAccessHandle sync is less clear-cut, especially considering that applications typically have to deal with async methods when opening a file anyways. To me, the slight performance improvement is not worth the greater risk of site breakage and the sacrifice of future flexibility. At this point, I plan to move forward with my initial proposal (https://github.com/whatwg/fs/issues/7#issuecomment-1162501488) of making only the methods of the SyncAccessHandle sync (as soon as https://github.com/whatwg/fs/pull/21 lands). If anyone else can provide a strong case to make createSyncAccessHandle sync and would like to drive that work, then of course they are welcome to :)

tomayac commented 1 year ago

Right. I have created this new Issue because…

If anyone else can provide a strong case to make createSyncAccessHandle sync and would like to drive that work, then of course they are welcome to

…we may have found this “anyone”. I hope for them to chime in on the Issue.

d3lm commented 1 year ago

Hello 👋 I am the Team Lead at StackBlitz for WebContainer, a Node.js runtime for the browser. For our runtime we would highly benefit from createSyncAccessHandle being synchronous because our idea is to use the OPFS as another layer in our kernel to allow swapping files out of memory onto disk which can drastically reduce the memory footprint for large applications. Our kernel is compiled to Wasm and a lot of APIs are expected to be synchronous. As Thomas said, without universal support for JSPI that allows to suspend the execution of the Wasm module when calling a function that returns a Promise, the only way we could open files from our kernel is to use a separate thread that performs this operation but that also means we'd have to write to that file on a separate thread (worker) IIUC (similar to how WORKERFS works for emscripten). In an ideal world, we could synchronously open files directly from our kernel, and start swapping the content.

Does that make sense?

a-sully commented 1 year ago

Hi @d3lm, thanks for contributing your use case! Just to make sure I understand correctly - you still would need to call the async getFileHandle() method (and maybe also getDirectoryHandle()) to get the FileSystemFileHandle on which you would then call createSyncAccessHandle(), correct?

On that earlier spec issue it was concluded that making createSyncAccessHandle() sync would not provide much benefit, in part because the async directory traversal methods that we never intend to make sync (i.e. getFileHandle() and getDirectoryHandle()) were assumed to be a prerequisite to open the file anyways. If you need to call these async methods anyways, then a sync createSyncAccessHandle() doesn't really help you much. This is the case for Emscripten, for example, which is general-purpose and performs this directory traversal on-demand.

The most convincing use case (courtesy of https://github.com/rhashimoto/wa-sqlite/discussions/67) I've seen so far for createSyncAccessHandle() to be sync is if there's a known set of files you plan to interact with. In this case, you could (asynchronously) get all the FileSystemFileHandles you need up front, then read/write/etc all synchronously... at which point an async "open" method is a real hindrance

d3lm commented 9 months ago

@a-sully Yes, that is absolutely right. I'd still need to call getDirectoryHandle or getFileHandle. And if there won't be sync variants of those then yea it doesn't make much sense to make createSyncAccessHandle synchronous. I think for our use case we'd need basically the entire chain of API calls to be synchronous so we could use OPFS as a backing store for our file system.

a-sully commented 9 months ago

I think for our use case we'd need basically the entire chain of API calls to be synchronous

Yup, this is what I had suspected :)

JSPI is currently in Dev Trial and is going into Origin Trial in M123 in Chrome. I would recommend checking it out!