Mahabhuta includes performance measurement capabilities to help you identify bottlenecks and optimize DOM processing. This guide covers how to collect metrics, generate reports, and use the data to improve performance.
The performance measurement system allows you to:
Important: When disabled, performance measurement has zero overhead - there are no hidden performance costs.
Enable performance measurement by passing a FilesystemPerfDataStore to processAsync():
const mahabhuta = require('mahabhuta');
const { FilesystemPerfDataStore } = mahabhuta;
// Create a data store that saves metrics to ./metrics directory
const dataStore = new FilesystemPerfDataStore('./metrics');
// Process HTML with metrics collection enabled
const output = await mahabhuta.processAsync(
htmlContent,
metadata,
mahafuncArrays,
dataStore, // Optional: enables metrics collection
'my-document.html' // Optional: document identifier
);
When dataStore is not provided, metrics collection is completely disabled with zero performance overhead.
After collecting metrics, use the CLI to generate performance reports:
# Show top 20 Mahafuncs by total time consumed
npx mahabhuta perf-report total --data-dir ./metrics
# Show top 20 Mahafuncs by average time per invocation
npx mahabhuta perf-report average --data-dir ./metrics
# Show breakdown by MahafuncArray
npx mahabhuta perf-report arrays --data-dir ./metrics
# Show time distribution statistics (min/max/median)
npx mahabhuta perf-report distribution --data-dir ./metrics
# Show all reports combined
npx mahabhuta perf-report all --data-dir ./metrics
# Export as JSON for external analysis
npx mahabhuta perf-report all --data-dir ./metrics --format json > stats.json
# Filter to specific plugin
npx mahabhuta perf-report average --filter "plugin-name"
# Limit to top 10 entries
npx mahabhuta perf-report total --top 10
# Combine options
npx mahabhuta perf-report total --data-dir ./metrics --top 5 --filter "akashacms"
Shows Mahafuncs that consume the most cumulative time across all invocations.
--- Top 20 Mahafuncs by Total Time ---
master > akashacms-builtin
AkStylesheets (ak-stylesheets):
423.12ms total, 150 calls
Use this to identify:
Shows Mahafuncs with the highest average execution time per call.
--- Top 20 Mahafuncs by Average Time ---
master > akashacms-blog
OpenGraphMunger (article.blog-post):
2.08ms avg, 150 calls
Use this to identify:
Shows time consumed by each MahafuncArray (typically plugins).
--- By MahafuncArray ---
master > akashacms-builtin:
1842.30ms total, 12.28ms avg, 150 calls
Use this to identify:
Shows timing variability for each Mahafunc with min/max/median statistics.
--- Time Distribution (Top 20) ---
master > mahabhuta-partials
Partial (partial):
Min: 0.45ms, Max: 15.23ms
Median: 0.96ms, Avg: 1.12ms
301 calls
Use this to identify:
Here's an example of the full report output:
=== Mahabhuta Performance Report ===
Documents processed: 150
Total processing time: 4523.45ms
Average per document: 30.16ms
--- Top 20 Mahafuncs by Total Time ---
master > akashacms-builtin
AkStylesheets (ak-stylesheets):
423.12ms total, 150 calls
master > akashacms-blog
OpenGraphMunger (article.blog-post):
312.45ms total, 150 calls
master > mahabhuta-partials
Partial (partial):
289.33ms total, 301 calls
--- Top 20 Mahafuncs by Average Time ---
master > akashacms-builtin
AkStylesheets (ak-stylesheets):
2.82ms avg, 150 calls
master > akashacms-blog
OpenGraphMunger (article.blog-post):
2.08ms avg, 150 calls
--- By MahafuncArray ---
master > akashacms-builtin:
1842.30ms total, 12.28ms avg, 150 calls
master > akashacms-blog:
892.15ms total, 5.95ms avg, 150 calls
--- Time Distribution (Top 20) ---
master > akashacms-builtin
AkStylesheets (ak-stylesheets):
Min: 1.23ms, Max: 8.45ms
Median: 2.56ms, Avg: 2.82ms
150 calls
You can also access metrics programmatically for custom analysis:
const dataStore = new FilesystemPerfDataStore('./metrics');
// Get aggregated statistics
const stats = await dataStore.getAggregatedStats();
console.log(`Processed ${stats.documentCount} documents`);
console.log(`Average time: ${stats.avgProcessingMs.toFixed(2)}ms`);
// Find slowest Mahafunc
const slowest = stats.byMahafunc
.sort((a, b) => b.totalDurationMs - a.totalDurationMs)[0];
console.log(`Slowest: ${slowest.className} - ${slowest.totalDurationMs.toFixed(2)}ms total`);
// Find Mahafuncs with high variability
for (const mahafunc of stats.byMahafunc) {
const variability = mahafunc.maxDurationMs / mahafunc.medianDurationMs;
if (variability > 3) {
console.log(`High variability in ${mahafunc.className}: ${variability.toFixed(2)}x`);
}
}
// Get all raw metrics
const allMetrics = await dataStore.getAllMetrics();
// Process each document's metrics
for (const metrics of allMetrics) {
console.log(`Document: ${metrics.documentId}`);
console.log(`Total time: ${metrics.totalDurationMs}ms`);
console.log(`Mahafuncs executed: ${metrics.mahafuncTimings.length}`);
}
// Clear metrics when done
await dataStore.clear();
Each document processing creates metrics with the following structure:
{
totalDurationMs: number, // Total time for processAsync()
timestamp: number, // When processing started
documentId?: string, // Optional document identifier
mahafuncTimings: [...], // Timing for each Mahafunc execution
arrayTimings: [...] // Timing for each MahafuncArray
}
{
arrayPath: string[], // Full nesting path, e.g., ["master", "plugin"]
className: string, // Mahafunc class name
mahafuncType: string, // Type: CustomElement, Munger, etc.
selector: string, // CSS selector or element name
durationMs: number, // Execution time in milliseconds
timestamp: number // When execution started
}
After processing multiple documents, you get aggregated statistics:
{
documentCount: number, // Total documents processed
totalProcessingMs: number, // Total time across all documents
avgProcessingMs: number, // Average time per document
byMahafunc: [...], // Per-Mahafunc statistics
byArray: [...] // Per-MahafuncArray statistics
}
Each entry in byMahafunc includes:
invocationCount: Number of times invokedtotalDurationMs: Sum of all execution timesavgDurationMs: Average per invocationminDurationMs: Fastest executionmaxDurationMs: Slowest executionmedianDurationMs: Median execution timeFrom the test suite with real Mahafuncs:
The overhead when enabled comes primarily from:
performance.now())When metrics collection is disabled (no dataStore provided), guard clauses ensure no performance impact:
// Inside Mahabhuta processing
if (processMetrics) {
// Only executed when metrics enabled
const start = performance.now();
// ... do work ...
processMetrics.mahafuncTimings.push({...});
}
This design means:
Follow this systematic approach to optimize performance:
Based on analysis, common optimization opportunities include:
Frequent execution + low time per call:
Infrequent execution + high time per call:
High variability (max >> median):
Many small operations:
// In AkashaCMS configuration
config.mahabhutaConfig = {
enablePerfMetrics: process.env.ENABLE_PERF_METRICS === 'true',
metricsDir: './output/.metrics'
};
// In render pipeline
let perfStore;
if (config.mahabhutaConfig.enablePerfMetrics) {
const { FilesystemPerfDataStore } = require('mahabhuta');
perfStore = new FilesystemPerfDataStore(config.mahabhutaConfig.metricsDir);
}
// During document rendering
const rendered = await mahabhuta.processAsync(
content,
metadata,
mahafuncArrays,
perfStore, // undefined if metrics disabled
documentPath
);
// After build
if (perfStore) {
console.log('Performance metrics collected.');
console.log('Generate reports with:');
console.log(` npx mahabhuta perf-report all --data-dir ${config.mahabhutaConfig.metricsDir}`);
}
You can implement your own storage by extending PerfDataStore:
const { PerfDataStore } = require('mahabhuta');
class DatabasePerfDataStore extends PerfDataStore {
constructor(dbConnection) {
super();
this.db = dbConnection;
}
async recordProcessMetrics(metrics) {
await this.db.insert('perf_metrics', metrics);
}
async getAllMetrics() {
return await this.db.query('SELECT * FROM perf_metrics');
}
async clear() {
await this.db.delete('perf_metrics');
}
async getAggregatedStats() {
// Compute statistics from database
const allMetrics = await this.getAllMetrics();
// ... aggregation logic ...
}
}
Symptoms: No JSON files appear in metrics directory.
Solutions:
dataStore parameter is passed to processAsync()Symptoms: perf-report shows "Documents processed: 0".
Solutions:
--data-dir pathSymptoms: Processing takes significantly longer with metrics.
Expected: 3-7% overhead is normal.
If higher:
Symptoms: Warning messages about invalid JSON.
Solutions:
clear() to remove corrupted files and start freshSymptoms: High memory usage during metrics collection.
Notes:
Solutions:
Mahabhuta tracks the full path through nested MahafuncArrays:
// If you have nested arrays:
master
└─> akashacms-builtin
└─> nested-plugin
└─> deep-array
// Metrics will show:
arrayPath: ["master", "akashacms-builtin", "nested-plugin", "deep-array"]
This allows you to see exactly where time is spent in complex plugin hierarchies.
Mahabhuta uses performance.now() for microsecond-level precision:
const start = performance.now(); // e.g., 1234567.890123
// ... execute Mahafunc ...
const end = performance.now(); // e.g., 1234570.234567
const duration = end - start; // e.g., 2.344444 ms
This precision allows accurate measurement even for very fast operations.
Use filters effectively to narrow analysis:
# Find all Mahafuncs in a specific plugin
npx mahabhuta perf-report total --filter "akashacms-builtin"
# Find nested arrays
npx mahabhuta perf-report arrays --filter "nested"
# Combine with top limit for focused view
npx mahabhuta perf-report average --filter "blog" --top 5
Export metrics to JSON for custom analysis:
npx mahabhuta perf-report all --format json > stats.json
Then analyze with external tools:
const stats = require('./stats.json');
// Find Mahafuncs with high variance
const highVariance = stats.distribution
.filter(m => m.max / m.median > 5)
.sort((a, b) => b.max - a.max);
console.log('High variance Mahafuncs:', highVariance);
Performance measurement in Mahabhuta provides:
Use performance measurement to:
For more technical details, see these files in the repository:
AI/Performance/PERFORMANCE-USAGE.md
AI/Performance/PERFORMANCE-MEASUREMENTS.mdAGENTS.md in the Performance Section