Add a Best Practices section to the website. NFC - #27334
Conversation
7d2220d to
7052085
Compare
f9da982 to
407b7ab
Compare
dschuff
left a comment
There was a problem hiding this comment.
oops, I forgot to hit send yesterday.
sbc100
left a comment
There was a problem hiding this comment.
Feedback addressed
| files before linking rather than combining everything into a single monolithic | ||
| compiler invocation. | ||
| - **Don't rely on raw ``extern "C"`` pointer manipulation** when interacting | ||
| with complex C++ objects across the JavaScript boundary; prefer Embind. |
There was a problem hiding this comment.
This point feels out of place in this list. It is at minimum debatable, I'd say? Raw pointer manipulation is very simple and efficient once you know it.
Generally speaking, I don't think we should recommend embind so generally, given the overhead. It is better that people make the effort to be efficient where it matters, and use embind where speed isn't an issue, but hard to put that into a short bullet point...
There was a problem hiding this comment.
Maybe "perfer embind, unless you really know what you doing" although I'm not sure how to say that exactly either.
There was a problem hiding this comment.
I think it's best to leave it out. There isn't a simple-enough best practice to recommend.
There was a problem hiding this comment.
I think what I'm trying to do here is have newcomers avoid trying do direct pointer manipulation, and present embind as the well-lit path to getting nice integration between native and JS code.
There was a problem hiding this comment.
My worry is that people start using embind even for simple things that don't need it, and then later ask "wait why is everything so slow?"
I guess I disagree about embind being the well-lit path. Or maybe it is well-lit but has pitfalls 😄
There was a problem hiding this comment.
Could it make sense to have a recommendation based on the type of API being exported to JS? e.g. use Embind if you have a C++ API or you want to do X and Y with your interop, or use something else if it's a C API?
There was a problem hiding this comment.
Perhaps we could phrase it as a warning against direct pointer manipulation unless you have a good reason (and good skills) to go that route.
I'm also thinking if recommending using pointer + subarray when passing data around rather than using a lot of calls. e.g. prefer getBytesFromWasm(ptr) over a sequence of getSingleValueFromWasm()
There was a problem hiding this comment.
I rephrased this point and using Avoid .. ; prefer .. rather than being overly prescriptive.
a282780 to
b759f99
Compare
| - **Use simple comma-separated lists** for list-based settings (for example, | ||
| ``-sEXPORTED_FUNCTIONS=_main,_malloc`` rather than JSON arrays like | ||
| ``-sEXPORTED_FUNCTIONS=['_main','_malloc']``). | ||
| - **Avoid long lists on the command line**; Use the ``@filename`` instead (for |
There was a problem hiding this comment.
| - **Avoid long lists on the command line**; Use the ``@filename`` instead (for | |
| - **Avoid long lists on the command line**; use a response file instead, with ``@filename`` (for |
| compiler invocation. | ||
| - **Avoid direct usage of C/C++ functions from JavaScript**; prefer higher-level | ||
| interfaces such as :js:func:`cwrap` and/or :ref:`embind` that support more | ||
| than purely numeric types. |
There was a problem hiding this comment.
I still disagree with this. Direct usage is simply faster, and often works well. How about
- Call directly between C/C++ and JavaScript where possible. When only passing around numeric types this is the most efficient thing to do.
- For more complex things, like passing a
std::vectorbetween the languages, use embind.
| - **Don't include the "=1" suffix for boolean flags.** For example, write | ||
| ``-sSTRICT`` and ``-sALLOW_MEMORY_GROWTH`` rather than ``-sSTRICT=1`` or | ||
| ``-sALLOW_MEMORY_GROWTH=1``. | ||
| - **Use separate compilation** by compiling ``.cpp`` sources to ``.o`` object |
There was a problem hiding this comment.
I would put all the things before this in a "lint" section. Separate compilation and C++/JS interop feel like substantially different things, choices about the build system and design.
| payload size is the priority. | ||
| - ``-flto``: Enable Link-Time Optimization (LTO) during both the compilation and | ||
| linking steps of release builds for maximum runtime performance and size | ||
| reduction. |
There was a problem hiding this comment.
Should we recommend Closure here?
| - ``-flto``: Enable Link-Time Optimization (LTO) during both the compilation and | ||
| linking steps of release builds for maximum runtime performance and size | ||
| reduction. | ||
|
|
There was a problem hiding this comment.
This section overlaps with our Optimizing Code page. Perhaps link to there? Or perhaps have a section here for optimizations that summarizes that page?
In particular, while most of this list is optimizations, things like STRICT feel more like "lint" (group with "avoid -sWASM=1, and EXPORT_ES6 feels more like "design choices" (group with "separate the compile&link stages)
| -------------------------------- | ||
|
|
||
| When exposing C++ functionality to JavaScript, prefer :ref:`embind` (``--bind``) | ||
| over raw ``extern "C"`` functions. Embind naturally handles C++ classes, |
There was a problem hiding this comment.
This overlaps with the above text, and I have the same response.
| on Emscripten's virtual in-memory filesystem (``MEMFS`` by default). See the | ||
| :ref:`file-system-overview` for an architectural overview. | ||
|
|
||
| - Do not assume direct access to the host file system. |
There was a problem hiding this comment.
This isn't a "best practice" so much as a "how to" - ?
| - For small temporary files, ``MEMFS`` is sufficient. | ||
| - For persistent client-side data storage across browser sessions, use | ||
| asynchronous storage backends such as :ref:`filesystem-api-idbfs` or the | ||
| :ref:`Filesystem-API`. |
There was a problem hiding this comment.
Perhaps just link to the main filesystem page for filesystem recommendations? This could also summarize that page, if we want that (if so, perhaps mention WasmFS).
I've been working on this as part of the https://developer.chrome.com/docs/modern-web-guidance project and it seems like whatever we do there it makes sense to maintain best practices guide directly in emscripten.