Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
emscripten-core
GitHub Repository: emscripten-core/emscripten
Path: blob/main/src/threadprofiler.js
6165 views
1
#preprocess
2
3
/**
4
* @license
5
* Copyright 2015 The Emscripten Authors
6
* SPDX-License-Identifier: MIT
7
*/
8
9
var emscriptenThreadProfiler = {
10
// UI update interval in milliseconds.
11
uiUpdateIntervalMsecs: 1000,
12
13
// UI div element.
14
threadProfilerDiv: null,
15
16
// Installs startup hook and periodic UI update timer.
17
initialize() {
18
var self = emscriptenThreadProfiler;
19
self.threadProfilerDiv = document.getElementById('threadprofiler');
20
if (!self.threadProfilerDiv) {
21
var div = document.createElement("div");
22
div.innerHTML = "<div id='threadprofiler' style='margin: 20px; border: solid 1px black;'></div>";
23
document.body.appendChild(div);
24
self.threadProfilerDiv = document.getElementById('threadprofiler');
25
}
26
var i = setInterval(() => self.updateUi(), self.uiUpdateIntervalMsecs);
27
addOnExit(() => clearInterval(i));
28
},
29
30
initializeNode() {
31
addOnInit(() => {
32
var self = emscriptenThreadProfiler;
33
self.dumpState();
34
var i = setInterval(() => self.dumpState(), self.uiUpdateIntervalMsecs);
35
addOnExit(() => clearInterval(i));
36
});
37
},
38
39
dumpState() {
40
var mainThread = _emscripten_main_runtime_thread_id();
41
42
var threads = [mainThread];
43
for (var thread of Object.values(PThread.pthreads)) {
44
threads.push(thread.pthread_ptr);
45
}
46
for (var threadPtr of threads) {
47
var threadName = PThread.getThreadName(threadPtr);
48
if (threadName) {
49
threadName = `"${threadName}" (${ptrToString(threadPtr)})`;
50
} else {
51
threadName = `(${ptrToString(threadPtr)})`;
52
}
53
54
console.log(`Thread ${threadName} now: ${PThread.threadStatusAsString(threadPtr)}. `);
55
}
56
},
57
58
updateUi() {
59
if (typeof PThread == 'undefined') {
60
// Likely running threadprofiler on a singlethreaded build, or not
61
// initialized yet, ignore updating.
62
return;
63
}
64
if (!runtimeInitialized) {
65
return;
66
}
67
var str = '';
68
var mainThread = _emscripten_main_runtime_thread_id();
69
70
var threads = [mainThread];
71
for (var thread of Object.values(PThread.pthreads)) {
72
threads.push(thread.pthread_ptr);
73
}
74
75
for (var threadPtr of threads) {
76
var profilerBlock = Atomics.load({{{ getHeapForType('*') }}}, {{{ getHeapOffset('threadPtr + ' + C_STRUCTS.pthread.profilerBlock, '*') }}});
77
#if MEMORY64
78
profilerBlock = Number(profilerBlock);
79
#endif
80
var threadName = PThread.getThreadName(threadPtr);
81
if (threadName) {
82
threadName = `"${threadName}" (${ptrToString(threadPtr)})`;
83
} else {
84
threadName = `(${ptrToString(threadPtr)})`;
85
}
86
87
str += `Thread ${threadName} now: ${PThread.threadStatusAsString(threadPtr)}. `;
88
89
var threadTimesInStatus = [];
90
var totalTime = 0;
91
var offset = profilerBlock + {{{ C_STRUCTS.thread_profiler_block.timeSpentInStatus }}};
92
for (var j = 0; j < {{{ cDefs.EM_THREAD_STATUS_NUMFIELDS }}}; ++j, offset += 8) {
93
threadTimesInStatus.push({{{ makeGetValue('offset', 0, 'double') }}});
94
totalTime += threadTimesInStatus[j];
95
{{{ makeSetValue('offset', 0, 0, 'double') }}};
96
}
97
var recent = '';
98
if (threadTimesInStatus[1] > 0) recent += (threadTimesInStatus[1] / totalTime * 100.0).toFixed(1) + '% running. ';
99
if (threadTimesInStatus[2] > 0) recent += (threadTimesInStatus[2] / totalTime * 100.0).toFixed(1) + '% sleeping. ';
100
if (threadTimesInStatus[3] > 0) recent += (threadTimesInStatus[3] / totalTime * 100.0).toFixed(1) + '% waiting for futex. ';
101
if (threadTimesInStatus[4] > 0) recent += (threadTimesInStatus[4] / totalTime * 100.0).toFixed(1) + '% waiting for mutex. ';
102
if (threadTimesInStatus[5] > 0) recent += (threadTimesInStatus[5] / totalTime * 100.0).toFixed(1) + '% waiting for proxied ops. ';
103
if (recent.length > 0) str += `Recent activity: ${recent}`;
104
str += '<br />';
105
}
106
emscriptenThreadProfiler.threadProfilerDiv.innerHTML = str;
107
}
108
};
109
110
if (globalThis.document) {
111
emscriptenThreadProfiler.initialize();
112
} else if (!ENVIRONMENT_IS_PTHREAD && globalThis.process) {
113
emscriptenThreadProfiler.initializeNode();
114
}
115
116