Welcome to my blog, stay tunned :
Home | Blogs | Stephane Eyskens's blog

Edge's performance with HTML5 Web Workers versus Chrome

Hi,

This post is a little unusual compared to what I usually blog but for some obscure reasons that I don't want to reveal here :), I have to make an in-depth analysis of HTML5. I'll tackle most of the APIs such as Web Workers, Web Sockets etc...and it will all be about metrics. I know that there exists several frameworks to benchmark browsers but 1) I find them a little opaque and 2) I'm only interested by HTML5 related metrics. Basically, I don't want to reinvent the wheel but I need to write some basic scripts whose the purpose is to measure browser performance.
For this blog post, I have taken metrics about HTML5 Web Workers. So, I have tested the following:

  • I wrote a web service that returns a large (+- 17 MB) lorem ipsum string
  • I wrote a web worker that performs a lemmatization process against the data returned by the web service
  • I took metrics using a single worker (one separate thread)
  • I then took metric over 4 different workers. I splitted the large string into 4 sub strings to perform the lemmatization process using my 4 cores in parrallel

For completeness, the machine on which this test was performed has 4 cores, 8 logical processors, 2,49GHz, 500GB SSD drives and 32GB of RAM. It's running Windows 10 Enterprise. For the fun, I also tried this with an IPAD Model MD795NF/A but it was way too slow and even crashed. I guess that the amount of data to handle was just too big for a mobile device such as an IPAD.

So, instead of performing the usual calculation algorithms when it comes to web workers, I tried to envision a more realistic scenario from a business perspective. In other words, I perform an AJAX query on the UI Thread and let web workers handle its large answer in separate threads. The large answer contains millions of words for which I perform a lemmatization using an open source library available on GitHub https://github.com/takafumir/javascript-lemmatizer which I have slighly modified in order to make it work through web workers. I could have avoided the AJAX call but it was easier to adjust the message size from a web service.

So, it turned out that Chrome was way faster. Unlike for the Web Storage where IE is faster for reading and writing into the sessionStorage and for reading from the localStorage (but a lot slower to write to the localStorage). Here, for Web Workers, figures are talking by themselves:

This graph shows the time taken by invidual workers over 5 execution. For each execution, 4 workers were spawned which makes a total of 20 metrics. Chrome is about 3 times faster than Edge... I then decided to see if the behaviour would be similar using a single worker (single thread):

This graph shows the time taken by a single worker over 10 executions. Edge is showing very stable performance but is slower than Chrome which is more heterogenous regarding its execution times. Strangely enough, Chrome is less than twice faster than Edge where it was nearly 3 times faster for the multi-threaded scenario.

This seems to indicate that Chrome is not only faster but seems to handle better the usage of multiple cores because in this scenario, it's growing from 1.5 faster to 3 times faster. Oh, and here is the script I used:

<script src="https://code.jquery.com/jquery-2.1.4.min.js" type="text/javascript"></script>
<script type="text/javascript">    
function MultipleWorkers()
{
    $.ajax({
        url: "http://edgewworkers.azurewebsites.net/service1.svc/getdata",
        headers: {          
            Accept : "application/json"
        },
        success: function (result) {
            console.log("Response length is " + result.length);            
            var step = result.length / 4;
            for (var i = 0; i < result.length; i += step)
            {
                var worker = new Worker("../js/lemmatizer.js");
                worker.postMessage(result.substr(i, step));
                worker.onmessage = function (e) {
		 $("#results").append(e.data+"<br/>");
                }
            }            
        }
    });
}

function SingleWorker() {
    $.ajax({
        url: "http://edgewworkers.azurewebsites.net/service1.svc/getdata",
        headers: {
            Accept: "application/json"
        },
        success: function (result) {
            console.log("Response length is " + result.length);
            var worker = new Worker("../js/lemmatizer.js");
            worker.postMessage(result);
            worker.onmessage = function (e)
            {
                $("#results").append(e.data+"<br/>");
            }
        }
    });
}
</script>
<input type="button" value="4 workers" onclick="MultipleWorkers()" />
<input type="button" value="single worker" onclick="SingleWorker()" />
<div id="results"></div>

This is the code of the page that uses the UI thread for the AJAX call and spawns one ore more workers to perform the lemmatization process. Here is the important part of the worker code:

function messageHandler(e) {
    var start = new Date().getTime();
    var lemmatizer = new Lemmatizer();
    postMessage("Received " + e.data.length + " bytes");
    var parts = e.data.split(" ");
    for (var i = 0; i < parts.length; i++) {
        _.each(lemmatizer.lemmas(parts[i], ""), function (val) {
            //this guy gets a lemma for the given word
        });
    }
    var end = new Date().getTime();
    postMessage(end - start);
}

So, I don't put the code of the lemmatization (500 lines of code...) itself because it's not important for the metric itself. So, I'm calculating a start time and I post the execution time via the postMessage function (that sends this message back to the UI thread in this case). Of course, the same code was used for both Edge and Chrome. If you're interested by the details, go to the GitHub project where this open source library is available.


Happy Coding