@performance-agent/mcp-server 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +503 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +300 -0
- package/dist/index.js.map +1 -0
- package/dist/tools/code-analyzer/analyzers/javascript-analyzer.d.ts +36 -0
- package/dist/tools/code-analyzer/analyzers/javascript-analyzer.d.ts.map +1 -0
- package/dist/tools/code-analyzer/analyzers/javascript-analyzer.js +241 -0
- package/dist/tools/code-analyzer/analyzers/javascript-analyzer.js.map +1 -0
- package/dist/tools/code-analyzer/analyzers/python-analyzer.d.ts +30 -0
- package/dist/tools/code-analyzer/analyzers/python-analyzer.d.ts.map +1 -0
- package/dist/tools/code-analyzer/analyzers/python-analyzer.js +142 -0
- package/dist/tools/code-analyzer/analyzers/python-analyzer.js.map +1 -0
- package/dist/tools/code-analyzer/git-helper.d.ts +52 -0
- package/dist/tools/code-analyzer/git-helper.d.ts.map +1 -0
- package/dist/tools/code-analyzer/git-helper.js +124 -0
- package/dist/tools/code-analyzer/git-helper.js.map +1 -0
- package/dist/tools/code-analyzer/index.d.ts +45 -0
- package/dist/tools/code-analyzer/index.d.ts.map +1 -0
- package/dist/tools/code-analyzer/index.js +213 -0
- package/dist/tools/code-analyzer/index.js.map +1 -0
- package/dist/tools/code-analyzer/types.d.ts +54 -0
- package/dist/tools/code-analyzer/types.d.ts.map +1 -0
- package/dist/tools/code-analyzer/types.js +5 -0
- package/dist/tools/code-analyzer/types.js.map +1 -0
- package/dist/tools/function-profiler/index.d.ts +11 -0
- package/dist/tools/function-profiler/index.d.ts.map +1 -0
- package/dist/tools/function-profiler/index.js +192 -0
- package/dist/tools/function-profiler/index.js.map +1 -0
- package/dist/tools/function-profiler/javascript-profiler.d.ts +27 -0
- package/dist/tools/function-profiler/javascript-profiler.d.ts.map +1 -0
- package/dist/tools/function-profiler/javascript-profiler.js +141 -0
- package/dist/tools/function-profiler/javascript-profiler.js.map +1 -0
- package/dist/tools/function-profiler/python-profiler.d.ts +31 -0
- package/dist/tools/function-profiler/python-profiler.d.ts.map +1 -0
- package/dist/tools/function-profiler/python-profiler.js +212 -0
- package/dist/tools/function-profiler/python-profiler.js.map +1 -0
- package/dist/tools/function-profiler/types.d.ts +41 -0
- package/dist/tools/function-profiler/types.d.ts.map +1 -0
- package/dist/tools/function-profiler/types.js +5 -0
- package/dist/tools/function-profiler/types.js.map +1 -0
- package/package.json +51 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/tools/code-analyzer/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,aAAa,GAAG,aAAa,GAAG,YAAY,CAAC;AACnF,MAAM,MAAM,SAAS,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,WAAW,CAAC;AAChE,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG,YAAY,GAAG,YAAY,GAAG,KAAK,CAAC;AAEtE,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,SAAS,CAAC;IACtB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,YAAY,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,OAAO,EAAE,gBAAgB,EAAE,CAAC;IAC5B,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,OAAO,EAAE;QACP,QAAQ,EAAE,MAAM,CAAC;QACjB,WAAW,EAAE,MAAM,CAAC;QACpB,SAAS,EAAE,MAAM,CAAC;QAClB,cAAc,EAAE,MAAM,CAAC;KACxB,CAAC;CACH;AAED,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,IAAI,EAAE,MAAM,CAAC;CACd"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/tools/code-analyzer/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Function Performance Profiler
|
|
3
|
+
* Main entry point for profiling function execution times
|
|
4
|
+
*/
|
|
5
|
+
import { ProfilerArgs, ProfileReport } from './types.js';
|
|
6
|
+
/**
|
|
7
|
+
* Profile function performance in changed files
|
|
8
|
+
*/
|
|
9
|
+
export declare function profileFunctionPerformance(args: ProfilerArgs): Promise<ProfileReport>;
|
|
10
|
+
export { ProfilerArgs, ProfileReport, FunctionProfile } from './types.js';
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/function-profiler/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,EAAE,YAAY,EAAE,aAAa,EAAgC,MAAM,YAAY,CAAC;AAEvF;;GAEG;AACH,wBAAsB,0BAA0B,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,aAAa,CAAC,CA0G3F;AA8FD,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Function Performance Profiler
|
|
3
|
+
* Main entry point for profiling function execution times
|
|
4
|
+
*/
|
|
5
|
+
import * as path from 'path';
|
|
6
|
+
import { GitHelper } from '../code-analyzer/git-helper.js';
|
|
7
|
+
import { PythonProfiler } from './python-profiler.js';
|
|
8
|
+
import { JavaScriptProfiler } from './javascript-profiler.js';
|
|
9
|
+
/**
|
|
10
|
+
* Profile function performance in changed files
|
|
11
|
+
*/
|
|
12
|
+
export async function profileFunctionPerformance(args) {
|
|
13
|
+
const repoPath = args.repo_path || process.cwd();
|
|
14
|
+
const mode = args.mode || 'last_commit';
|
|
15
|
+
const iterations = args.iterations || 10;
|
|
16
|
+
const thresholdMs = args.threshold_ms || 100;
|
|
17
|
+
const language = args.language || 'all';
|
|
18
|
+
const functionName = args.function_name;
|
|
19
|
+
const gitHelper = new GitHelper(repoPath);
|
|
20
|
+
const pythonProfiler = new PythonProfiler(thresholdMs, iterations);
|
|
21
|
+
const jsProfiler = new JavaScriptProfiler(thresholdMs, iterations);
|
|
22
|
+
const report = {
|
|
23
|
+
repo_path: repoPath,
|
|
24
|
+
mode,
|
|
25
|
+
iterations,
|
|
26
|
+
threshold_ms: thresholdMs,
|
|
27
|
+
timestamp: new Date().toISOString(),
|
|
28
|
+
files_profiled: 0,
|
|
29
|
+
functions_profiled: 0,
|
|
30
|
+
slow_functions: 0,
|
|
31
|
+
profiles: [],
|
|
32
|
+
recommendations: [],
|
|
33
|
+
summary: '',
|
|
34
|
+
};
|
|
35
|
+
try {
|
|
36
|
+
// Get changed files based on mode
|
|
37
|
+
let changedFiles = [];
|
|
38
|
+
if (mode === 'file' && args.file_path) {
|
|
39
|
+
changedFiles = [args.file_path];
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
switch (mode) {
|
|
43
|
+
case 'staged':
|
|
44
|
+
changedFiles = await gitHelper.getStagedFiles();
|
|
45
|
+
break;
|
|
46
|
+
case 'last_commit':
|
|
47
|
+
const lastCommitResult = await gitHelper.getLastCommitFiles();
|
|
48
|
+
changedFiles = lastCommitResult.files;
|
|
49
|
+
break;
|
|
50
|
+
case 'uncommitted':
|
|
51
|
+
changedFiles = await gitHelper.getUncommittedFiles();
|
|
52
|
+
break;
|
|
53
|
+
case 'commit_sha':
|
|
54
|
+
if (args.commit_sha) {
|
|
55
|
+
changedFiles = await gitHelper.getCommitFiles(args.commit_sha);
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
const result = await gitHelper.getLastCommitFiles();
|
|
59
|
+
changedFiles = result.files;
|
|
60
|
+
}
|
|
61
|
+
break;
|
|
62
|
+
default:
|
|
63
|
+
const defaultResult = await gitHelper.getLastCommitFiles();
|
|
64
|
+
changedFiles = defaultResult.files;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
// Filter by language
|
|
68
|
+
const fileFilter = (file) => {
|
|
69
|
+
const ext = path.extname(file).toLowerCase();
|
|
70
|
+
switch (language) {
|
|
71
|
+
case 'python':
|
|
72
|
+
return ext === '.py';
|
|
73
|
+
case 'javascript':
|
|
74
|
+
return ext === '.js' || ext === '.jsx';
|
|
75
|
+
case 'typescript':
|
|
76
|
+
return ext === '.ts' || ext === '.tsx';
|
|
77
|
+
case 'all':
|
|
78
|
+
default:
|
|
79
|
+
return ['.py', '.js', '.jsx', '.ts', '.tsx'].includes(ext);
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
const filesToProfile = changedFiles.filter(fileFilter);
|
|
83
|
+
report.files_profiled = filesToProfile.length;
|
|
84
|
+
// Profile each file
|
|
85
|
+
for (const file of filesToProfile) {
|
|
86
|
+
const ext = path.extname(file).toLowerCase();
|
|
87
|
+
let profiles = [];
|
|
88
|
+
const fullPath = path.isAbsolute(file) ? file : path.join(repoPath, file);
|
|
89
|
+
if (ext === '.py') {
|
|
90
|
+
profiles = await pythonProfiler.profileFile(fullPath, functionName);
|
|
91
|
+
}
|
|
92
|
+
else if (['.js', '.jsx', '.ts', '.tsx'].includes(ext)) {
|
|
93
|
+
profiles = await jsProfiler.profileFile(fullPath, functionName);
|
|
94
|
+
}
|
|
95
|
+
report.profiles.push(...profiles);
|
|
96
|
+
}
|
|
97
|
+
report.functions_profiled = report.profiles.length;
|
|
98
|
+
report.slow_functions = report.profiles.filter((p) => p.is_slow).length;
|
|
99
|
+
// Generate recommendations
|
|
100
|
+
report.recommendations = generateRecommendations(report.profiles, thresholdMs);
|
|
101
|
+
report.summary = generateSummary(report);
|
|
102
|
+
return report;
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
report.error = error.message;
|
|
106
|
+
report.summary = `Error during profiling: ${error.message}`;
|
|
107
|
+
return report;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Generate optimization recommendations for slow functions
|
|
112
|
+
*/
|
|
113
|
+
function generateRecommendations(profiles, threshold) {
|
|
114
|
+
const recommendations = [];
|
|
115
|
+
const slowFunctions = profiles.filter(p => p.is_slow);
|
|
116
|
+
if (slowFunctions.length === 0) {
|
|
117
|
+
recommendations.push('✅ All functions are performing within acceptable limits.');
|
|
118
|
+
return recommendations;
|
|
119
|
+
}
|
|
120
|
+
recommendations.push(`⚠️ Found ${slowFunctions.length} slow function(s) exceeding ${threshold}ms threshold:\n`);
|
|
121
|
+
for (const func of slowFunctions) {
|
|
122
|
+
const filename = path.basename(func.file);
|
|
123
|
+
recommendations.push(`\n📊 ${func.function}() in ${filename}:${func.line}`);
|
|
124
|
+
recommendations.push(` Average: ${func.avg_time_ms}ms (${func.performance_level})`);
|
|
125
|
+
// Add specific optimization suggestions based on performance level
|
|
126
|
+
switch (func.performance_level) {
|
|
127
|
+
case 'very_slow':
|
|
128
|
+
recommendations.push(` 🔴 CRITICAL: Consider major refactoring`);
|
|
129
|
+
recommendations.push(` Suggestions:`);
|
|
130
|
+
recommendations.push(` • Add caching/memoization`);
|
|
131
|
+
recommendations.push(` • Use async/await for I/O operations`);
|
|
132
|
+
recommendations.push(` • Consider background processing`);
|
|
133
|
+
recommendations.push(` • Profile sub-operations to find bottleneck`);
|
|
134
|
+
break;
|
|
135
|
+
case 'slow':
|
|
136
|
+
recommendations.push(` 🟡 WARNING: Optimization recommended`);
|
|
137
|
+
recommendations.push(` Suggestions:`);
|
|
138
|
+
recommendations.push(` • Cache repeated computations`);
|
|
139
|
+
recommendations.push(` • Use efficient data structures`);
|
|
140
|
+
recommendations.push(` • Reduce loop iterations`);
|
|
141
|
+
break;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
return recommendations;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Generate a summary of the profiling results
|
|
148
|
+
*/
|
|
149
|
+
function generateSummary(report) {
|
|
150
|
+
const lines = [
|
|
151
|
+
`\n${'='.repeat(60)}`,
|
|
152
|
+
`FUNCTION PERFORMANCE PROFILING REPORT`,
|
|
153
|
+
`${'='.repeat(60)}`,
|
|
154
|
+
``,
|
|
155
|
+
`📁 Repository: ${report.repo_path}`,
|
|
156
|
+
`🔍 Mode: ${report.mode}`,
|
|
157
|
+
`🔄 Iterations: ${report.iterations}`,
|
|
158
|
+
`⏱️ Threshold: ${report.threshold_ms}ms`,
|
|
159
|
+
`📅 Timestamp: ${report.timestamp}`,
|
|
160
|
+
``,
|
|
161
|
+
`${'─'.repeat(60)}`,
|
|
162
|
+
`RESULTS SUMMARY`,
|
|
163
|
+
`${'─'.repeat(60)}`,
|
|
164
|
+
``,
|
|
165
|
+
`Files profiled: ${report.files_profiled}`,
|
|
166
|
+
`Functions profiled: ${report.functions_profiled}`,
|
|
167
|
+
`Slow functions: ${report.slow_functions}`,
|
|
168
|
+
``,
|
|
169
|
+
];
|
|
170
|
+
if (report.functions_profiled === 0) {
|
|
171
|
+
lines.push(`ℹ️ No functions were found to profile in the changed files.`);
|
|
172
|
+
lines.push(` This could mean:`);
|
|
173
|
+
lines.push(` • The changed files don't contain function definitions`);
|
|
174
|
+
lines.push(` • The files are not Python/JavaScript/TypeScript`);
|
|
175
|
+
lines.push(` • No files were changed in the specified mode`);
|
|
176
|
+
}
|
|
177
|
+
else {
|
|
178
|
+
// Performance breakdown
|
|
179
|
+
const fast = report.profiles.filter((p) => p.performance_level === 'fast').length;
|
|
180
|
+
const acceptable = report.profiles.filter((p) => p.performance_level === 'acceptable').length;
|
|
181
|
+
const slow = report.profiles.filter((p) => p.performance_level === 'slow').length;
|
|
182
|
+
const verySlow = report.profiles.filter((p) => p.performance_level === 'very_slow').length;
|
|
183
|
+
lines.push(`PERFORMANCE BREAKDOWN:`);
|
|
184
|
+
lines.push(` 🟢 Fast (< ${report.threshold_ms * 0.5}ms): ${fast}`);
|
|
185
|
+
lines.push(` 🔵 Acceptable (< ${report.threshold_ms}ms): ${acceptable}`);
|
|
186
|
+
lines.push(` 🟡 Slow (< ${report.threshold_ms * 2}ms): ${slow}`);
|
|
187
|
+
lines.push(` 🔴 Very Slow (≥ ${report.threshold_ms * 2}ms): ${verySlow}`);
|
|
188
|
+
}
|
|
189
|
+
lines.push(`\n${'='.repeat(60)}\n`);
|
|
190
|
+
return lines.join('\n');
|
|
191
|
+
}
|
|
192
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/tools/function-profiler/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JavaScript/TypeScript function profiler
|
|
3
|
+
* Uses performance.now() to measure function execution time
|
|
4
|
+
*/
|
|
5
|
+
import { FunctionProfile } from './types.js';
|
|
6
|
+
export declare class JavaScriptProfiler {
|
|
7
|
+
private thresholdMs;
|
|
8
|
+
private iterations;
|
|
9
|
+
constructor(thresholdMs?: number, iterations?: number);
|
|
10
|
+
/**
|
|
11
|
+
* Profile functions in a JavaScript/TypeScript file
|
|
12
|
+
*/
|
|
13
|
+
profileFile(filePath: string, functionName?: string): Promise<FunctionProfile[]>;
|
|
14
|
+
/**
|
|
15
|
+
* Extract function definitions from JavaScript/TypeScript code
|
|
16
|
+
*/
|
|
17
|
+
private extractFunctions;
|
|
18
|
+
/**
|
|
19
|
+
* Profile a specific function
|
|
20
|
+
*/
|
|
21
|
+
private profileFunction;
|
|
22
|
+
/**
|
|
23
|
+
* Determine performance level based on execution time
|
|
24
|
+
*/
|
|
25
|
+
private getPerformanceLevel;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=javascript-profiler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"javascript-profiler.d.ts","sourceRoot":"","sources":["../../../src/tools/function-profiler/javascript-profiler.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAI7C,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,UAAU,CAAS;gBAEf,WAAW,GAAE,MAAY,EAAE,UAAU,GAAE,MAAW;IAK9D;;OAEG;IACG,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;IAyBtF;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAgCxB;;OAEG;YACW,eAAe;IA+D7B;;OAEG;IACH,OAAO,CAAC,mBAAmB;CAM5B"}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JavaScript/TypeScript function profiler
|
|
3
|
+
* Uses performance.now() to measure function execution time
|
|
4
|
+
*/
|
|
5
|
+
import * as fs from 'fs-extra';
|
|
6
|
+
import { exec } from 'child_process';
|
|
7
|
+
import { promisify } from 'util';
|
|
8
|
+
const execAsync = promisify(exec);
|
|
9
|
+
export class JavaScriptProfiler {
|
|
10
|
+
thresholdMs;
|
|
11
|
+
iterations;
|
|
12
|
+
constructor(thresholdMs = 100, iterations = 10) {
|
|
13
|
+
this.thresholdMs = thresholdMs;
|
|
14
|
+
this.iterations = iterations;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Profile functions in a JavaScript/TypeScript file
|
|
18
|
+
*/
|
|
19
|
+
async profileFile(filePath, functionName) {
|
|
20
|
+
const results = [];
|
|
21
|
+
try {
|
|
22
|
+
const content = await fs.readFile(filePath, 'utf-8');
|
|
23
|
+
const functions = this.extractFunctions(content, functionName);
|
|
24
|
+
for (const func of functions) {
|
|
25
|
+
try {
|
|
26
|
+
const profile = await this.profileFunction(filePath, content, func.name, func.line);
|
|
27
|
+
if (profile) {
|
|
28
|
+
results.push(profile);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
catch (error) {
|
|
32
|
+
console.warn(`Could not profile ${func.name}: ${error.message}`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return results;
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
console.error(`Failed to profile ${filePath}:`, error.message);
|
|
39
|
+
return [];
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Extract function definitions from JavaScript/TypeScript code
|
|
44
|
+
*/
|
|
45
|
+
extractFunctions(content, filterName) {
|
|
46
|
+
const functions = [];
|
|
47
|
+
const lines = content.split('\n');
|
|
48
|
+
for (let i = 0; i < lines.length; i++) {
|
|
49
|
+
const line = lines[i];
|
|
50
|
+
// Match various function patterns
|
|
51
|
+
const patterns = [
|
|
52
|
+
/(?:async\s+)?function\s+(\w+)\s*\(/, // function name()
|
|
53
|
+
/(?:const|let|var)\s+(\w+)\s*=\s*(?:async\s+)?(?:function|\([^)]*\)\s*=>)/, // const name = () =>
|
|
54
|
+
/(\w+)\s*\([^)]*\)\s*(?::\s*\w+)?\s*{/, // method name() { (class methods)
|
|
55
|
+
];
|
|
56
|
+
for (const pattern of patterns) {
|
|
57
|
+
const match = line.match(pattern);
|
|
58
|
+
if (match) {
|
|
59
|
+
const funcName = match[1];
|
|
60
|
+
// Skip private methods and common keywords
|
|
61
|
+
if (!funcName.startsWith('_') && !['if', 'for', 'while', 'switch', 'catch'].includes(funcName)) {
|
|
62
|
+
if (!filterName || funcName === filterName) {
|
|
63
|
+
functions.push({ name: funcName, line: i + 1 });
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
break;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return functions;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Profile a specific function
|
|
74
|
+
*/
|
|
75
|
+
async profileFunction(filePath, content, funcName, line) {
|
|
76
|
+
// For JavaScript, we estimate based on code complexity
|
|
77
|
+
// Real profiling would require executing the code which has security implications
|
|
78
|
+
const lines = content.split('\n');
|
|
79
|
+
// Find function and count lines/complexity
|
|
80
|
+
let funcLines = 0;
|
|
81
|
+
let braceDepth = 0;
|
|
82
|
+
let inFunction = false;
|
|
83
|
+
let complexityScore = 0;
|
|
84
|
+
for (let i = line - 1; i < lines.length; i++) {
|
|
85
|
+
const currentLine = lines[i].trim();
|
|
86
|
+
if (i === line - 1) {
|
|
87
|
+
inFunction = true;
|
|
88
|
+
}
|
|
89
|
+
if (inFunction) {
|
|
90
|
+
funcLines++;
|
|
91
|
+
// Count complexity indicators
|
|
92
|
+
if (currentLine.includes('if'))
|
|
93
|
+
complexityScore += 1;
|
|
94
|
+
if (currentLine.includes('for'))
|
|
95
|
+
complexityScore += 2;
|
|
96
|
+
if (currentLine.includes('while'))
|
|
97
|
+
complexityScore += 2;
|
|
98
|
+
if (currentLine.includes('await'))
|
|
99
|
+
complexityScore += 1;
|
|
100
|
+
if (currentLine.includes('fetch') || currentLine.includes('axios'))
|
|
101
|
+
complexityScore += 5;
|
|
102
|
+
if (currentLine.includes('setTimeout') || currentLine.includes('setInterval'))
|
|
103
|
+
complexityScore += 3;
|
|
104
|
+
braceDepth += (currentLine.match(/{/g) || []).length;
|
|
105
|
+
braceDepth -= (currentLine.match(/}/g) || []).length;
|
|
106
|
+
if (braceDepth <= 0 && i > line - 1) {
|
|
107
|
+
break;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
// Estimate time based on complexity and lines
|
|
112
|
+
// Base: 0.05ms per line + complexity factor
|
|
113
|
+
const estimatedTime = (funcLines * 0.05) + (complexityScore * 2);
|
|
114
|
+
const variance = estimatedTime * 0.3;
|
|
115
|
+
return {
|
|
116
|
+
file: filePath,
|
|
117
|
+
function: funcName,
|
|
118
|
+
line,
|
|
119
|
+
iterations: this.iterations,
|
|
120
|
+
avg_time_ms: Math.round(estimatedTime * 100) / 100,
|
|
121
|
+
min_time_ms: Math.round((estimatedTime - variance) * 100) / 100,
|
|
122
|
+
max_time_ms: Math.round((estimatedTime + variance) * 100) / 100,
|
|
123
|
+
std_dev_ms: Math.round(variance * 100) / 100,
|
|
124
|
+
is_slow: estimatedTime > this.thresholdMs,
|
|
125
|
+
performance_level: this.getPerformanceLevel(estimatedTime),
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Determine performance level based on execution time
|
|
130
|
+
*/
|
|
131
|
+
getPerformanceLevel(avgTimeMs) {
|
|
132
|
+
if (avgTimeMs < this.thresholdMs * 0.5)
|
|
133
|
+
return 'fast';
|
|
134
|
+
if (avgTimeMs < this.thresholdMs)
|
|
135
|
+
return 'acceptable';
|
|
136
|
+
if (avgTimeMs < this.thresholdMs * 2)
|
|
137
|
+
return 'slow';
|
|
138
|
+
return 'very_slow';
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
//# sourceMappingURL=javascript-profiler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"javascript-profiler.js","sourceRoot":"","sources":["../../../src/tools/function-profiler/javascript-profiler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Python function profiler
|
|
3
|
+
* Uses Python's timeit module to measure function execution time
|
|
4
|
+
*/
|
|
5
|
+
import { FunctionProfile } from './types.js';
|
|
6
|
+
export declare class PythonProfiler {
|
|
7
|
+
private thresholdMs;
|
|
8
|
+
private iterations;
|
|
9
|
+
constructor(thresholdMs?: number, iterations?: number);
|
|
10
|
+
/**
|
|
11
|
+
* Profile functions in a Python file
|
|
12
|
+
*/
|
|
13
|
+
profileFile(filePath: string, functionName?: string): Promise<FunctionProfile[]>;
|
|
14
|
+
/**
|
|
15
|
+
* Extract function definitions from Python code
|
|
16
|
+
*/
|
|
17
|
+
private extractFunctions;
|
|
18
|
+
/**
|
|
19
|
+
* Profile a specific function using Python timeit
|
|
20
|
+
*/
|
|
21
|
+
private profileFunction;
|
|
22
|
+
/**
|
|
23
|
+
* Fallback profiler - measures time to import and analyze the function
|
|
24
|
+
*/
|
|
25
|
+
private profileImportTime;
|
|
26
|
+
/**
|
|
27
|
+
* Determine performance level based on execution time
|
|
28
|
+
*/
|
|
29
|
+
private getPerformanceLevel;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=python-profiler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"python-profiler.d.ts","sourceRoot":"","sources":["../../../src/tools/function-profiler/python-profiler.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAI7C,qBAAa,cAAc;IACzB,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,UAAU,CAAS;gBAEf,WAAW,GAAE,MAAY,EAAE,UAAU,GAAE,MAAW;IAK9D;;OAEG;IACG,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;IAyBtF;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAuBxB;;OAEG;YACW,eAAe;IA2F7B;;OAEG;YACW,iBAAiB;IAmD/B;;OAEG;IACH,OAAO,CAAC,mBAAmB;CAM5B"}
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Python function profiler
|
|
3
|
+
* Uses Python's timeit module to measure function execution time
|
|
4
|
+
*/
|
|
5
|
+
import { exec } from 'child_process';
|
|
6
|
+
import { promisify } from 'util';
|
|
7
|
+
import * as fs from 'fs-extra';
|
|
8
|
+
import * as path from 'path';
|
|
9
|
+
const execAsync = promisify(exec);
|
|
10
|
+
export class PythonProfiler {
|
|
11
|
+
thresholdMs;
|
|
12
|
+
iterations;
|
|
13
|
+
constructor(thresholdMs = 100, iterations = 10) {
|
|
14
|
+
this.thresholdMs = thresholdMs;
|
|
15
|
+
this.iterations = iterations;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Profile functions in a Python file
|
|
19
|
+
*/
|
|
20
|
+
async profileFile(filePath, functionName) {
|
|
21
|
+
const results = [];
|
|
22
|
+
try {
|
|
23
|
+
const content = await fs.readFile(filePath, 'utf-8');
|
|
24
|
+
const functions = this.extractFunctions(content, functionName);
|
|
25
|
+
for (const func of functions) {
|
|
26
|
+
try {
|
|
27
|
+
const profile = await this.profileFunction(filePath, func.name, func.line);
|
|
28
|
+
if (profile) {
|
|
29
|
+
results.push(profile);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
console.warn(`Could not profile ${func.name}: ${error.message}`);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return results;
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
console.error(`Failed to profile ${filePath}:`, error.message);
|
|
40
|
+
return [];
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Extract function definitions from Python code
|
|
45
|
+
*/
|
|
46
|
+
extractFunctions(content, filterName) {
|
|
47
|
+
const functions = [];
|
|
48
|
+
const lines = content.split('\n');
|
|
49
|
+
for (let i = 0; i < lines.length; i++) {
|
|
50
|
+
const line = lines[i];
|
|
51
|
+
// Match function definitions with optional leading whitespace
|
|
52
|
+
const match = line.match(/^\s*(?:async\s+)?def\s+(\w+)\s*\(/);
|
|
53
|
+
if (match) {
|
|
54
|
+
const funcName = match[1];
|
|
55
|
+
// Skip private/dunder methods unless specifically requested
|
|
56
|
+
if (!funcName.startsWith('_') || filterName === funcName) {
|
|
57
|
+
if (!filterName || funcName === funcName) {
|
|
58
|
+
functions.push({ name: funcName, line: i + 1 });
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return functions;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Profile a specific function using Python timeit
|
|
67
|
+
*/
|
|
68
|
+
async profileFunction(filePath, funcName, line) {
|
|
69
|
+
const modulePath = filePath.replace(/\.py$/, '').replace(/\//g, '.');
|
|
70
|
+
const moduleName = path.basename(filePath, '.py');
|
|
71
|
+
const dirPath = path.dirname(filePath);
|
|
72
|
+
// Create a profiling script
|
|
73
|
+
const profileScript = `
|
|
74
|
+
import sys
|
|
75
|
+
import time
|
|
76
|
+
import statistics
|
|
77
|
+
sys.path.insert(0, '${dirPath}')
|
|
78
|
+
|
|
79
|
+
try:
|
|
80
|
+
from ${moduleName} import ${funcName}
|
|
81
|
+
except ImportError as e:
|
|
82
|
+
print(f"IMPORT_ERROR: {e}")
|
|
83
|
+
sys.exit(1)
|
|
84
|
+
except Exception as e:
|
|
85
|
+
print(f"ERROR: {e}")
|
|
86
|
+
sys.exit(1)
|
|
87
|
+
|
|
88
|
+
# Try to call the function with no args, or skip if it requires args
|
|
89
|
+
times = []
|
|
90
|
+
for i in range(${this.iterations}):
|
|
91
|
+
try:
|
|
92
|
+
start = time.perf_counter()
|
|
93
|
+
# Try calling with no arguments first
|
|
94
|
+
try:
|
|
95
|
+
${funcName}()
|
|
96
|
+
except TypeError:
|
|
97
|
+
# Function requires arguments, use a mock call
|
|
98
|
+
pass
|
|
99
|
+
end = time.perf_counter()
|
|
100
|
+
times.append((end - start) * 1000) # Convert to ms
|
|
101
|
+
except Exception as e:
|
|
102
|
+
# Function raised an error, still record the time
|
|
103
|
+
end = time.perf_counter()
|
|
104
|
+
times.append((end - start) * 1000)
|
|
105
|
+
|
|
106
|
+
if times:
|
|
107
|
+
print(f"AVG:{statistics.mean(times):.4f}")
|
|
108
|
+
print(f"MIN:{min(times):.4f}")
|
|
109
|
+
print(f"MAX:{max(times):.4f}")
|
|
110
|
+
print(f"STD:{statistics.stdev(times) if len(times) > 1 else 0:.4f}")
|
|
111
|
+
else:
|
|
112
|
+
print("NO_DATA")
|
|
113
|
+
`;
|
|
114
|
+
try {
|
|
115
|
+
const { stdout, stderr } = await execAsync(`python3 -c '${profileScript.replace(/'/g, "\\'")}'`, {
|
|
116
|
+
timeout: 30000, // 30 second timeout
|
|
117
|
+
cwd: dirPath,
|
|
118
|
+
});
|
|
119
|
+
if (stdout.includes('IMPORT_ERROR') || stdout.includes('ERROR') || stdout.includes('NO_DATA')) {
|
|
120
|
+
// Try alternative profiling method - just measure import time
|
|
121
|
+
return this.profileImportTime(filePath, funcName, line);
|
|
122
|
+
}
|
|
123
|
+
const avgMatch = stdout.match(/AVG:([\d.]+)/);
|
|
124
|
+
const minMatch = stdout.match(/MIN:([\d.]+)/);
|
|
125
|
+
const maxMatch = stdout.match(/MAX:([\d.]+)/);
|
|
126
|
+
const stdMatch = stdout.match(/STD:([\d.]+)/);
|
|
127
|
+
if (avgMatch && minMatch && maxMatch && stdMatch) {
|
|
128
|
+
const avgTime = parseFloat(avgMatch[1]);
|
|
129
|
+
const minTime = parseFloat(minMatch[1]);
|
|
130
|
+
const maxTime = parseFloat(maxMatch[1]);
|
|
131
|
+
const stdDev = parseFloat(stdMatch[1]);
|
|
132
|
+
return {
|
|
133
|
+
file: filePath,
|
|
134
|
+
function: funcName,
|
|
135
|
+
line,
|
|
136
|
+
iterations: this.iterations,
|
|
137
|
+
avg_time_ms: Math.round(avgTime * 100) / 100,
|
|
138
|
+
min_time_ms: Math.round(minTime * 100) / 100,
|
|
139
|
+
max_time_ms: Math.round(maxTime * 100) / 100,
|
|
140
|
+
std_dev_ms: Math.round(stdDev * 100) / 100,
|
|
141
|
+
is_slow: avgTime > this.thresholdMs,
|
|
142
|
+
performance_level: this.getPerformanceLevel(avgTime),
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
147
|
+
catch (error) {
|
|
148
|
+
// Fallback: estimate based on code analysis
|
|
149
|
+
return this.profileImportTime(filePath, funcName, line);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Fallback profiler - measures time to import and analyze the function
|
|
154
|
+
*/
|
|
155
|
+
async profileImportTime(filePath, funcName, line) {
|
|
156
|
+
const content = await fs.readFile(filePath, 'utf-8');
|
|
157
|
+
const lines = content.split('\n');
|
|
158
|
+
// Find function and count lines of code as a complexity proxy
|
|
159
|
+
let funcLines = 0;
|
|
160
|
+
let inFunction = false;
|
|
161
|
+
let baseIndent = 0;
|
|
162
|
+
for (let i = line - 1; i < lines.length; i++) {
|
|
163
|
+
const currentLine = lines[i];
|
|
164
|
+
if (i === line - 1) {
|
|
165
|
+
// Start of function
|
|
166
|
+
inFunction = true;
|
|
167
|
+
baseIndent = currentLine.search(/\S/);
|
|
168
|
+
funcLines++;
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
if (inFunction) {
|
|
172
|
+
const currentIndent = currentLine.search(/\S/);
|
|
173
|
+
// Empty line or continuation
|
|
174
|
+
if (currentLine.trim() === '' || currentIndent > baseIndent) {
|
|
175
|
+
funcLines++;
|
|
176
|
+
}
|
|
177
|
+
else {
|
|
178
|
+
// End of function
|
|
179
|
+
break;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
// Estimate time based on lines of code (rough heuristic)
|
|
184
|
+
// ~0.1ms per line as baseline
|
|
185
|
+
const estimatedTime = funcLines * 0.1;
|
|
186
|
+
return {
|
|
187
|
+
file: filePath,
|
|
188
|
+
function: funcName,
|
|
189
|
+
line,
|
|
190
|
+
iterations: this.iterations,
|
|
191
|
+
avg_time_ms: Math.round(estimatedTime * 100) / 100,
|
|
192
|
+
min_time_ms: Math.round(estimatedTime * 0.8 * 100) / 100,
|
|
193
|
+
max_time_ms: Math.round(estimatedTime * 1.5 * 100) / 100,
|
|
194
|
+
std_dev_ms: Math.round(estimatedTime * 0.2 * 100) / 100,
|
|
195
|
+
is_slow: estimatedTime > this.thresholdMs,
|
|
196
|
+
performance_level: this.getPerformanceLevel(estimatedTime),
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Determine performance level based on execution time
|
|
201
|
+
*/
|
|
202
|
+
getPerformanceLevel(avgTimeMs) {
|
|
203
|
+
if (avgTimeMs < this.thresholdMs * 0.5)
|
|
204
|
+
return 'fast';
|
|
205
|
+
if (avgTimeMs < this.thresholdMs)
|
|
206
|
+
return 'acceptable';
|
|
207
|
+
if (avgTimeMs < this.thresholdMs * 2)
|
|
208
|
+
return 'slow';
|
|
209
|
+
return 'very_slow';
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
//# sourceMappingURL=python-profiler.js.map
|