History

Add JS profiling API

Karol Suprynowicz committed 3 years ago

Commit a84c68f1 parent 47ec27f6 files · +144 −2Browse files

Showing the changes to libraries/script-engine/src/v8/ScriptEngineV8.cpp (1 of 6 files). Show all

Unified · Split

libraries/script-engine/src/v8/ScriptEngineV8.cpp+85−0
@@ -56,6 +56,7 @@ · 55 unmodified lines
56#include "ScriptValueV8Wrapper.h"56#include "ScriptValueV8Wrapper.h"
57#include "ScriptEngineLoggingV8.h"57#include "ScriptEngineLoggingV8.h"
58#include "ScriptValueIteratorV8Wrapper.h"58#include "ScriptValueIteratorV8Wrapper.h"
59#include "shared/FileUtils.h"
59 60
60static const int MAX_DEBUG_VALUE_LENGTH { 80 };61static const int MAX_DEBUG_VALUE_LENGTH { 80 };
61 62
@@ -1450,6 +1451,90 @@ void ScriptEngineV8::dumpHeapObjectStatistics() { · 1388 unmodified lines
1450 }1451 }
1451}1452}
1452 1453
1454void ScriptEngineV8::startProfiling() {
1455 if (_profiler) {
1456 qWarning(scriptengine_v8) << "ScriptEngineV8::startProfiling: Profiler is already running";
1457 return;
1458 }
1459 _profiler = v8::CpuProfiler::New(_v8Isolate);
1460 v8::CpuProfilingResult result = _profiler->Start(v8::CpuProfilingOptions());
1461 if (!result.id) {
1462 qWarning(scriptengine_v8) << "ScriptEngineV8::startProfiling: Profiler failed to start";
1463 _profiler->Dispose();
1464 _profiler = nullptr;
1465 return;
1466 }
1467 qDebug(scriptengine_v8) << "Script profiler started";
1468 _profilerId = result.id;
1469};
1470
1471// Helper function for ScriptEngineV8::stopProfilingAndSave
1472
1473int getTotalNodeHitCount(const v8::CpuProfileNode *node) {
1474 int hitCount = node->GetHitCount();
1475 for (int i = 0; i < node->GetChildrenCount(); i++) {
1476 hitCount += getTotalNodeHitCount(node->GetChild(i));
1477 }
1478 return hitCount;
1479}
1480
1481QString getLogFileName() {
1482 static const QString FILENAME_FORMAT = "overte-profile_%1.txt";
1483 static const QString DATETIME_FORMAT = "yyyy-MM-dd_hh.mm.ss";
1484 static const QString LOGS_DIRECTORY = "Logs";
1485
1486 QString result = FileUtils::standardPath(LOGS_DIRECTORY);
1487 QDateTime now = QDateTime::currentDateTime();
1488
1489 result.append(QString(FILENAME_FORMAT).arg(now.toString(DATETIME_FORMAT)));
1490 return result;
1491}
1492
1493void ScriptEngineV8::stopProfilingAndSave() {
1494 // the following will produce 11/18 13:55:36
1495 const QString DATE_STRING_FORMAT = "MM/dd hh:mm:ss";
1496
1497 if (!_profiler || !_profilerId) {
1498 qWarning(scriptengine_v8) << "ScriptEngineV8::stopProfilingAndSave: Profiler is not running";
1499 return;
1500 }
1501 v8::CpuProfile *profile = _profiler->Stop(_profilerId);
1502 QString filename(getLogFileName());
1503 QFile file(filename);
1504 if (file.open(QIODevice::WriteOnly)) {
1505 QStringList samples;
1506 for (int i = 0; i < profile->GetSamplesCount(); i++) {
1507 QString line;
1508 QTextStream stream(&line);
1509 const v8::CpuProfileNode *node = profile->GetSample(i);
1510 stream << getTotalNodeHitCount(node) << ";"
1511 << node->GetHitCount() << ";"
1512 << node->GetFunctionNameStr() << ";"
1513 << node->GetScriptResourceNameStr() << ";"
1514 << node->GetLineNumber() << "\n";
1515 samples.append(line);
1516 }
1517 samples.sort();
1518 QStringList deduplicated;
1519 deduplicated.append(samples[0]);
1520 for (int i=1; i < samples.size(); i++) {
1521 if (samples[i] != samples[i-1]) {
1522 deduplicated.append(samples[i]);
1523 }
1524 }
1525 QTextStream fileStream(&file);
1526 for (QString line : deduplicated) {
1527 fileStream << line;
1528 }
1529 } else {
1530 qWarning(scriptengine_v8) << "ScriptEngineV8::stopProfilingAndSave: Cannot open output file";
1531 }
1532 profile->Delete();
1533 _profiler->Dispose();
1534 _profiler = nullptr;
1535 qDebug(scriptengine_v8) << "Script profiler stopped, results written to: " << filename;
1536};
1537
1453ContextScopeV8::ContextScopeV8(ScriptEngineV8 *engine) :1538ContextScopeV8::ContextScopeV8(ScriptEngineV8 *engine) :
1454 _engine(engine) {1539 _engine(engine) {
1455 Q_ASSERT(engine);1540 Q_ASSERT(engine);