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

emcc generates large amount of unused boilerplate JS code for small amount of C code #1838

Closed
JamesDunne opened this issue Nov 19, 2013 · 14 comments

Comments

@JamesDunne
Copy link

My emcc command-line is:

emcc c_files_here -o output.js -s TOTAL_STACK="192" -s TOTAL_MEMORY="2048" -s FAST_MEMORY="2048" -s EXPORTED_FUNCTIONS="[my functions here]"

This gives me a JS file size of 142KB. That's exceedingly large, in my opinion. My C code compiles to just 363 lines of JS code (about 7KB), whereas the remainder of the enormous generated JS code, 3247 lines, is almost all unused boilerplate code. My C code does not use any emscripten features at all. It is just portable logic and uses no dependencies or external libraries.

I toyed with -O2 but it only made my code broken because the functions I declared as extern to be defined in JS were complained about being missing:

function _externed_function() {
Module['printErr']('missing function: externed_function'); abort(-1);
}

That seems like a bug to me; extern functions should always be externally "linkable" regardless of optimization. Also, -O2 did not reduce any of the boilerplate code.

I added -s DEFAULT_LIBRARY_FUNCS_TO_INCLUDE="['memcpy','memset','malloc','free','strlen']" to my emcc commandline (i.e. removing the '$Browser' element from src/settings.js).

This significantly reduced the file size to just 53KB, a considerable improvement for sure, but even 53KB is still too large in my opinion. I really just want my portable and independent C code to be compiled to a minimal JS module with no bells or whistles.

Is there no other way to reduce the generated size by chopping out bits of boilerplate? Obviously I don't want to hack up emscripten itself because I want a clean upgrade path. I'd like to see more emphasis on reducing generated code size and even optimizing for it. Outlining is fine but it's not an issue in my code; the excessive amount of boilerplate is.

Also, is there a nice way to define JS-exported functions in my C code as opposed to supplying the EXPORTED_FUNCTIONS list on the emcc commandline? I pored over what little documentation there is but couldn't find anything like this.

I don't mean to sound whiny; this is a great project and I'm loving the results!

@kripken
Copy link
Member

kripken commented Nov 19, 2013

Hard to read, can you please fix the formatting of your comment? it looks like one huge wall of text atm ;)

@JamesDunne
Copy link
Author

Magically works now. Github freaked out for a moment there.

@kripken
Copy link
Member

kripken commented Nov 19, 2013

Try closure compiler to reduce code size in addition, -O2 --closure 1.

EMSCRIPTEN_KEEPALIVE can keep code alive without EXPORTED_FUNCTIONS (but it doesn't export - the code won't be accessible from the outside.

@JamesDunne
Copy link
Author

The -O2 switch automatically breaks my code and causes an abort() at runtime.

@JamesDunne
Copy link
Author

WARNING root: disabling closure because debug info was requested happens if I use --closure 1 without an -O setting. No other debug options are enabled so I don't see why this would be the case.

@JamesDunne
Copy link
Author

Aha, finally success! I'm down to 16KB of JS code now.

I added -s LINKABLE="1" -O2 --closure 1 to my build command line so that -O2 wouldn't trim out the extern functions.

@kripken
Copy link
Member

kripken commented Nov 20, 2013

Note that if you really care only about code size, you can get a small reduction from -s ASM_JS=0, as non-asm.js can be slightly smaller.

@JamesDunne
Copy link
Author

Cool, thanks. I'd really like to just elide all of the boilerplate that doesn't have to do with initializing the heap and exporting the module. Some more options for limiting generated boilerplate would be great!

@kripken
Copy link
Member

kripken commented Nov 20, 2013

Closure should remove everything possible (if not, then that is a bug in closure, and we should help them fix it). In general though, emscripten output will always have a little basic overhead in terms of setting up a C-like runtime environment, parts of libc as necessary, etc. But that should be just a few K at most.

@kripken kripken closed this as completed Nov 20, 2013
@makc
Copy link

makc commented Apr 5, 2015

is there any official advice on this?

-s LINKABLE="1" -O2 --closure 1

actually blows the file up to 1.3MB now, where

 -O2 --closure 1

generates 115KB (both also have --bind and --memory-init-file 0). All I am compiling here is this cpp:

int test() {
    return 42;
}

#include <emscripten/bind.h>
using namespace emscripten;
EMSCRIPTEN_BINDINGS(my_module) {
    function("test", &test);
}

with these pre/post js:

window['Some'] = (function () {
...
    return Module;
}) ();

yet there are things like d.da("/tmp");d.da("/home");d.da("/home/web_user")}, which are surely not used.

@makc
Copy link

makc commented Apr 5, 2015

by getting rid of --bind magic in favor of exprort "C" / -s EXPORTED_FUNCTIONS="['_test']" I was able to go down to 85KB from 115 above, but still nowhere near 16KB that are claimed here.

@makc
Copy link

makc commented Apr 5, 2015

and adding this

-s DEFAULT_LIBRARY_FUNCS_TO_INCLUDE="['memcpy','memset','malloc','free','strlen']"

only cuts it down to 41KB.

@makc
Copy link

makc commented Apr 5, 2015

and DEFAULT_LIBRARY_FUNCS_TO_INCLUDE + bind (and O2) = 71KB. I think I will try to stick with this way as it seem to give good compromise, but if there is anything else I can do - please give me the link.

@kripken
Copy link
Member

kripken commented Apr 6, 2015

LINKABLE disables all dead code elimination, so it will increase code size substantially.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants