Closed anthonny closed 6 years ago
In general, we want to avoid having special code for JavaScript. The ideal strategy is to make Opal faster, or get it to generate more optimized JavaScript code. With that said, if we've identified a "hot spot" that's eating up a lot of time, we can replace the implementation of the method in Ruby with native JavaScript code.
You can see an example of how this is done in the opal_ext/file.rb class.
https://github.com/asciidoctor/asciidoctor/blob/master/lib/asciidoctor/opal_ext/file.rb#L98
Code in a %x()
string or enclosed in backticks is passed directly into the compiled JavaScript code. Obvious places to put this code are areas where we are already using a guard block to isolate Opal-specific code, such as https://github.com/asciidoctor/asciidoctor/blob/master/lib/asciidoctor/substitutors.rb#L371
Another idea is to stream the converted result to the DOM so that we write each section or block to the DOM as it's converted. That way, there isn't a large pause waiting for the browser to perform the innerHTML replacement. We could potentially hook into the Converter#convert method.
Did a quick run with the Chrome CPU profiling and the winner is... $sub
and $gsub
:
Streaming the content to the DOM is an excellent idea (plus AMO don't like innerHTML
) but I think this is not the current "hot spot".
A test using Nashorn can be found at https://github.com/lordofthejars/asciidoctorj/blob/feature_189/src/test/java/org/asciidoctor/WhenAsciidoctorJIsUsedWithinNashorn.java#L28
I noticed that the last version of v8 is getting faster and faster. Here's the timing loop for rendering the AsciiDoc Python user guide (which has been a benchmark for Asciidoctor since the beginning) using node.
node 0.12
Load scripts: 0.261s
Run #1: 1.217s
Run #2: 0.897s
Run #3: 0.766s
Run #4: 0.742s
node 5.3.0
Load scripts: 0.253s
Run #1: 1.08s
Run #2: 0.857s
Run #3: 0.673s
Run #4: 0.691s
(Good to know that Asciidoctor.js works with node v5.3.0).
In comparison, Asciidoctor running on Ruby 2.3.0 converts it in 0.18s.
We should probably create a benchmark folder in Asciidoctor.js so that we can easily get results to compare between versions. I have a script that I could commit. I'll propose it in a PR.
Is it possible to profile using node? It seems like it would be a lot easier to automate.
Here are the timings using jjs / nashorn 1.8.0_51.
Load scripts: 5.265s
Run #1: 30.995s
Run #2: 18.884s
Run #3: 13.255s
Run #4: 10.513s
As promised, #161.
For some reason, phantomjs can't resolve the include directive, so I can't get results for phantom. I haven't been able to figure out why yet.
Got it working with PhantomJS 1.9.8:
Load scripts: 0.085s
Run #1: 1.169s
Run #2: 1.146s
Run #3: 1.152s
Run #4: 1.169s
Thanks to Dan we have a benchmark script (and on recent version of Node.js it's pretty to use the built-in profiler).
:beers:
Some tools : https://developer.chrome.com/devtools/docs/cpu-profiling
http://octane-benchmark.googlecode.com/svn/latest/index.html