scichart
Version:
Fast WebGL JavaScript Charting Library and Framework
595 lines (594 loc) • 29 kB
JavaScript
"use strict";
/**
* WasmMemoryDebugHelper - TypeScript interface for WASM memory tracking
*
* This helper provides access to memory tracking data stored in window.__sciChartMemoryTracking
* by the C++ memory override system. It allows toggling tracking flags and retrieving/logging
* memory statistics.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.WasmMemoryDebugHelper = void 0;
/**
* WasmMemoryDebugHelper class - provides TypeScript interface to memory tracking
* @ignore This is supposed to be available only during development in Debug Wasm build mode
*/
var WasmMemoryDebugHelper = /** @class */ (function () {
function WasmMemoryDebugHelper() {
}
/**
* Get the memory tracking object from window, or undefined if not initialized
* @returns The memory tracking object with proper typing, or undefined
*/
WasmMemoryDebugHelper.getTracking = function () {
return window.__sciChartMemoryTracking;
};
/**
* Get the window object with memory tracking property
* @returns The window object (use getTracking() for typed access to memory tracking data)
*/
WasmMemoryDebugHelper.getWindow = function () {
return window;
};
/**
* Check if memory tracking is initialized
*/
WasmMemoryDebugHelper.isInitialized = function () {
return !!this.getTracking();
};
/**
* Initialize memory tracking storage on the JavaScript side
* This mirrors the C++ init_memory_tracking_storage function
* Note: The C++ code automatically initializes this, but this method
* can be called explicitly if needed for testing or manual initialization
*/
WasmMemoryDebugHelper.initializeTracking = function () {
if (!window.__sciChartMemoryTracking) {
window.__sciChartMemoryTracking = {
// Malloc/Free tracking
records: new Map(),
allRecords: new Map(),
mallocTimestamp: 0,
mallocNextGuid: 1,
// New/Delete tracking
newRecords: new Map(),
allNewRecords: new Map(),
newDeleteTimestamp: 0,
newDeleteNextGuid: 1,
// Common settings
stackTraceEnabled: true,
mallocTrackingEnabled: true,
newDeleteTrackingEnabled: true
};
}
};
// ============================================================================
// Flag Toggling Methods
// ============================================================================
/**
* Enable or disable stack trace capture for allocations
*/
WasmMemoryDebugHelper.setStackTraceEnabled = function (enabled) {
var tracking = this.getTracking();
if (tracking) {
tracking.stackTraceEnabled = enabled;
}
};
/**
* Get current stack trace enabled state
*/
WasmMemoryDebugHelper.getStackTraceEnabled = function () {
var tracking = this.getTracking();
return tracking ? tracking.stackTraceEnabled : true;
};
/**
* Enable or disable malloc/free tracking
*/
WasmMemoryDebugHelper.setMallocTrackingEnabled = function (enabled) {
var tracking = this.getTracking();
if (tracking) {
tracking.mallocTrackingEnabled = enabled;
}
};
/**
* Get current malloc tracking enabled state
*/
WasmMemoryDebugHelper.getMallocTrackingEnabled = function () {
var tracking = this.getTracking();
return tracking ? tracking.mallocTrackingEnabled : true;
};
/**
* Enable or disable new/delete tracking
*/
WasmMemoryDebugHelper.setNewDeleteTrackingEnabled = function (enabled) {
var tracking = this.getTracking();
if (tracking) {
tracking.newDeleteTrackingEnabled = enabled;
}
};
/**
* Get current new/delete tracking enabled state
*/
WasmMemoryDebugHelper.getNewDeleteTrackingEnabled = function () {
var tracking = this.getTracking();
return tracking ? tracking.newDeleteTrackingEnabled : true;
};
// ============================================================================
// Helper Methods - Calculate Stats from Maps
// ============================================================================
/**
* Calculate statistics from a Map of memory records
* @param map The Map to calculate stats from
* @returns Statistics object with counts and byte totals
*/
WasmMemoryDebugHelper.calculateStatsFromMap = function (map) {
var allocCount = 0;
var deallocCount = 0;
var totalAllocated = 0;
var totalFreed = 0;
for (var _i = 0, _a = Array.from(map.entries()); _i < _a.length; _i++) {
var _b = _a[_i], record = _b[1];
allocCount++;
totalAllocated += record.size;
if (record.deallocated) {
deallocCount++;
totalFreed += record.size;
}
}
return { allocCount: allocCount, deallocCount: deallocCount, totalAllocated: totalAllocated, totalFreed: totalFreed };
};
// ============================================================================
// Reset Methods
// ============================================================================
/**
* Reset malloc/free batch tracking - clears current batch records only
* Preserves: allRecords Map (historical data)
*/
WasmMemoryDebugHelper.resetMallocBatch = function () {
var tracking = this.getTracking();
if (tracking) {
tracking.records.clear();
}
};
/**
* Reset new/delete batch tracking - clears current batch records only
* Preserves: allNewRecords Map (historical data)
*/
WasmMemoryDebugHelper.resetNewDeleteBatch = function () {
var tracking = this.getTracking();
if (tracking) {
tracking.newRecords.clear();
}
};
/**
* Reset malloc/free historical data - clears historical records only
* Clears: allRecords Map (historical)
* Preserves: records Map (batch), timeline counters
*/
WasmMemoryDebugHelper.resetMallocHistorical = function () {
var tracking = this.getTracking();
if (tracking) {
tracking.allRecords.clear();
}
};
/**
* Reset new/delete historical data - clears historical records only
* Clears: allNewRecords Map (historical)
* Preserves: newRecords Map (batch), timeline counters
*/
WasmMemoryDebugHelper.resetNewDeleteHistorical = function () {
var tracking = this.getTracking();
if (tracking) {
tracking.allNewRecords.clear();
}
};
/**
* Reset all historical data - clears both malloc/free and new/delete historical records
* Calls resetMallocHistorical() and resetNewDeleteHistorical()
*/
WasmMemoryDebugHelper.resetAllHistorical = function () {
this.resetMallocHistorical();
this.resetNewDeleteHistorical();
};
/**
* Reset everything - clears all batch and historical data for both malloc/free and new/delete
* Clears all Maps (batch and historical) while preserving timeline counters
* Calls all batch and historical reset methods
*/
WasmMemoryDebugHelper.resetAll = function () {
this.resetMallocBatch();
this.resetNewDeleteBatch();
this.resetAllHistorical();
};
// ============================================================================
// Data Retrieval Methods - Malloc/Free
// ============================================================================
/**
* Get malloc/free memory statistics (calculated from allRecords - historical)
*/
WasmMemoryDebugHelper.getMallocStats = function () {
var tracking = this.getTracking();
if (!tracking) {
return {
totalAllocations: 0,
totalDeallocations: 0,
currentAllocatedBytes: 0,
peakAllocatedBytes: 0
};
}
var stats = this.calculateStatsFromMap(tracking.allRecords);
return {
totalAllocations: stats.allocCount,
totalDeallocations: stats.deallocCount,
currentAllocatedBytes: stats.totalAllocated - stats.totalFreed,
peakAllocatedBytes: stats.totalAllocated
};
};
/**
* Get current batch malloc/free records
*/
WasmMemoryDebugHelper.getMallocRecords = function () {
var tracking = this.getTracking();
return tracking ? tracking.records : new Map();
};
/**
* Get all historical malloc/free records
*/
WasmMemoryDebugHelper.getAllMallocRecords = function () {
var tracking = this.getTracking();
return tracking ? tracking.allRecords : new Map();
};
// ============================================================================
// Data Retrieval Methods - New/Delete
// ============================================================================
/**
* Get new/delete memory statistics (calculated from allNewRecords - historical)
*/
WasmMemoryDebugHelper.getNewDeleteStats = function () {
var tracking = this.getTracking();
if (!tracking) {
return {
totalAllocations: 0,
totalDeallocations: 0,
currentAllocatedBytes: 0,
peakAllocatedBytes: 0
};
}
var stats = this.calculateStatsFromMap(tracking.allNewRecords);
return {
totalAllocations: stats.allocCount,
totalDeallocations: stats.deallocCount,
currentAllocatedBytes: stats.totalAllocated - stats.totalFreed,
peakAllocatedBytes: stats.totalAllocated
};
};
/**
* Get current batch new/delete records
*/
WasmMemoryDebugHelper.getNewDeleteRecords = function () {
var tracking = this.getTracking();
return tracking ? tracking.newRecords : new Map();
};
/**
* Get all historical new/delete records
*/
WasmMemoryDebugHelper.getAllNewDeleteRecords = function () {
var tracking = this.getTracking();
return tracking ? tracking.allNewRecords : new Map();
};
// ============================================================================
// Console Logging Methods - Malloc/Free
// ============================================================================
/**
* Log current batch malloc/free allocations with detailed statistics
* Stats are calculated from the records Map (current batch)
*/
WasmMemoryDebugHelper.logMallocBatch = function () {
var tracking = this.getTracking();
if (!tracking) {
console.warn("Memory tracking not initialized");
return;
}
var records = tracking.records;
var batchStats = this.calculateStatsFromMap(records);
// Calculate batch statistics
var deletedCount = 0;
var notDeletedCount = 0;
var totalAllocatedBytes = 0;
var notDeallocatedBytes = 0;
var notDeletedRecords = [];
var idx = 0;
for (var _i = 0, _a = Array.from(records.entries()); _i < _a.length; _i++) {
var _b = _a[_i], record = _b[1];
totalAllocatedBytes += record.size;
if (record.deallocated) {
deletedCount++;
}
else {
notDeletedCount++;
notDeallocatedBytes += record.size;
notDeletedRecords.push({ record: record, index: idx });
}
idx++;
}
var allocatedDiff = batchStats.totalAllocated - batchStats.totalFreed;
var active = batchStats.allocCount - batchStats.deallocCount;
console.groupCollapsed("[malloc/free] Memory Stats - Allocated Diff: ".concat(allocatedDiff, " bytes ") +
"(Allocs: ".concat(batchStats.allocCount, ", Deallocs: ").concat(batchStats.deallocCount, ", Active: ").concat(active, ")"));
console.log("[malloc/free] Total Allocated: ".concat(batchStats.totalAllocated, " bytes, ") +
"Total Freed: ".concat(batchStats.totalFreed, " bytes, Current: ").concat(allocatedDiff, " bytes"));
console.log("Batch Summary: ".concat(records.size, " allocations, ").concat(deletedCount, " deleted, ").concat(notDeletedCount, " not deleted"));
console.log("Memory: ".concat(totalAllocatedBytes, " bytes allocated, ").concat(notDeallocatedBytes, " bytes not deallocated"));
// Group 1: All batch allocations
console.groupCollapsed("All Batch Allocations (".concat(records.size, " total: ").concat(deletedCount, " freed, ").concat(notDeletedCount, " active)"));
var index = 0;
for (var _c = 0, _d = Array.from(records.entries()); _c < _d.length; _c++) {
var _e = _d[_c], guid = _e[0], record = _e[1];
var ptrStr = "0x".concat(record.ptr.toString(16));
var status_1 = record.deallocated ? " [FREED]" : " [ACTIVE]";
var deallocStr = record.deallocated ? " (freed at ".concat(record.deallocationTimestamp, ")") : "";
console.groupCollapsed("[".concat(index, "] [").concat(record.timestamp, "]: guid=").concat(guid, ", ptr=").concat(ptrStr, ", ").concat(record.size, "bt").concat(status_1).concat(deallocStr));
index++;
if (record.stackTraceJS) {
console.groupCollapsed("JS Stack Trace");
console.log(record.stackTraceJS);
console.groupEnd();
}
console.groupEnd();
}
console.groupEnd();
// Group 2: Non-deleted records (potential leaks)
if (notDeletedRecords.length > 0) {
console.groupCollapsed("Non-Deleted Records (".concat(notDeletedRecords.length, " active allocations, ").concat(notDeallocatedBytes, " bytes)"));
for (var _f = 0, notDeletedRecords_1 = notDeletedRecords; _f < notDeletedRecords_1.length; _f++) {
var item = notDeletedRecords_1[_f];
var ptrStr = "0x".concat(item.record.ptr.toString(16));
console.groupCollapsed("[".concat(item.index, "] [").concat(item.record.timestamp, "]: guid=").concat(item.record.guid, ", ptr=").concat(ptrStr, ", ").concat(item.record.size, "bt [ACTIVE]"));
if (item.record.stackTraceJS) {
console.groupCollapsed("JS Stack Trace");
console.log(item.record.stackTraceJS);
console.groupEnd();
}
console.groupEnd();
}
console.groupEnd();
}
console.groupEnd();
// Reset current batch tracking after logging
this.resetMallocBatch();
};
/**
* Log all historical malloc/free allocations (does not reset)
* Stats are calculated from the allRecords Map (historical)
*/
WasmMemoryDebugHelper.logAllMallocAllocations = function () {
var tracking = this.getTracking();
if (!tracking) {
console.warn("Memory tracking not initialized");
return;
}
var allRecords = tracking.allRecords;
var historicalStats = this.calculateStatsFromMap(allRecords);
// Calculate statistics
var activeCount = 0;
var freedCount = 0;
var totalAllocatedBytes = 0;
var notDeallocatedBytes = 0;
var notDeletedRecords = [];
var idx = 0;
for (var _i = 0, _a = Array.from(allRecords.entries()); _i < _a.length; _i++) {
var _b = _a[_i], record = _b[1];
totalAllocatedBytes += record.size;
if (record.deallocated) {
freedCount++;
}
else {
activeCount++;
notDeallocatedBytes += record.size;
notDeletedRecords.push({ record: record, index: idx });
}
idx++;
}
var allocatedDiff = historicalStats.totalAllocated - historicalStats.totalFreed;
var active = historicalStats.allocCount - historicalStats.deallocCount;
console.groupCollapsed("[malloc/free] Memory Stats - Allocated Diff: ".concat(allocatedDiff, " bytes ") +
"(Allocs: ".concat(historicalStats.allocCount, ", Deallocs: ").concat(historicalStats.deallocCount, ", Active: ").concat(active, ")"));
console.log("[malloc/free] Total Allocated: ".concat(historicalStats.totalAllocated, " bytes, ") +
"Total Freed: ".concat(historicalStats.totalFreed, " bytes, Current: ").concat(allocatedDiff, " bytes"));
console.log("Historical Summary: ".concat(allRecords.size, " total allocations, ").concat(freedCount, " freed, ").concat(activeCount, " active"));
console.log("Memory: ".concat(totalAllocatedBytes, " bytes allocated; ").concat(notDeallocatedBytes, " bytes not deallocated"));
// Group 1: All historical allocations
console.groupCollapsed("All Historical Allocations (".concat(allRecords.size, " total: ").concat(freedCount, " freed, ").concat(activeCount, " active)"));
var index = 0;
for (var _c = 0, _d = Array.from(allRecords.entries()); _c < _d.length; _c++) {
var _e = _d[_c], guid = _e[0], record = _e[1];
var ptrStr = "0x".concat(record.ptr.toString(16));
var status_2 = record.deallocated ? " [FREED]" : " [ACTIVE]";
var deallocStr = record.deallocated ? " (freed at ".concat(record.deallocationTimestamp, ")") : "";
console.groupCollapsed("[".concat(index, "] [").concat(record.timestamp, "]: guid=").concat(guid, ", ptr=").concat(ptrStr, ", ").concat(record.size, "bt").concat(status_2).concat(deallocStr));
index++;
if (record.stackTraceJS) {
console.groupCollapsed("JS Stack Trace");
console.log(record.stackTraceJS);
console.groupEnd();
}
console.groupEnd();
}
console.groupEnd();
// Group 2: Non-deleted records (potential leaks)
if (notDeletedRecords.length > 0) {
console.groupCollapsed("Non-Deleted Records (".concat(notDeletedRecords.length, " active allocations; ").concat(notDeallocatedBytes, " bytes)"));
for (var _f = 0, notDeletedRecords_2 = notDeletedRecords; _f < notDeletedRecords_2.length; _f++) {
var item = notDeletedRecords_2[_f];
var ptrStr = "0x".concat(item.record.ptr.toString(16));
console.groupCollapsed("[".concat(item.index, "] [").concat(item.record.timestamp, "]: guid=").concat(item.record.guid, ", ptr=").concat(ptrStr, ", ").concat(item.record.size, "bt [ACTIVE]"));
if (item.record.stackTraceJS) {
console.groupCollapsed("JS Stack Trace");
console.log(item.record.stackTraceJS);
console.groupEnd();
}
console.groupEnd();
}
console.groupEnd();
}
console.groupEnd();
};
// ============================================================================
// Console Logging Methods - New/Delete
// ============================================================================
/**
* Log current batch new/delete allocations with detailed statistics
* Stats are calculated from the newRecords Map (current batch)
*/
WasmMemoryDebugHelper.logNewDeleteBatch = function () {
var tracking = this.getTracking();
if (!tracking) {
console.warn("Memory tracking not initialized");
return;
}
var records = tracking.newRecords;
var batchStats = this.calculateStatsFromMap(records);
// Calculate batch statistics
var deletedCount = 0;
var notDeletedCount = 0;
var totalAllocatedBytes = 0;
var notDeallocatedBytes = 0;
var notDeletedRecords = [];
var idx = 0;
for (var _i = 0, _a = Array.from(records.entries()); _i < _a.length; _i++) {
var _b = _a[_i], record = _b[1];
totalAllocatedBytes += record.size;
if (record.deallocated) {
deletedCount++;
}
else {
notDeletedCount++;
notDeallocatedBytes += record.size;
notDeletedRecords.push({ record: record, index: idx });
}
idx++;
}
var allocatedDiff = batchStats.totalAllocated - batchStats.totalFreed;
var active = batchStats.allocCount - batchStats.deallocCount;
console.groupCollapsed("[new/delete] Memory Stats - Allocated Diff: ".concat(allocatedDiff, " bytes ") +
"(News: ".concat(batchStats.allocCount, ", Deletes: ").concat(batchStats.deallocCount, ", Active: ").concat(active, ")"));
console.log("[new/delete] Total Allocated: ".concat(batchStats.totalAllocated, " bytes, ") +
"Total Deleted: ".concat(batchStats.totalFreed, " bytes, Current: ").concat(allocatedDiff, " bytes"));
console.log("Batch Summary (new/delete): ".concat(records.size, " allocations, ").concat(deletedCount, " deleted, ").concat(notDeletedCount, " not deleted"));
console.log("Memory: ".concat(totalAllocatedBytes, " bytes allocated, ").concat(notDeallocatedBytes, " bytes not deallocated"));
// Group 1: All batch allocations
console.groupCollapsed("All Batch New/Delete Allocations (".concat(records.size, " total: ").concat(deletedCount, " deleted, ").concat(notDeletedCount, " active)"));
var index = 0;
for (var _c = 0, _d = Array.from(records.entries()); _c < _d.length; _c++) {
var _e = _d[_c], guid = _e[0], record = _e[1];
var ptrStr = "0x".concat(record.ptr.toString(16));
var status_3 = record.deallocated ? " [DELETED]" : " [ACTIVE]";
var deallocStr = record.deallocated ? " (deleted at ".concat(record.deallocationTimestamp, ")") : "";
console.groupCollapsed("[".concat(index, "] [").concat(record.timestamp, "]: guid=").concat(guid, ", ptr=").concat(ptrStr, ", ").concat(record.size, "bt").concat(status_3).concat(deallocStr));
index++;
if (record.stackTraceJS) {
console.groupCollapsed("JS Stack Trace");
console.log(record.stackTraceJS);
console.groupEnd();
}
console.groupEnd();
}
console.groupEnd();
// Group 2: Non-deleted records (potential leaks)
if (notDeletedRecords.length > 0) {
console.groupCollapsed("Non-Deleted Records (".concat(notDeletedRecords.length, " active allocations, ").concat(notDeallocatedBytes, " bytes)"));
for (var _f = 0, notDeletedRecords_3 = notDeletedRecords; _f < notDeletedRecords_3.length; _f++) {
var item = notDeletedRecords_3[_f];
var ptrStr = "0x".concat(item.record.ptr.toString(16));
console.groupCollapsed("[".concat(item.index, "] [").concat(item.record.timestamp, "]: guid=").concat(item.record.guid, ", ptr=").concat(ptrStr, ", ").concat(item.record.size, "bt [ACTIVE]"));
if (item.record.stackTraceJS) {
console.groupCollapsed("JS Stack Trace");
console.log(item.record.stackTraceJS);
console.groupEnd();
}
console.groupEnd();
}
console.groupEnd();
}
console.groupEnd();
// Reset current batch tracking after logging
this.resetNewDeleteBatch();
};
/**
* Log all historical new/delete allocations (does not reset)
* Stats are calculated from the allNewRecords Map (historical)
*/
WasmMemoryDebugHelper.logAllNewDeleteAllocations = function () {
var tracking = this.getTracking();
if (!tracking) {
console.warn("Memory tracking not initialized");
return;
}
var allRecords = tracking.allNewRecords;
var historicalStats = this.calculateStatsFromMap(allRecords);
// Calculate statistics
var activeCount = 0;
var deletedCount = 0;
var totalAllocatedBytes = 0;
var notDeallocatedBytes = 0;
var notDeletedRecords = [];
var idx = 0;
for (var _i = 0, _a = Array.from(allRecords.entries()); _i < _a.length; _i++) {
var _b = _a[_i], record = _b[1];
totalAllocatedBytes += record.size;
if (record.deallocated) {
deletedCount++;
}
else {
activeCount++;
notDeallocatedBytes += record.size;
notDeletedRecords.push({ record: record, index: idx });
}
idx++;
}
var allocatedDiff = historicalStats.totalAllocated - historicalStats.totalFreed;
var active = historicalStats.allocCount - historicalStats.deallocCount;
console.groupCollapsed("[new/delete] Memory Stats - Allocated Diff: ".concat(allocatedDiff, " bytes ") +
"(News: ".concat(historicalStats.allocCount, ", Deletes: ").concat(historicalStats.deallocCount, ", Active: ").concat(active, ")"));
console.log("[new/delete] Total Allocated: ".concat(historicalStats.totalAllocated, " bytes, ") +
"Total Deleted: ".concat(historicalStats.totalFreed, " bytes, Current: ").concat(allocatedDiff, " bytes"));
console.log("Historical Summary (new/delete): ".concat(allRecords.size, " total allocations, ").concat(deletedCount, " deleted, ").concat(activeCount, " active"));
console.log("Memory: ".concat(totalAllocatedBytes, " bytes allocated; ").concat(notDeallocatedBytes, " bytes not deallocated"));
// Group 1: All historical allocations
console.groupCollapsed("All Historical New/Delete Allocations (".concat(allRecords.size, " total: ").concat(deletedCount, " deleted, ").concat(activeCount, " active)"));
var index = 0;
for (var _c = 0, _d = Array.from(allRecords.entries()); _c < _d.length; _c++) {
var _e = _d[_c], guid = _e[0], record = _e[1];
var ptrStr = "0x".concat(record.ptr.toString(16));
var status_4 = record.deallocated ? " [DELETED]" : " [ACTIVE]";
var deallocStr = record.deallocated ? " (deleted at ".concat(record.deallocationTimestamp, ")") : "";
console.groupCollapsed("[".concat(index, "] [").concat(record.timestamp, "]: guid=").concat(guid, ", ptr=").concat(ptrStr, ", ").concat(record.size, "bt").concat(status_4).concat(deallocStr));
index++;
if (record.stackTraceJS) {
console.groupCollapsed("JS Stack Trace");
console.log(record.stackTraceJS);
console.groupEnd();
}
console.groupEnd();
}
console.groupEnd();
// Group 2: Non-deleted records (potential leaks)
if (notDeletedRecords.length > 0) {
console.groupCollapsed("Non-Deleted Records (".concat(notDeletedRecords.length, " active allocations; ").concat(notDeallocatedBytes, " bytes)"));
for (var _f = 0, notDeletedRecords_4 = notDeletedRecords; _f < notDeletedRecords_4.length; _f++) {
var item = notDeletedRecords_4[_f];
var ptrStr = "0x".concat(item.record.ptr.toString(16));
console.groupCollapsed("[".concat(item.index, "] [").concat(item.record.timestamp, "]: guid=").concat(item.record.guid, ", ptr=").concat(ptrStr, ", ").concat(item.record.size, "bt [ACTIVE]"));
if (item.record.stackTraceJS) {
console.groupCollapsed("JS Stack Trace");
console.log(item.record.stackTraceJS);
console.groupEnd();
}
console.groupEnd();
}
console.groupEnd();
}
console.groupEnd();
};
return WasmMemoryDebugHelper;
}());
exports.WasmMemoryDebugHelper = WasmMemoryDebugHelper;