-
Notifications
You must be signed in to change notification settings - Fork 70
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
JavaScript: Closure compilation at the advanced level (WIP) #92
Comments
30-50% faster? That sounds fantastic. On that very subject, is there some way we can add Javascript benchmarks? Having some benchmarks prior your PR being merged @lhecker would then nicely showcase the improvements when they land. Would also help to avoid situations like pre-release protocolbuffers/protobuf#2117 Is there a general, language independent suite of benchmarks that could be used? |
@myitcv I'll port the C++ benchmarks to JS realy quick, but I'm not really comfortable with integrating it into this project since I'm not familar with the coding style, preferred directory layout, nor library/framework choice. I'll make it available as a gist or something though as soon as I'm done. 🙂 |
@myitcv I've set up a benchmark project (quick & dirty though). DecodeHere are the interesting numbers (formatted):
EncodeAnd the less interesting part (encoding doesnt really use assertions):
|
Thanks for the update @lhecker - we'd be very happy to give this a try when you have a branch ready. |
@myitcv You can find it here. 🙂 You can build it by running |
@lhecker - I'm being slow; how does the |
Ah okay I assumed you're using the npm/commonjs version (because most do nowadays, right?) and that particular file is what's distributed there. If you don't use that you can probably directly use my fork (I don't really see any difference between that JS release and the actual repository so I guess that should work). |
No, we're using the official Github releases What's interesting is that the file Which makes me wonder whether we're doing the "right thing" or not... We reference: <script src="goog/base.js"></script>
<script src="protobuf/map.js"></script>
<script src="protobuf/message.js"></script>
<script src="protobuf/binary/arith.js"></script>
<script src="protobuf/binary/constants.js"></script>
<script src="protobuf/binary/utils.js"></script>
<script src="protobuf/binary/decoder.js"></script>
<script src="protobuf/binary/encoder.js"></script>
<script src="protobuf/binary/reader.js"></script>
<script src="protobuf/binary/writer.js"></script> where And the Any thoughts on where we're going wrong? Should we be referencing the |
No I think you should continue referencing the same files but replaced with those from my fork instead. I didn't use anything except for CommonJS and ES6 modules in a long time so I'm not entirely sure about any implications regarding precompilation with the closure compiler etc. I'm not even a real frontend engineer anyways. 😄 But my gut instincts tell me that it should just work. ™ The |
Ah btw @myitcv: I don't know how your asset compilation chain is set up or if you even have one but to make use of possible performance improvements due to the removal of the You can also try this experimental file. It's the same as |
@lhecker thanks. It's been a while since we looked at our build pipeline... indeed when we first put it together there we no up-to-date npm packages for either the closure library or protobuf (hence my not having a clue about |
@lhecker after a very rudimentary test, we're also seeing ~40% speed up which is great, specifically around |
Wow, this is great. Sorry for the delay, There is so much activity on GitHub that I miss stuff sometimes. I think dropping asserts for the dist release should be fine. We want them to trigger in unit tests, but I think the intention is that release builds will not need them. Please send a PR with your work -- this sounds great. |
@haberman Sorry I forgot about this again. 😕 There where quite some merge conflicts going on, but by carefully applying some nuclear regular expressions (as simple as Again: The problem is that throughout the code you guys currently use closure asserts as a way to add preconditions for functions, but unfortunately asserts get stripped away in optimized builds. So my question in this issue remains: What do we do about the use of asserts in the code? One example is this which makes the testCopyInto_notSameType test fail. This is the only test that fails due to this, but there are surely more places in the code where asserts are used like that, but don't have any unit tests yet. The other test that fails right now is testUnknownExtension, but I'm not yet entirely sure why it fails. This test creates a
while a
I don't really understand all the code in this library, which is why it'd be great if someone can help me that test in particular. Do you want me to still open a PR even though it's incomplete? Either way we have to decide what to do about the assertions (e.g. drop them including tests that rely on that behaviour entirely or replace them with |
I think this is entirely intended. The asserts are intended to catch errors in how the functions are called. But we only want to perform these checks in debug builds (ie. in unit tests). In optimized builds we don't want to pay for these checks. How many of our unit tests depend on asserts getting triggered? Perhaps we could wrap these checks somehow so that they are only triggered for non-opt builds? The other question is how we could allow our users to use the non-opt build for their own unit tests. Ideally the npm package could include both debug and release builds, and users could opt for which one they want. Does that seem doable? |
ping @lhecker would love to see these changes land. Looking at your WIP branch it wasn't immediately clear, do these changes only apply to the |
@AndrewGuenther I'm currently very busy and don't have enough time to work on this. I'm not even sure when this will change in the future... Especially considering that I recently switched to compiling the output of The WIP branch ( |
@haberman As I said in my previous comment right above I'm currently extremely busy and don't know when I'm able to continue my work. I hope you can understand that as well. 😅 The asserts might be a must have for the npm module though as that one won't have any closure type annotations etc. It'd might indeed be a good idea to ship a debug and a release build there due to that. I don't think there is an easy solution for switching between both though. A user of the npm package would have to code an own solution for that using a build script etc. Also regarding the tests relying on asserts: I'm only aware of testCopyInto_notSameType and testUnknownExtension relying on that. I went into a bit into detail in my other comment above. |
@lhecker that makes sense, I actually ended up going a similar route as well, however, when I directly compile the Currently, I have to compile the entirety of each consuming project together in order to make it work, but ideally I would like to only compile the |
@AndrewGuenther Did you make sure to use the The relevant parts in my build script look like this: if [ ! -r "$deps_path" ]; then
echo $'\n# Calcdeps'
./node_modules/google-closure-library/closure/bin/calcdeps.py \
-p ./node_modules/google-closure-library/closure \
-p "$project_dir" \
-i "$js_entry_path" \
> "$deps_path"
fi
readarray -t deps < "$deps_path"
java -jar "$compiler_path" \
--warning_level=VERBOSE \
--jscomp_error='*' \
--jscomp_off=analyzerChecks \
--jscomp_off=deprecated \
--jscomp_off=extraRequire \
--jscomp_off=inferredConstCheck \
--jscomp_off=lintChecks \
--jscomp_off=unnecessaryCasts \
--compilation_level=ADVANCED \
--process_common_js_modules \
--assume_function_wrapper \
--language_in=ECMASCRIPT5 \
--language_out=ECMASCRIPT5 \
--generate_exports \
--export_local_property_definitions \
--rewrite_polyfills=false \
--create_source_map="$out_map_path" \
--js_output_file="$out_js_path" \
"${deps[@]}" The extra call to |
Merry Christmas everyone! Looks like this went quiet for quite a while but it will be very useful to have it fixed. I've raised PR protocolbuffers/protobuf#5509 for this. Working on the tests. |
Oh dear... I'm such an idiot... I seem to have deleted my protobuf fork at some point since opening this issue and my work from back then has been lost. 😰 |
@lhecker Your commit is still here (referenced in this issue) :) |
After further modifications the only failing test is testCopyInto_notSameType which depends on |
Is there any progress? Seem jj's PR is not merged, and proto.js is still too large for mobile cases. |
Hey @haberman!
I've recently found your TODO and started adding those proper
@export
etc. annotations. My current work can be found here (WIP - I'll surely squash the commits in the future).I'm actually nearly done now: All required annotations are added, the gulp file as well as the tests have been modified & fixed. The problem I now have is that you guys are using
goog.asserts
, which gets stripped out on the advanced closure level and there is no CLI switch to disable that (there is onlysetRemoveClosureAsserts(boolean)
in the API).So... What should be the way forward now? Should I simply copy/paste the required parts from
goog.asserts
into this project, write a modified closure-compiler CLI or simply drop all asserts in the dist release? 🙂cc: @xfxyjwf
P.S.: The size of the gzipped dist release is about 60% smaller (28kB vs. 11kB) and permanently (!) about 30-50% (!) faster without the asserts @ advanced level. So maybe if we continue dropping all non-essential asserts we could even gain a non-trivial speed improvement (or release a "fast" version alternatively, since almost always incoming data in the browser is received by trusted entities anyways).
The text was updated successfully, but these errors were encountered: