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 | #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 | ||
| 60 | static const int MAX_DEBUG_VALUE_LENGTH { 80 }; | 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 | ContextScopeV8::ContextScopeV8(ScriptEngineV8 *engine) : | 1538 | ContextScopeV8::ContextScopeV8(ScriptEngineV8 *engine) : |
| 1454 | _engine(engine) { | 1539 | _engine(engine) { |
| 1455 | Q_ASSERT(engine); | 1540 | Q_ASSERT(engine); |