UNPKG

zthreader

Version:

JavaScript library that provides pseudo-threading for leveraging resources during long, CPU intensive operations

169 lines (140 loc) 6.72 kB
<!DOCTYPE html> <html> <head> <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable = no" name="viewport"> <meta charset="utf-8" /> <title>ZThreader example</title> <script src="../dist/zthreader.min.js" type="text/javascript"></script> </head> <body> <div id="container"> <h1>Example JavaScript "threading" application #2</h1> <p> Below two buttons to execute a heavy operation. </p> <p> The <strong>normal</strong> one will complete faster, but will leave the application unresponsive (there <i>should</i> be a GIF image showing a spinning animation during the operation but it is likely to be frozen (if it appears at all!), and on some browsers you'd even be unable to switch to different tabs!). As a matter of fact, if you're unlucky the browser/tab might even crash as the script execution takes longer than the browser deems feasible!! Just to be sure, open this page in a new window and test the "normal" button there in case the thing decides to crash!! </p> <p> The <strong>threaded</strong> one will take slightly longer to complete, but will leave plenty of CPU cycles to render the application interface, keeping it responsive (i.e. GIF animation should run smoothly, switching to other tabs should be possible (will postpone script execution until return though!). As a matter of fact, if you're feeling adventurous, you can click this button multiple times to run several threads at the same time (they will each take longer to complete, but with the benefit that the UI still remains responsive! also note that upon each individual threads completion, the remainder will complete faster as more resources become available). </p> <p> Upon completion of each individual execution, an alert box should popup to show the results (elapsed time). </p> <button id="normal" onclick="normal();">normal execution</button> <button id="threaded" onclick="threaded();">threaded execution</button> <div id="state"></div> <img id="loader" src="assets/loader.gif" style="display:none;" /> </div> <script type="text/javascript"> // initialize ZThreader to ensure 60 fps animation at 40% CPU load zThreader.init( 0.4, 60 ); var MAX_ITERATIONS = 150000000; // a ridiculous amount to overload the CPU var startTime, elapsedTime; var isRunning = false; var isRunningNormal = false; var stats = { "normal" : 0, "concurrent" : 0 }; // invoked when starting the execution function handleStart() { isRunning = true; document.getElementById( "loader" ).style.display = "block"; startTime = +new Date(); } // invoked when completing a full execution function handleComplete() { elapsedTime = +new Date() - startTime; if ( isRunningNormal ) stats.normal = elapsedTime; if ( zThreader.getAmountOfThreads() === 0 ) { isRunning = false; document.getElementById( "loader" ).style.display = "none"; showState( "currently running 0 operations" ); var msg; if ( isRunningNormal ) { msg = "total operation(s) took: " + elapsedTime + " milliseconds to complete."; } else { // calculate some statistics msg = ( "total " + stats.concurrent + " operation(s) took: " + elapsedTime + " milliseconds to complete" ); if ( stats.concurrent > 1 ) { msg += " ( " + ( elapsedTime / stats.concurrent ).toFixed( 0 ) + " milliseconds per operation ) "; } if ( stats.normal != 0 ) { msg += " ran at " + (( stats.normal / ( elapsedTime / stats.concurrent )) * 100 ).toFixed( 2 ) + " % of un-threaded speed"; } stats.concurrent = 0; // reset } alert( msg ); } else { showState( "currently running " + zThreader.getAmountOfThreads() + " concurrent threads" ); } } // convenience method to display a message in the DOM function showState( msg ) { document.getElementById( "state").innerHTML = msg; } // the fiendishly heavy function we'd like to execute function heavyOperation( number ) { Math.sin( Math.pow( Math.random() * MAX_ITERATIONS, number )); } // the normal, non-threaded execution of the heavy function function normal() { if ( isRunning ) { return; } isRunningNormal = true; handleStart(); for ( var i = 0; i < MAX_ITERATIONS; ++i ) { heavyOperation( i ); } handleComplete(); isRunningNormal = false; } // the threaded version of running the fiendishly heavy function function threaded() { var thread = new zThread({ completeFn: handleComplete, // here we define our own custom override of // the ZThread internal execution handler to // run the heavy operation executionFn: function() { // the amount of times we call the "heavyOperation"-function // per iteration of the internal execution method var stepsPerIteration = 2500; for ( var i = 0; i < stepsPerIteration; ++i ) { if ( this._iterations >= MAX_ITERATIONS ) { return true; } else { // execute operation (and increment iteration) heavyOperation( ++this._iterations ); } } return false; } }); handleStart(); thread.run(); stats.concurrent = Math.max( stats.concurrent, zThreader.getAmountOfThreads() ); showState( "currently running " + zThreader.getAmountOfThreads() + " concurrent threads" ); } </script> </body>