Showing the changes to libraries/script-engine/src/v8/ScriptEngineV8.cpp (1 of 6 files). Show all
Unified · Split
| @@ -56,6 +56,7 @@ · 55 unmodified lines | ||
| 56 | 56 | #include "ScriptValueV8Wrapper.h" |
| 57 | 57 | #include "ScriptEngineLoggingV8.h" |
| 58 | 58 | #include "ScriptValueIteratorV8Wrapper.h" |
| 59 | +#include "shared/FileUtils.h" | |
| 59 | 60 | |
| 60 | 61 | static 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 | |
| 1454 | +void 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 | + | |
| 1473 | +int 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 | + | |
| 1481 | +QString 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 | + | |
| 1493 | +void 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 | + | |
| 1453 | 1538 | ContextScopeV8::ContextScopeV8(ScriptEngineV8 *engine) : |
| 1454 | 1539 | _engine(engine) { |
| 1455 | 1540 | Q_ASSERT(engine); |