blob: 7cb0d7ad0f0147bea65a2331d75ad8176e618335 [file] [log] [blame]
// Copyright 2015 The Emscripten Authors. All rights reserved.
// Emscripten is available under two separate licenses, the MIT license and the
// University of Illinois/NCSA Open Source License. Both these licenses can be
// found in the LICENSE file.
var emscriptenThreadProfiler = {
// UI update interval in milliseconds.
uiUpdateIntervalMsecs: 1000,
// UI div element.
threadProfilerDiv: null,
// Installs startup hook and periodic UI update timer.
initialize: function initialize() {
this.threadProfilerDiv = document.getElementById('threadprofiler');
if (!this.threadProfilerDiv) {
var div = document.createElement("div");
div.innerHTML = "<div id='threadprofiler' style='margin: 20px; border: solid 1px black;'></div>";
document.body.appendChild(div);
this.threadProfilerDiv = document.getElementById('threadprofiler');
}
setInterval(function() { emscriptenThreadProfiler.updateUi() }, this.uiUpdateIntervalMsecs);
},
updateUi: function updateUi() {
if (typeof PThread === 'undefined') return; // Likely running threadprofiler on a singlethreaded build, or not initialized yet, ignore updating.
var str = '';
var mainThread = PThread.mainThreadBlock;
var threads = [PThread.mainThreadBlock];
for(var t in PThread.pthreads) threads.push(PThread.pthreads[t].threadInfoStruct);
for(var i = 0; i < threads.length; ++i) {
var threadPtr = threads[i];//(t == PThread.mainThreadBlock ? PThread.mainThreadBlock : maiPThread.pthreads[t].threadInfoStruct;
var profilerBlock = Atomics.load(HEAPU32, (threadPtr + 20 /*C_STRUCTS.pthread.profilerBlock*/ ) >> 2);
var threadName = PThread.getThreadName(threadPtr);
if (threadName) threadName = '"' + threadName + '" (0x' + threadPtr.toString(16) + ')';
else threadName = '(0x' + threadPtr.toString(16) + ')';
str += 'Thread ' + threadName + ' now: ' + PThread.threadStatusAsString(threadPtr) + '. ';
var threadTimesInStatus = [];
var totalTime = 0;
for(var j = 0; j < 7/*EM_THREAD_STATUS_NUMFIELDS*/; ++j) {
threadTimesInStatus.push(HEAPF64[((profilerBlock + 16/*C_STRUCTS.thread_profiler_block.timeSpentInStatus*/) >> 3) + j]);
totalTime += threadTimesInStatus[j];
HEAPF64[((profilerBlock + 16/*C_STRUCTS.thread_profiler_block.timeSpentInStatus*/) >> 3) + j] = 0;
}
var recent = '';
if (threadTimesInStatus[1] > 0) recent += (threadTimesInStatus[1] / totalTime * 100.0).toFixed(1) + '% running. ';
if (threadTimesInStatus[2] > 0) recent += (threadTimesInStatus[2] / totalTime * 100.0).toFixed(1) + '% sleeping. ';
if (threadTimesInStatus[3] > 0) recent += (threadTimesInStatus[3] / totalTime * 100.0).toFixed(1) + '% waiting for futex. ';
if (threadTimesInStatus[4] > 0) recent += (threadTimesInStatus[4] / totalTime * 100.0).toFixed(1) + '% waiting for mutex. ';
if (threadTimesInStatus[5] > 0) recent += (threadTimesInStatus[5] / totalTime * 100.0).toFixed(1) + '% waiting for proxied ops. ';
if (recent.length > 0) str += 'Recent activity: ' + recent;
str += '<br />';
}
this.threadProfilerDiv.innerHTML = str;
}
};
if (typeof Module !== 'undefined' && typeof document !== 'undefined') emscriptenThreadProfiler.initialize();