fortify2-js
Version:
MOST POWERFUL JavaScript Security Library! Military-grade cryptography + 19 enhanced object methods + quantum-resistant algorithms + perfect TypeScript support. More powerful than Lodash with built-in security.
233 lines (230 loc) • 8.34 kB
JavaScript
import { performance } from 'perf_hooks';
import { logger } from '../utils/Logger.js';
/**
* Performance Profiler
*
* High-precision performance monitoring system for FastApi.ts optimization.
* Measures performance metrics with minimal overhead (<0.01ms per measurement).
*/
class PerformanceProfiler {
constructor() {
this.metrics = [];
this.activeRequests = new Map();
this.maxMetricsHistory = 10000;
// Measure our own overhead
this.measurementOverhead = this.calibrateMeasurementOverhead();
logger.debug("performance", `Performance measurement overhead: ${this.measurementOverhead.toFixed(4)}ms`);
}
/**
* Start measuring a request
*/
startMeasurement(req) {
const requestId = this.generateRequestId();
const startTime = performance.now();
const metric = {
requestId,
timestamp: Date.now(),
route: req.route?.path || req.path,
method: req.method,
totalTime: startTime, // Store start time temporarily
cacheHit: false,
cacheLayer: "miss",
memoryUsed: process.memoryUsage().heapUsed,
gcTriggered: false,
requestType: "standard", // Default, will be updated
optimizationPath: "none",
targetMet: false,
optimizationGain: 0,
};
this.activeRequests.set(requestId, metric);
return requestId;
}
/**
* Complete measurement
*/
completeMeasurement(requestId, res) {
const metric = this.activeRequests.get(requestId);
if (!metric || !metric.totalTime) {
return null;
}
// Calculate total time
const endTime = performance.now();
const totalTime = endTime - metric.totalTime - this.measurementOverhead;
// Check if target was met
const targetMet = this.checkTargetMet(metric.requestType, totalTime);
// Calculate optimization gain (compared to baseline)
const optimizationGain = this.calculateOptimizationGain(metric.requestType, totalTime);
// Final memory check
const finalMemory = process.memoryUsage().heapUsed;
const memoryDelta = finalMemory - (metric.memoryUsed || 0);
const completedMetric = {
...metric,
totalTime,
memoryUsed: memoryDelta,
targetMet,
optimizationGain,
};
// Store metric
this.storeMetric(completedMetric);
// Clean up
this.activeRequests.delete(requestId);
return completedMetric;
}
/**
* Set request classification
*/
setRequestType(requestId, type, path) {
const metric = this.activeRequests.get(requestId);
if (metric) {
metric.requestType = type;
metric.optimizationPath = path;
}
}
/**
* Mark cache operation
*/
markCacheOperation(requestId, hit, layer, time) {
const metric = this.activeRequests.get(requestId);
if (metric) {
metric.cacheTime = time;
metric.cacheHit = hit;
metric.cacheLayer = layer;
}
}
/**
* Get current performance statistics
*/
getStats() {
if (this.metrics.length === 0) {
return this.getEmptyStats();
}
const recentMetrics = this.metrics.slice(-1000); // Last 1000 requests
const responseTimes = recentMetrics
.map((m) => m.totalTime)
.sort((a, b) => a - b);
const stats = {
totalRequests: this.metrics.length,
// Response time statistics
p50ResponseTime: this.getPercentile(responseTimes, 0.5),
p95ResponseTime: this.getPercentile(responseTimes, 0.95),
p99ResponseTime: this.getPercentile(responseTimes, 0.99),
avgResponseTime: responseTimes.reduce((a, b) => a + b, 0) / responseTimes.length,
// Target achievement
ultraFastTargetRate: this.calculateTargetRate(recentMetrics, "ultra-fast"),
fastTargetRate: this.calculateTargetRate(recentMetrics, "fast"),
// Cache performance
overallCacheHitRate: this.calculateCacheHitRate(recentMetrics),
l1CacheHitRate: this.calculateCacheHitRate(recentMetrics, "L1"),
l2CacheHitRate: this.calculateCacheHitRate(recentMetrics, "L2"),
l3CacheHitRate: this.calculateCacheHitRate(recentMetrics, "L3"),
// Memory performance
avgMemoryUsage: recentMetrics.reduce((sum, m) => sum + m.memoryUsed, 0) /
recentMetrics.length,
gcFrequency: recentMetrics.filter((m) => m.gcTriggered).length /
recentMetrics.length,
// Optimization effectiveness
optimizationSuccessRate: recentMetrics.filter((m) => m.targetMet).length /
recentMetrics.length,
avgOptimizationGain: recentMetrics.reduce((sum, m) => sum + m.optimizationGain, 0) /
recentMetrics.length,
};
return stats;
}
/**
* Get detailed metrics for analysis
*/
getDetailedMetrics(limit = 100) {
return this.metrics.slice(-limit);
}
/**
* Clear metrics history
*/
clearMetrics() {
this.metrics = [];
this.activeRequests.clear();
}
// Private helper methods
generateRequestId() {
return `req_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
}
calibrateMeasurementOverhead() {
const iterations = 1000;
const start = performance.now();
for (let i = 0; i < iterations; i++) {
performance.now();
performance.now();
}
const end = performance.now();
return (end - start) / iterations;
}
checkTargetMet(type, totalTime) {
switch (type) {
case "ultra-fast":
return totalTime <= 1.0;
case "fast":
return totalTime <= 5.0;
case "standard":
return totalTime <= 20.0;
default:
return false;
}
}
calculateOptimizationGain(type, totalTime) {
// Baseline times (before optimization)
const baselines = {
"ultra-fast": 5.0, // Was 5ms, now targeting 1ms
fast: 15.0, // Was 15ms, now targeting 5ms
standard: 50.0, // Was 50ms, now targeting 20ms
};
const baseline = baselines[type];
return Math.max(0, baseline - totalTime);
}
storeMetric(metric) {
this.metrics.push(metric);
// Maintain history limit
if (this.metrics.length > this.maxMetricsHistory) {
this.metrics = this.metrics.slice(-this.maxMetricsHistory);
}
}
getPercentile(sortedArray, percentile) {
const index = Math.ceil(sortedArray.length * percentile) - 1;
return sortedArray[Math.max(0, index)] || 0;
}
calculateTargetRate(metrics, type) {
const typeMetrics = metrics.filter((m) => m.requestType === type);
if (typeMetrics.length === 0)
return 0;
const targetMet = typeMetrics.filter((m) => m.targetMet).length;
return targetMet / typeMetrics.length;
}
calculateCacheHitRate(metrics, layer) {
const relevantMetrics = layer
? metrics.filter((m) => m.cacheLayer === layer)
: metrics;
if (relevantMetrics.length === 0)
return 0;
const hits = relevantMetrics.filter((m) => m.cacheHit).length;
return hits / relevantMetrics.length;
}
getEmptyStats() {
return {
totalRequests: 0,
p50ResponseTime: 0,
p95ResponseTime: 0,
p99ResponseTime: 0,
avgResponseTime: 0,
ultraFastTargetRate: 0,
fastTargetRate: 0,
overallCacheHitRate: 0,
l1CacheHitRate: 0,
l2CacheHitRate: 0,
l3CacheHitRate: 0,
avgMemoryUsage: 0,
gcFrequency: 0,
optimizationSuccessRate: 0,
avgOptimizationGain: 0,
};
}
}
export { PerformanceProfiler };
//# sourceMappingURL=PerformanceProfiler.js.map