1+ // Mock jest and vscode using existing mock structure
2+ global . jest = { fn : ( impl ) => impl || ( ( ) => { } ) } ;
3+
4+ // Use the existing vscode mock pattern
5+ const Module = require ( 'module' ) ;
6+ const originalRequire = Module . prototype . require ;
7+
8+ Module . prototype . require = function ( id ) {
9+ if ( id === 'vscode' ) {
10+ const vscode = require ( './out/test/mocks/vscode.js' ) ;
11+ return vscode . default ;
12+ }
13+ return originalRequire . apply ( this , arguments ) ;
14+ } ;
15+
16+ const { parseTemplate } = require ( './out/parsers/templateParser.js' ) ;
17+ const { isSerilogCall } = require ( './out/utils/serilogDetector.js' ) ;
18+ const { CacheManager } = require ( './out/utils/cacheManager.js' ) ;
19+
20+ function benchmark ( name , iterations , operation ) {
21+ // Warmup
22+ for ( let i = 0 ; i < Math . min ( 1000 , iterations / 10 ) ; i ++ ) {
23+ operation ( ) ;
24+ }
25+
26+ const measurements = [ ] ;
27+ for ( let run = 0 ; run < 10 ; run ++ ) {
28+ const start = process . hrtime . bigint ( ) ;
29+ for ( let i = 0 ; i < iterations ; i ++ ) {
30+ operation ( ) ;
31+ }
32+ const end = process . hrtime . bigint ( ) ;
33+
34+ const totalNs = Number ( end - start ) ;
35+ const avgNs = totalNs / iterations ;
36+ measurements . push ( avgNs ) ;
37+ }
38+
39+ measurements . sort ( ( a , b ) => a - b ) ;
40+ const mean = measurements . reduce ( ( a , b ) => a + b ) / measurements . length ;
41+ const median = measurements [ Math . floor ( measurements . length / 2 ) ] ;
42+
43+ const unit = mean < 1000 ? 'ns' : mean < 1000000 ? 'μs' : 'ms' ;
44+ const divisor = unit === 'ns' ? 1 : unit === 'μs' ? 1000 : 1000000 ;
45+
46+ console . log ( `${ name . padEnd ( 30 ) } | Mean: ${ ( mean / divisor ) . toFixed ( 1 ) . padStart ( 7 ) } ${ unit } | Median: ${ ( median / divisor ) . toFixed ( 1 ) . padStart ( 7 ) } ${ unit } ` ) ;
47+ }
48+
49+ console . log ( 'Serilog Syntax Benchmarks' ) ;
50+ console . log ( '=========================' ) ;
51+ console . log ( ) ;
52+
53+ // Parser Benchmarks
54+ console . log ( 'ParserBenchmarks' ) ;
55+ console . log ( '---------------' ) ;
56+
57+ benchmark ( 'ParseSimpleTemplate' , 100000 , ( ) => {
58+ parseTemplate ( "Simple template with {Property}" ) ;
59+ } ) ;
60+
61+ benchmark ( 'ParseComplexTemplate' , 100000 , ( ) => {
62+ parseTemplate ( "Complex {@User} with {Count:N0} and {Timestamp:yyyy-MM-dd HH:mm:ss}" ) ;
63+ } ) ;
64+
65+ benchmark ( 'ParseMultipleProperties' , 100000 , ( ) => {
66+ parseTemplate ( "Multiple {Prop1} {Prop2} {Prop3} {Prop4} {Prop5}" ) ;
67+ } ) ;
68+
69+ benchmark ( 'ParseAllTemplates' , 10000 , ( ) => {
70+ const templates = [
71+ "Simple template with {Property}" ,
72+ "Complex {@User} with {Count:N0} and {Timestamp:yyyy-MM-dd HH:mm:ss}" ,
73+ "Multiple {Prop1} {Prop2} {Prop3} {Prop4} {Prop5}" ,
74+ "Nested {Outer,10:F2} and {@Inner} with {$String}" ,
75+ "Positional {0} {1} {2} mixed with {Named}" ,
76+ "Verbatim string with {Property1} and {Property2}" ,
77+ "Malformed {Unclosed and {Valid} property" ,
78+ "Empty {} and {Valid} with {@Destructured}"
79+ ] ;
80+ for ( const template of templates ) {
81+ parseTemplate ( template ) ;
82+ }
83+ } ) ;
84+
85+ benchmark ( 'ParseWithErrorRecovery' , 100000 , ( ) => {
86+ parseTemplate ( "Malformed {Unclosed and {Valid} property" ) ;
87+ } ) ;
88+
89+ benchmark ( 'ParseVerbatimString' , 100000 , ( ) => {
90+ parseTemplate ( "Verbatim string with {Property1} and {Property2}" ) ;
91+ } ) ;
92+
93+ console . log ( ) ;
94+
95+ // Cache Benchmarks
96+ console . log ( 'CacheBenchmarks' ) ;
97+ console . log ( '--------------' ) ;
98+
99+ let cache = new CacheManager ( 100 ) ;
100+ let cacheKeys = [ ] ;
101+
102+ for ( let i = 0 ; i < 200 ; i ++ ) {
103+ cacheKeys . push ( `Log.Information("Test {Property${ i } }")` ) ;
104+ }
105+
106+ for ( let i = 0 ; i < 50 ; i ++ ) {
107+ cache . set ( cacheKeys [ i ] , i % 2 === 0 ) ;
108+ }
109+
110+ benchmark ( 'CacheHitPerformance' , 50000 , ( ) => {
111+ for ( let i = 0 ; i < 50 ; i ++ ) {
112+ cache . get ( cacheKeys [ i ] ) ;
113+ }
114+ } ) ;
115+
116+ benchmark ( 'CacheMissPerformance' , 50000 , ( ) => {
117+ for ( let i = 150 ; i < 200 ; i ++ ) {
118+ cache . get ( cacheKeys [ i ] ) ;
119+ }
120+ } ) ;
121+
122+ benchmark ( 'CacheAddPerformance' , 10000 , ( ) => {
123+ const localCache = new CacheManager ( 100 ) ;
124+ for ( let i = 0 ; i < 100 ; i ++ ) {
125+ localCache . set ( cacheKeys [ i ] , true ) ;
126+ }
127+ } ) ;
128+
129+ benchmark ( 'CacheEvictionPerformance' , 5000 , ( ) => {
130+ const localCache = new CacheManager ( 50 ) ;
131+ for ( let i = 0 ; i < 100 ; i ++ ) {
132+ localCache . set ( cacheKeys [ i ] , true ) ;
133+ }
134+ } ) ;
135+
136+ benchmark ( 'CacheMixedOperations' , 1000 , ( ) => {
137+ const localCache = new CacheManager ( 100 ) ;
138+ for ( let i = 0 ; i < 200 ; i ++ ) {
139+ const key = cacheKeys [ i % cacheKeys . length ] ;
140+ if ( ! localCache . get ( key ) ) {
141+ localCache . set ( key , i % 2 === 0 ) ;
142+ }
143+ }
144+ } ) ;
145+
146+ console . log ( ) ;
147+
148+ // Call Detector Benchmarks
149+ console . log ( 'CallDetectorBenchmarks' ) ;
150+ console . log ( '---------------------' ) ;
151+
152+ const serilogLines = [
153+ "_logger.LogInformation(\"User {UserId} logged in\", userId);" ,
154+ "Log.Information(\"Processing {Count} items\", count);" ,
155+ "_logger.LogError(ex, \"Failed to process {ItemId}\", id);" ,
156+ "logger.BeginScope(\"Operation {OperationId}\", opId);" ,
157+ ".WriteTo.Console(outputTemplate: \"[{Timestamp}] {Message}\")"
158+ ] ;
159+
160+ const nonSerilogLines = [
161+ "Console.WriteLine(\"Hello World\");" ,
162+ "var result = ProcessData(input);" ,
163+ "if (condition) { return true; }" ,
164+ "// This is a comment about logging" ,
165+ "string message = \"User logged in\";"
166+ ] ;
167+
168+ const mixedLines = [ ] ;
169+ for ( let i = 0 ; i < 100 ; i ++ ) {
170+ if ( i % 3 === 0 ) {
171+ mixedLines . push ( serilogLines [ i % serilogLines . length ] ) ;
172+ } else {
173+ mixedLines . push ( nonSerilogLines [ i % nonSerilogLines . length ] ) ;
174+ }
175+ }
176+
177+ benchmark ( 'DetectSerilogCalls' , 50000 , ( ) => {
178+ for ( const line of serilogLines ) {
179+ isSerilogCall ( line ) ;
180+ }
181+ } ) ;
182+
183+ benchmark ( 'DetectNonSerilogCalls' , 50000 , ( ) => {
184+ for ( const line of nonSerilogLines ) {
185+ isSerilogCall ( line ) ;
186+ }
187+ } ) ;
188+
189+ benchmark ( 'DetectMixedCalls' , 5000 , ( ) => {
190+ for ( const line of mixedLines ) {
191+ isSerilogCall ( line ) ;
192+ }
193+ } ) ;
194+
195+ console . log ( ) ;
196+ console . log ( 'Benchmark completed' ) ;
0 commit comments