MODULE BenchSyntaxHighlighter; (** AUTHOR "staubesv"; PURPOSE "Benchmarks for SyntaxHighlighter"; *) IMPORT Streams, Commands, Options, Dates, Strings, Files, Random, Texts, TextUtilities, SyntaxHighlighter; CONST DefaultHighlighterName = "Oberon"; DefaultNofIterations = 1000; PROCEDURE Reader(reader : Texts.TextReader; nofIterations : LONGINT; out : Streams.Writer); VAR char32 : Texts.Char32; startTime, endTime : Dates.DateTime; i : LONGINT; BEGIN ASSERT((reader # NIL) & (nofIterations > 0) & (out # NIL)); out.String("Reading text "); out.Int(nofIterations, 0); out.String(" times ... "); out.Update; startTime := Dates.Now(); FOR i := 1 TO nofIterations DO reader.SetPosition(0); REPEAT reader.ReadCh(char32); UNTIL reader.eot; END; endTime := Dates.Now(); Strings.ShowTimeDifference(startTime, endTime, out); out.Ln; END Reader; PROCEDURE Words(reader : Texts.TextReader; highlighter : SyntaxHighlighter.Highlighter; nofIterations : LONGINT; out : Streams.Writer); VAR char32 : Texts.Char32; style : SyntaxHighlighter.Style; wordEnd, readerPosition, i : LONGINT; startTime, endTime : Dates.DateTime; BEGIN ASSERT((reader # NIL) & (highlighter # NIL) & (nofIterations > 0) & (out # NIL)); out.String("Match words "); out.Int(nofIterations, 0); out.String(" times ... "); out.Update; startTime := Dates.Now(); FOR i := 1 TO nofIterations DO wordEnd := -1; reader.SetPosition(0); REPEAT readerPosition := reader.GetPosition(); reader.ReadCh(char32); IF (readerPosition > wordEnd) & (char32 > 32) THEN style := highlighter.GetWordStyle(reader, readerPosition, wordEnd); reader.SetPosition(readerPosition); reader.ReadCh(char32); END; UNTIL reader.eot; END; endTime := Dates.Now(); Strings.ShowTimeDifference(startTime, endTime, out); out.Ln; END Words; PROCEDURE RebuildRegions(reader : Texts.TextReader; highlighter : SyntaxHighlighter.Highlighter; nofIterations : LONGINT; out : Streams.Writer); VAR state : SyntaxHighlighter.State; startTime, endTime : Dates.DateTime; i : LONGINT; BEGIN ASSERT((reader # NIL) & (highlighter # NIL) & (nofIterations > 0) & (out # NIL)); state := highlighter.GetState(); out.String("Rebuild regions "); out.Int(nofIterations, 0); out.String(" times ... "); out.Update; startTime := Dates.Now(); FOR i := 1 TO nofIterations DO highlighter.RebuildRegions(reader, state); END; endTime := Dates.Now(); Strings.ShowTimeDifference(startTime, endTime, out); out.Ln; END RebuildRegions; PROCEDURE RegionLookup(reader : Texts.TextReader; highlighter : SyntaxHighlighter.Highlighter; nofIterations : LONGINT; out : Streams.Writer); VAR style : SyntaxHighlighter.Style; state : SyntaxHighlighter.State; random : Random.Generator; length, position, start, end, i : LONGINT; startTime, endTime : Dates.DateTime; BEGIN ASSERT((reader # NIL) & (highlighter # NIL) & (nofIterations > 0) & (out # NIL)); state := highlighter.GetState(); NEW(random); length := reader.text.GetLength(); highlighter.RebuildRegions(reader, state); out.String("Region lookup"); out.Int(nofIterations, 0); out.String(" times ... "); out.Update; startTime := Dates.Now(); FOR i := 1 TO nofIterations DO position := random.Dice(length); style := highlighter.GetRegionStyle(position, state, start, end); END; endTime := Dates.Now(); Strings.ShowTimeDifference(startTime, endTime, out); out.Ln; END RegionLookup; PROCEDURE Full(reader : Texts.TextReader; highlighter : SyntaxHighlighter.Highlighter; nofIterations : LONGINT; out : Streams.Writer); VAR char32 : Texts.Char32; style : SyntaxHighlighter.Style; state : SyntaxHighlighter.State; startTime, endTime : Dates.DateTime; readerPosition, regionStart, regionEnd, lastEnd, i : LONGINT; BEGIN ASSERT((reader # NIL) & (highlighter # NIL) & (nofIterations > 0) & (out # NIL)); state := highlighter.GetState(); out.String("Full highlighting "); out.Int(nofIterations, 0); out.String(" times ... "); out.Update; startTime := Dates.Now(); FOR i := 1 TO nofIterations DO reader.SetPosition(0); lastEnd := -1; REPEAT readerPosition := reader.GetPosition(); reader.ReadCh(char32); IF (lastEnd < readerPosition) THEN style := NIL; style := highlighter.GetRegionStyle(readerPosition, state, regionStart, regionEnd); IF (style # NIL) THEN lastEnd := regionEnd; ELSE IF (char32 > 32) THEN style := highlighter.GetWordStyle(reader, readerPosition, lastEnd); reader.SetPosition(readerPosition); reader.ReadCh(char32); END; END; END; UNTIL reader.eot; END; endTime := Dates.Now(); Strings.ShowTimeDifference(startTime, endTime, out); out.Ln; END Full; PROCEDURE Indent(writer : Streams.Writer; width : LONGINT); VAR i : LONGINT; BEGIN FOR i := 1 TO width DO writer.Char(" "); END; END Indent; PROCEDURE Bench*(context : Commands.Context); (** [Options] filename [benchmark] ~ *) VAR filename : Files.FileName; highlighterName, benchmark : ARRAY 64 OF CHAR; nofIterations : LONGINT; options : Options.Options; text : Texts.Text; reader : Texts.TextReader; format : LONGINT; res: WORD; highlighter : SyntaxHighlighter.Highlighter; BEGIN NEW(options); options.Add("h", "highlighter" , Options.String); options.Add("n", "nofIterations", Options.Integer); IF options.Parse(context.arg, context.error) THEN benchmark := ""; context.arg.SkipWhitespace; context.arg.String(filename); context.arg.SkipWhitespace; context.arg.String(benchmark); IF ~options.GetString("highlighter", highlighterName) THEN highlighterName := DefaultHighlighterName; END; IF ~options.GetInteger("nofIterations", nofIterations) THEN nofIterations := DefaultNofIterations; END; IF (nofIterations > 0) THEN highlighter := SyntaxHighlighter.GetHighlighter(highlighterName); IF (highlighter # NIL) THEN NEW(text); TextUtilities.LoadAuto(text, filename, format, res); IF (res = 0) THEN context.out.String(filename); context.out.String(": "); NEW(reader, text); text.AcquireRead; IF (benchmark = "") THEN context.out.Ln; Indent(context.out, 4); Reader(reader, nofIterations, context.out); context.out.Update; Indent(context.out, 4); Words(reader, highlighter, nofIterations, context.out); context.out.Update; Indent(context.out, 4); RebuildRegions(reader, highlighter, nofIterations, context.out); context.out.Update; Indent(context.out, 4); RegionLookup(reader, highlighter, nofIterations, context.out); context.out.Update; Indent(context.out, 4); Full(reader, highlighter, nofIterations, context.out); context.out.Update; ELSIF (benchmark = "reader") THEN Reader(reader, nofIterations, context.out); ELSIF (benchmark = "words") THEN Words(reader, highlighter, nofIterations, context.out); ELSIF (benchmark = "rebuildregions") THEN RebuildRegions(reader, highlighter, nofIterations, context.out); ELSIF (benchmark = "regionlookup") THEN RegionLookup(reader, highlighter, nofIterations, context.out); ELSIF (benchmark = "full") THEN Full(reader, highlighter, nofIterations, context.out); ELSE context.error.String("Unknown benchmark: "); context.error.String(benchmark); context.error.Ln; END; text.ReleaseRead; ELSE context.error.String("Could not open file "); context.error.String(filename); context.error.Ln; END; ELSE context.error.String("Highlighter "); context.error.String(highlighterName); context.error.String(" not found."); context.error.Ln; END; ELSE context.error.String("Parameter error: {nofIterations > 0}!"); context.error.Ln; END; END; END Bench; PROCEDURE TestScanner*(context : Commands.Context); (** [options] filename highlighterName ~ *) VAR options : Options.Options; filename : Files.FileName; highlighterName : ARRAY 64 OF CHAR; highlighter : SyntaxHighlighter.Highlighter; text : Texts.Text; reader : Texts.TextReader; char32 : Texts.Char32; token : SyntaxHighlighter.Token; position, format : LONGINT; res: WORD; BEGIN NEW(options); options.Add("d", "details", Options.Flag); IF options.Parse(context.arg, context.error) THEN filename := ""; context.arg.SkipWhitespace; context.arg.String(filename); highlighterName := ""; context.arg.SkipWhitespace; context.arg.String(highlighterName); highlighter := SyntaxHighlighter.GetHighlighter(highlighterName); IF (highlighter # NIL) THEN NEW(text); TextUtilities.LoadAuto(text, filename, format, res); IF (res = 0) THEN context.out.String("Token chain for file "); context.out.String(filename); context.out.String(":"); context.out.Ln; text.AcquireRead; NEW(reader, text); reader.SetPosition(0); position := 0; reader.ReadCh(char32); REPEAT (* skip whitespace *) WHILE (char32 <= 32) & ~reader.eot DO reader.ReadCh(char32); INC(position); END; IF ~reader.eot THEN ASSERT(char32 > 32); context.out.Ln; context.out.String("Scan "); context.out.Int(position, 0); context.out.Ln; reader.SetPosition(position); highlighter.GetToken(reader, position, token); context.out.String(" -> "); CASE token.type OF |SyntaxHighlighter.Type_Invalid: context.out.String("INV"); |SyntaxHighlighter.Type_Identifier: context.out.String("ID("); context.out.String(token.value); |SyntaxHighlighter.Type_Number: context.out.String("NUM("); context.out.String(token.value); |SyntaxHighlighter.Type_Token: context.out.String("T("); context.out.String(token.value); ELSE context.out.String("UNKNOWN"); END; IF (token.type = SyntaxHighlighter.Type_Identifier) OR (token.type = SyntaxHighlighter.Type_Number) OR (token.type = SyntaxHighlighter.Type_Token) THEN IF options.GetFlag("details") THEN context.out.String(", "); context.out.Int(token.startPosition, 0); context.out.String(".."); context.out.Int(token.endPosition, 0); END; context.out.String(")"); END; IF (token.type # SyntaxHighlighter.Type_Invalid) THEN reader.SetPosition(token.endPosition + 1); position := token.endPosition + 1; ELSE INC(position); END; reader.ReadCh(char32); END; UNTIL reader.eot; text.ReleaseRead; ELSE context.error.String("Could not open file "); context.error.String(filename); context.error.String(", res = "); context.error.Int(res, 0); context.error.Ln; END; ELSE context.error.String("Highlighter "); context.error.String(highlighterName); context.error.String(" not found."); context.error.Ln; END; END; END TestScanner; END BenchSyntaxHighlighter. System.Free BenchSyntaxHighlighter ~ BenchSyntaxHighlighter.Bench Usb.Mod reader ~ BenchSyntaxHighlighter.Bench BIOS.I386.Machine.Mod reader ~ BenchSyntaxHighlighter.Bench Usb.Mod words ~ BenchSyntaxHighlighter.Bench BIOS.I386.Machine.Mod words ~ BenchSyntaxHighlighter.Bench Usb.Mod rebuildregions~ BenchSyntaxHighlighter.Bench BIOS.I386.Machine.Mod rebuildregions ~ BenchSyntaxHighlighter.Bench -n=1000000 Usb.Mod regionlookup~ BenchSyntaxHighlighter.Bench BIOS.I386.Machine.Mod regionlookup ~ BenchSyntaxHighlighter.Bench Usb.Mod full ~ BenchSyntaxHighlighter.Bench BIOS.I386.Machine.Mod full ~ BenchSyntaxHighlighter.Bench Usb.Mod ~ BenchSyntaxHighlighter.Bench BIOS.I386.Machine.Mod ~ Tests: BenchSyntaxHighlighter.TestScanner Test.Mod Oberon ~ BenchSyntaxHighlighter.TestScanner --details Test.Mod Oberon ~ System.DoCommands FSTools.Enumerate *.Mod BenchSyntaxHighlighter.Bench -n=1 <#filename#> ~ FSTools.Enumerate *.XML BenchSyntaxHighlighter.Bench -n=1 <#filename#> ~ FSTools.Enumerate *.TOOL BenchSyntaxHighlighter.Bench -n=1 <#filename#> ~ FSTools.Enumerate *.C BenchSyntaxHighlighter.Bench -n=1 <#filename#> ~ ~