DIRECTORY Basics, BasicTime USING [GetClockPulses, GMT, Now, Pulses, PulsesToMicroseconds], Commander USING [CommandProc, Register], FS USING [StreamOpen], IO USING [Close, Flush, PutChar, Put, PutF, PutRope, STREAM], PrincOps, Process USING [Detach, GetPriority, MsecToTicks, Pause, SetPriority], Random USING [Init, Choose], Real USING [FixI], Rope, SafeStorage USING [ ReclaimCollectibleObjects, SetCollectionInterval, WaitForCollectorDone], ViewerIO USING [CreateViewerStreams], VMStatistics USING [pageFaults]; GoodTimes: CEDAR MONITOR IMPORTS Basics, BasicTime, Commander, FS, IO, Process, Random, Real, Rope, SafeStorage, ViewerIO, VMStatistics SHARES Rope = BEGIN CARD: TYPE = LONG CARDINAL; Microseconds: TYPE = LONG CARDINAL; PTR: TYPE = LONG POINTER; Pulses: TYPE = BasicTime.Pulses; ROPE: TYPE = Rope.ROPE; STREAM: TYPE = IO.STREAM; NewInlineFetch: PROC [base: ROPE, index: INT] RETURNS [c: CHAR] = TRUSTED INLINE { IF base # NIL THEN { first: CARDINAL _ LOOPHOLE[base, LONG POINTER TO CARDINAL]^; IF first <= 100000B THEN RETURN [QFX[base, index, first]]}; RETURN [Rope.Fetch[base, index]]; }; QFX: PROC [base: ROPE, index: CARDINAL, bound: CARDINAL] RETURNS [CHAR] = TRUSTED MACHINE CODE { PrincOps.zBNDCK; PrincOps.zRSTRL, 4; }; pause: INTEGER _ 0; faults: INT _ 0; pi: REAL _ 3.14159; int: INT _ 31416; card: CARD _ 31416; cardinal: CARDINAL _ 31416; stream: IO.STREAM _ NIL; WritePageMark: PROC = TRUSTED { WriteChar[14C]; WriteChar[15C]; IO.Flush[stream]; }; WriteChar: PROC [c: CHAR] = TRUSTED { IO.PutChar[stream, c]; IF abort THEN {IO.Flush[stream]; ERROR ABORTED}; }; WriteRope: PROC [r: ROPE] = TRUSTED { IF r # NIL THEN { IO.PutRope[stream, r]; }; IF abort THEN {IO.Flush[stream]; ERROR ABORTED}; }; WriteDecimal: PROC [x: INT] = { IO.Put[stream, [integer[x]]]; }; WriteReal: PROC [x: REAL] = { IO.Put[stream, [real[x]]]; }; WriteLine: PROC [s: ROPE] = TRUSTED { WriteRope[s]; WriteChar[15C]; }; Put: PROC [c: CHAR] RETURNS [BOOL] = TRUSTED { IF c = '" THEN WriteChar['\\]; WriteChar[c]; RETURN [FALSE]; }; WriteRopeLit: PROC [r: ROPE] = TRUSTED { WriteChar['"]; WriteRope[r]; WriteChar['"]; }; Show: PROC [r: ROPE, pieces: BOOL _ TRUE, label: ROPE _ NIL] RETURNS [ROPE] = TRUSTED { EachPiece: Rope.PieceActionType = TRUSTED { WriteRope[" "]; WriteChar['"]; [] _ Rope.Map[base, start, len, Put]; WriteChar['"]; WriteChar[15C]; RETURN [FALSE]; }; IF label # NIL THEN {WriteRope[label]; WriteRope[": "]}; WriteRopeLit[r]; WriteChar[15C]; IF pieces THEN [] _ Rope.PieceMap[r, 0, Rope.Size[r], EachPiece]; RETURN [r]}; FillData: TYPE = RECORD [c: CHAR]; FetchProc: Rope.FetchType = { WITH data SELECT FROM rf: REF FillData => RETURN [rf.c]; ENDCASE => ERROR}; MakeFill: PROC [fill: CHAR, size: INT] RETURNS [ROPE] = { RETURN [Rope.MakeRope[NEW[FillData _ [fill]], size, FetchProc]]}; ItsShowTime: PROC [lastMark: Microseconds, msg: ROPE, lead: ROPE _ NIL, useCR: BOOL _ TRUE] = TRUSTED { delta: Microseconds _ GetMark[] - lastMark; places: CARDINAL _ SELECT delta FROM < 100 => 6, < 1000 => 5, < 10000 => 4, < 100000 => 3, < 1000000 => 2, ENDCASE => 1; IF lead # NIL THEN WriteRope[lead]; WriteReal[delta / 1E6]; WriteRope[" secs "]; faults _ VMStatistics.pageFaults - faults; IF faults # 0 THEN { WriteRope["("]; WriteDecimal[faults]; IF faults = 1 THEN WriteRope[" fault) "] ELSE WriteRope[" faults) "]}; WriteRope[msg]; IF useCR THEN WriteChar[15C]; faults _ VMStatistics.pageFaults; }; offset: Microseconds _ 0; lastDelta: Microseconds _ 0; RandomRange: PROC [r: ROPE] RETURNS [start,len: INT] = { size: INT _ r.Size[]; start _ Random.Choose[0, size]; len _ Random.Choose[0, size]; }; ShowNumber: PROC [str: ROPE, number: INT] = { WriteRope[str]; WriteDecimal[number]; }; CountPieces: PROC [r: ROPE] RETURNS [CARDINAL] = { count: CARDINAL _ 0; EachPiece: Rope.PieceActionType = { count _ count + 1; RETURN [FALSE]}; [] _ Rope.PieceMap[r, 0, Rope.MaxLen, EachPiece]; RETURN [count]; }; ShowGC: PROC = { gcMark: Microseconds _ 0; delta: Microseconds _ 0; afterObjs,afterWords: LONG INTEGER _ 0; gcMark _ GetMark[]; IF useTraceAndSweep THEN { [] _ SafeStorage.ReclaimCollectibleObjects[FALSE, TRUE]; [incarnation: , reason: , wordsReclaimed: afterWords, objectsReclaimed: afterObjs] _ SafeStorage.WaitForCollectorDone[]; delta _ GetMark[] - gcMark; ItsShowTime[gcMark, "to collect (trace and sweep)", " "]} ELSE { [] _ SafeStorage.ReclaimCollectibleObjects[FALSE, FALSE]; [incarnation: , reason: , wordsReclaimed: afterWords, objectsReclaimed: afterObjs] _ SafeStorage.WaitForCollectorDone[]; delta _ GetMark[] - gcMark; ItsShowTime[gcMark, "to collect (normal)", " "]}; ShowNumber[" objs collected: ", afterObjs]; ShowNumber[", words collected: ", afterWords]; WriteChar[15C]; IF afterObjs > 0 THEN { adj: INT _ afterWords + afterObjs/2; ShowNumber[" words/obj: ", adj/afterObjs]; IF afterObjs > 0 THEN ShowNumber[", usecs/obj: ", delta/afterObjs]; IF afterObjs > 0 THEN ShowNumber[", usecs/word: ", delta/afterWords]; WriteChar[15C]}; WriteChar[15C]; }; ShowCurrentTime: PROC = TRUSTED { IO.PutF[stream, "At the time, the tone will be %g\n", [time[BasicTime.Now[]]]]; }; GetMark: PROC RETURNS [Microseconds] = TRUSTED { RETURN [BasicTime.PulsesToMicroseconds[BasicTime.GetClockPulses[]]]; }; startTime: BasicTime.GMT; SetStartTime: PROC = TRUSTED { startTime _ BasicTime.Now[]; }; ShowStartTime: PROC = TRUSTED { IO.PutF[stream, "This test started at %g\n", [time[BasicTime.Now[]]]]; }; AppendString: PROC [dst,src: LONG STRING] = TRUSTED { pos: CARDINAL = dst.length; IF src = NIL THEN RETURN; FOR i: CARDINAL IN [0..src.length) DO dst[i+pos] _ src[i]; ENDLOOP; dst.length _ pos + dst.length; }; NullAction: PROC [c: CHAR] RETURNS [BOOL] = {RETURN [FALSE]}; NullProc: PROC = {}; nullProc: PROC _ NullProc; NullEntryProc: ENTRY PROC = {}; nullEntryProc: PROC _ NullEntryProc; dummyREF: REF _ NIL; dummyPtr: LONG POINTER _ NIL; Dummy: TYPE = RECORD [a,b: INT]; DummyLink: TYPE = RECORD[next: Link _ NIL, a,b: CARDINAL]; Link: TYPE = LONG POINTER TO DummyLink; sky: Sky _ Sky[red[4]]; dummyREF1: ROPE _ "dummyREF1"; dummyREF2: ROPE _ "dummyREF2"; dummyPtr1: Link _ LOOPHOLE[dummyREF1]; Sky: TYPE = RECORD [opt: SELECT tag: * FROM red => [red: INT], blue => [blue: INT] ENDCASE]; RandomPiece: PROC [size: NAT] RETURNS [ROPE] = TRUSTED { fill: PROC RETURNS [CHAR] = TRUSTED { nat: NAT _ Random.Choose[40B, 'z-0C]; RETURN [nat + 0C]}; RETURN [Rope.FromProc[Random.Choose[1, size], fill]]}; RandomRope: PROC [maxTotal: NAT _ 0, maxPiece: NAT _ 0] RETURNS [ROPE] = TRUSTED { IF maxTotal = 0 THEN maxTotal _ Random.Choose[1, 1000]; IF maxPiece = 0 OR maxPiece > maxTotal THEN maxPiece _ maxTotal; {size: NAT _ Random.Choose[1, maxTotal]; ref: ROPE _ RandomPiece[maxPiece]; DO rsize: INT _ Rope.Size[ref]; IF rsize >= size THEN { ref _ Rope.Substr[ref, Random.Choose[0, size/2], size]; RETURN [ref]}; IF rsize > 0 THEN rsize _ rsize - 1; ref _ Rope.Replace[ref, Random.Choose[0, rsize], Random.Choose[0, rsize/2], RandomPiece[maxPiece]]; ENDLOOP}; }; CheckReplace: PROC [x: ROPE, start: INT, len: INT, y: ROPE] = TRUSTED { size: INT _ Rope.Size[x]; pos: INT _ start + len; IF start > size THEN start _ size; IF pos < start THEN pos _ start; IF pos > size THEN pos _ size; {left: ROPE _ Rope.Replace[x, start, len, y]; r1: ROPE _ Rope.Substr[x, 0, start]; r2: ROPE _ y; r3: ROPE _ Rope.Substr[x, pos]; c1: ROPE _ Rope.Concat[r1, r2]; right: ROPE _ Rope.Concat[c1, r3]; IF NOT Rope.Equal[left, right] THEN { left _ Show[left, FALSE, " left"]; r1 _ Show[r1, FALSE, " r1"]; r2 _ Show[r2, FALSE, " r2"]; r3 _ Show[r3, FALSE, " r3"]; c1 _ Show[c1, FALSE, " c1"]; right _ Show[right, FALSE, "right"]; SIGNAL CheckReplaceFailed}}; [] _ Rope.VerifyStructure[x]; }; CheckReplaceFailed: SIGNAL = CODE; CauseError: PROC = {ERROR MyError}; MyError: ERROR = CODE; maxBestIndex: NAT = 64; best: ARRAY [0..maxBestIndex] OF REAL _ ALL[0.0]; GopherIt: PROC = TRUSTED { head: LONG STRING _ "Starting major loop ..."; header: ROPE _ "Starting major loop ..."; headSize: CARDINAL _ head.length; dummy: REF _ NIL; start: INT _ 0; c: CHAR _ 0C; operationIndex: NAT _ 0; str: STRING _ [20]; mark: Pulses _ BasicTime.GetClockPulses[]; InitMark: PROC = TRUSTED { mark _ BasicTime.GetClockPulses[]; faults _ VMStatistics.pageFaults; }; TestOne: PROC [inner: PROC, operations: INT _ 100, dummyProcVar: PROC _ NIL] RETURNS [timePerOperation: REAL _ 0.0] = TRUSTED { elapsed: Microseconds _ 0; overhead: Microseconds _ 0; temp: Pulses _ 0; divisor: REAL _ 1.0; IF dummyProcVar = NIL THEN dummyProcVar _ dummyProc; IO.Flush[stream]; dummyProcVar[]; inner[]; Process.SetPriority[Process.GetPriority[]+2]; WHILE elapsed < 1000 DO divisor _ operations; dummyProcVar[]; dummyProcVar[]; temp _ BasicTime.GetClockPulses[]; temp _ BasicTime.GetClockPulses[]; FOR i: INT IN [0..operations) DO dummyProcVar[]; ENDLOOP; temp _ BasicTime.GetClockPulses[] - temp; overhead _ BasicTime.PulsesToMicroseconds[temp]; IF operations > 3 THEN { inner[]; -- do once to get some 1st-time effects over inner[]}; -- do once more to get some 2nd-time effects over temp _ BasicTime.GetClockPulses[]; temp _ BasicTime.GetClockPulses[]; FOR i: INT IN [0..operations) DO inner[]; ENDLOOP; temp _ BasicTime.GetClockPulses[] - temp; elapsed _ BasicTime.PulsesToMicroseconds[temp]; IF elapsed > overhead THEN elapsed _ elapsed - overhead ELSE elapsed _ 0; IF operations > 10000 AND elapsed = 0 THEN ERROR; operations _ operations * 10; ENDLOOP; Process.SetPriority[Process.GetPriority[]-2]; timePerOperation _ LOOPHOLE[elapsed, INT]; timePerOperation _ timePerOperation / divisor; }; Report: PROC [inner: PROC, msg: ROPE, operations: INT _ 100, dummyProcVar: PROC _ NIL] = TRUSTED { faults: INT _ VMStatistics.pageFaults; timePerOperation: REAL _ TestOne[inner, operations, dummyProcVar]; bestTime: REAL _ best[operationIndex]; IF bestTime > timePerOperation THEN best[operationIndex] _ bestTime _ timePerOperation; operationIndex _ operationIndex + 1; faults _ VMStatistics.pageFaults - faults; WriteRope[" "]; WriteReal[timePerOperation]; WriteRope[" usecs ["]; WriteReal[bestTime]; WriteRope["] "]; IF faults > 0 THEN { WriteRope[" ("]; WriteDecimal[faults]; IF faults = 1 THEN WriteRope[" fault) "] ELSE WriteRope[" faults) "]}; WriteLine[msg]; }; dummyProc: PROC = TRUSTED {i: INT _ int; {}}; -- one up-level access dummyProc0: PROC = TRUSTED {}; -- really nothing!!! innerBool1: PROC = TRUSTED { b: BOOL _ TRUE; IF b THEN {b _ TRUE}; }; innerBool2: PROC = TRUSTED { b: BOOL _ FALSE; IF b THEN {b _ TRUE}; }; innerNarrow: PROC = TRUSTED { ref: REF _ header; r: ROPE _ NARROW[ref]; }; innerRefSelect1: PROC = TRUSTED { ref: REF _ header; WITH ref SELECT FROM x: ROPE => {}; ENDCASE => ERROR; }; innerRefSelect2: PROC = TRUSTED { ref: REF _ header; WITH ref SELECT FROM a: ATOM => {}; x: ROPE => {}; ENDCASE => ERROR; }; innerRefSelect3: PROC = TRUSTED { ref: REF _ header; WITH ref SELECT FROM a: ATOM => {}; l: LIST OF REF => {}; x: ROPE => {}; ENDCASE => ERROR; }; innerVariantSelect: PROC = TRUSTED { ptr: LONG POINTER TO Sky _ @sky; WITH x: ptr SELECT FROM red => {}; ENDCASE => ERROR; }; dummyStringFetch: PROC = TRUSTED { str: LONG STRING _ head; index: CARDINAL _ start; -- to allow for narrowing c _ 0C}; innerStringFetch: PROC = TRUSTED { c _ head[start]; }; innerRopeInlineFetch: PROC = TRUSTED { c _ Rope.InlineFetch[header, start]; }; innerNewInlineFetch: PROC = TRUSTED { c _ NewInlineFetch[header, start]; }; innerRopeFetch: PROC = TRUSTED { c _ Rope.Fetch[header, start]; }; innerRopeLength: PROC = TRUSTED { [] _ Rope.Length[header]; }; innerNew: PROC = TRUSTED { dummyREF _ NEW[Dummy]; }; innerDoublePointerAssign: PROC = TRUSTED { dummyPtr _ dummyPtr1; dummyPtr _ NIL; }; innerDoubleRefAssign: PROC = TRUSTED { dummyREF _ dummyREF1; dummyREF _ NIL; }; innerDoubleRefAssign2: PROC = TRUSTED { dummyREF _ dummyREF1; dummyREF _ dummyREF2; }; innerAppendString: PROC = TRUSTED { str.length _ 2; AppendString[str, "bb"]; }; innerRopeConcat: PROC = TRUSTED { [] _ Rope.Concat["aa", "bb"]; }; dummyCardinalAdd: PROC = TRUSTED { card: CARDINAL _ cardinal; card _ cardinal; }; innerCardinalAdd: PROC = TRUSTED { card: CARDINAL _ cardinal; card _ card + cardinal; }; innerCardinalMult: PROC = TRUSTED { card: CARDINAL _ cardinal; card _ card * cardinal; }; innerCardinalDiv: PROC = TRUSTED { card: CARDINAL _ cardinal; card _ cardinal / 100; }; dummyIntAdd: PROC = TRUSTED { li: INT _ int; li _ int; }; innerIntAdd: PROC = TRUSTED { li: INT _ int; li _ li + int; }; innerIntMult: PROC = TRUSTED { li: INT _ int; li _ li * int; }; innerIntDiv: PROC = TRUSTED { li: INT _ int; li _ li / 100; }; dummyCardAdd: PROC = TRUSTED { r: CARD _ card; r _ card; }; innerCardAdd: PROC = TRUSTED { r: CARD _ card; r _ card + card; }; innerCardMult: PROC = TRUSTED { r: CARD _ card; r _ card * card; }; innerCardDiv: PROC = TRUSTED { r: CARD _ card; r _ card / 100; }; dummyRealAdd: PROC = TRUSTED { r: REAL _ pi; r _ pi; }; innerRealAdd: PROC = TRUSTED { r: REAL _ pi; r _ pi + pi; }; innerRealMult: PROC = TRUSTED { r: REAL _ pi; r _ pi * pi; }; innerRealDiv: PROC = TRUSTED { r: REAL _ pi; r _ pi / 100.0; }; innerFix: PROC = TRUSTED { li: INT _ Real.FixI[pi]; }; innerFloat: PROC = TRUSTED { r: REAL _ int; }; innerNullProc: PROC = TRUSTED { NullProc[]; }; innerNullProcVar: PROC = TRUSTED { nullProc[]; }; innerNullEntryProc: PROC = TRUSTED { NullEntryProc[]; }; innerNullEntryProcVar: PROC = TRUSTED { nullEntryProc[]; }; innerProcAndCatch: PROC = TRUSTED { CauseError[! MyError => CONTINUE]; }; innerRandom: PROC = TRUSTED { [] _ Random.Choose[0, 1000]; }; innerWriteToFile: PROC = TRUSTED { st: IO.STREAM _ FS.StreamOpen["GoodTimes.test", create]; FOR i: NAT IN [0..1000) DO j: CARDINAL _ i MOD headSize; IO.PutChar[st, 15C]; ENDLOOP; IO.Close[st]; }; Report[innerBool1, "{b: BOOL _ TRUE; IF b THEN {b _ TRUE}}", 1000, dummyProc0]; Report[innerBool2, "{b: BOOL _ FALSE; IF b THEN {b _ TRUE}}", 1000, dummyProc0]; Report[innerNarrow, "NARROW", 1000]; Report[innerRefSelect1, "REF SELECT", 1000]; Report[innerRefSelect2, "REF SELECT (2nd case)", 1000]; Report[innerRefSelect3, "REF SELECT (3rd case)", 1000]; Report[innerVariantSelect, "variant record SELECT", 1000]; Report[innerStringFetch, "LONG STRING fetch", 1000, dummyStringFetch]; Report[innerRopeInlineFetch, "Rope.InlineFetch (flat rope)", 1000, dummyStringFetch]; Report[innerNewInlineFetch, "NewInlineFetch (flat rope)", 1000, dummyStringFetch]; Report[innerRopeFetch, "Rope.Fetch (flat rope)", 1000, dummyStringFetch]; Report[innerRopeLength, "Rope.Length (flat rope)", 1000]; Report[innerNew, "NEW (4-word object)"]; Report[innerDoublePointerAssign, "double long pointer assign (g1 _ g2; g1 _ NIL)", 10000, dummyProc0]; Report[innerDoubleRefAssign, "double AssignRefs (g1 _ g2; g1 _ NIL)", 1000, dummyProc0]; Report[innerDoubleRefAssign2, "double AssignRefs (g1 _ g2; g1 _ g3)", 1000, dummyProc0]; Report[innerAppendString, "AppendString[str, 'bb'] (str = 'aa')"]; Report[innerRopeConcat, "Rope.Concat['aa', 'bb']"]; Report[innerCardinalAdd, "CARDINAL add (card _ 31416 + 31416)", 10000, dummyCardinalAdd]; Report[innerCardinalMult, "CARDINAL multiply (card _ 31416 * 31416)", 10000, dummyCardinalAdd]; Report[innerCardinalDiv, "CARDINAL divide (card _ 31416 / 100)", 10000, dummyCardinalAdd]; Report[innerIntAdd, "INT add (li _ 31416 + 31416)", 1000, dummyIntAdd]; Report[innerIntMult, "INT multiply (li _ 31416 * 31416)", 1000, dummyIntAdd]; Report[innerIntDiv, "INT divide (li _ 31416 / 100)", 1000, dummyIntAdd]; Report[innerCardAdd, "CARD add (lc _ 31416 + 31416)", 1000, dummyCardAdd]; Report[innerCardMult, "CARD multiply (lc _ 31416 * 31416)", 1000, dummyCardAdd]; Report[innerCardDiv, "CARD divide (lc _ 31416 / 1000)", 1000, dummyCardAdd]; Report[innerRealAdd, "REAL add (li _ 3.1416 + 3.1416)", 1000, dummyRealAdd]; Report[innerRealMult, "REAL multiply (li _ 3.1416 * 3.1416)", 1000, dummyRealAdd]; Report[innerRealDiv, "REAL divide (li _ 3.1416 / 100.0)", 1000, dummyRealAdd]; Report[innerFix, "INT _ REAL", 1000, dummyRealAdd]; Report[innerFloat, "REAL _ INT", 1000, dummyRealAdd]; Report[innerNullProc, "local proc call", 1000, dummyProc0]; Report[innerNullProcVar, "local proc var call", 1000, dummyProc0]; Report[innerNullEntryProc, "local ENTRY proc call", 1000, dummyProc0]; Report[innerNullEntryProcVar, "local ENTRY proc var call", 1000, dummyProc0]; Report[innerProcAndCatch, "proc call & caught ERROR", 100, dummyProc0]; Report[innerRandom, "[] _ Random.Choose[0, 1000]", 100, dummyProc0]; Report[innerWriteToFile, "for FileIO.Open, 1000 IO.PutChars, IO.Close", 10]; WriteRope["Checking consistency of Rope operations... "]; {-- perform some random consistency checks on ropes last: ROPE _ NIL; localMark: Microseconds _ GetMark[]; offset _ 0; FOR i: NAT IN [0..100) DO ref: ROPE _ RandomRope[100, 40]; size: INT _ ref.Size[]; start: INT _ Random.Choose[0,size]; len: INT _ Random.Choose[0,size]; rep: ROPE _ Rope.Substr[ref, Random.Choose[0,size], Random.Choose[0,size]]; ref _ Rope.Replace[ref, start, len, rep]; CheckReplace[ref, start, len, rep]; last _ ref; ENDLOOP; ItsShowTime[localMark, "to check."]; }; ShowGC[]; IF showRopes THEN { WritePageMark[]; FOR i: CARDINAL IN [0..4) DO ShowNumber["Round #", i]; {base: ROPE _ Rope.Concat[header, MakeFill['$, 100]]; replSize: CARDINAL _ Random.Choose[1, 6]; rep: ROPE _ MakeFill['*, replSize]; subMark: Microseconds _ GetMark[]; size: INT _ base.Size[]; FOR j: CARDINAL IN [0..10) DO start _ Random.Choose[0, size]; FOR k: CARDINAL IN [0..100) DO base _ base.Replace[start, 0, rep]; size _ size + replSize; start _ start + replSize; ENDLOOP; ENDLOOP; ItsShowTime[subMark, "for 1000 insertions", ", "]; {leaves,nodes,maxDepth: INT _ 0; [leaves,nodes,maxDepth] _ base.VerifyStructure[]; ShowNumber[" size: ", size]; ShowNumber[", leaves: ", leaves]; ShowNumber[", nodes: ", nodes]; ShowNumber[", depth: ", maxDepth]; {mapTime: Microseconds _ GetMark[]; [] _ Rope.Map[base, 0, Rope.MaxLen, NullAction]; ItsShowTime[mapTime, "to map", "; "]; mapTime _ GetMark[]; base _ base.Balance[]; ItsShowTime[mapTime, "to balance", " ", FALSE]; [leaves,nodes,maxDepth] _ base.VerifyStructure[]; IF size # base.Size[] THEN ERROR; -- Balance failed! ShowNumber[", leaves: ", leaves]; ShowNumber[", nodes: ", nodes]; ShowNumber[", depth: ", maxDepth]; WriteChar[15C]}}}; ENDLOOP; ShowGC[]; }; IF swapTraceAndSweep THEN useTraceAndSweep _ NOT useTraceAndSweep; IF pause >= 0 THEN Process.Pause[Process.MsecToTicks[pause]]; }; InnerRun: PROC [majors: NAT _ 8] = TRUSTED { oldInterval: INT _ SafeStorage.SetCollectionInterval[1000000]; in: STREAM; [in,stream] _ ViewerIO.CreateViewerStreams["GoodTimes.ts", NIL, "GoodTimes.ts", FALSE]; SetStartTime[]; [] _ Random.Init[]; -- setup for full range FOR i: NAT IN [0..maxBestIndex] DO best[i]_ 1.0E9; ENDLOOP; FOR major: NAT IN [0..majors) WHILE gopher DO WriteChar[15C]; ShowStartTime[]; ShowCurrentTime[]; WriteRope["Major loop #"]; WriteDecimal[major]; WriteChar[15C]; GopherIt[]; ShowCurrentTime[]; WritePageMark[]; ENDLOOP; IO.Close[in]; IO.Close[stream]; [] _ SafeStorage.SetCollectionInterval[oldInterval]; }; Run: PROC [majors: NAT _ 8] = { InnerRun[majors ! ABORTED => CONTINUE]; }; Test: PROC [majors: NAT _ 4, fork: BOOL _ TRUE] = TRUSTED { IF fork THEN Process.Detach[FORK Run[majors]] ELSE Run[majors]; }; GoodTimesCommand: Commander.CommandProc = { Test[]; }; gopher: BOOL _ TRUE; -- _ FALSE stops the test at the next clean point abort: BOOL _ FALSE; -- _ TRUE aborts the test at the next output showRopes: BOOL _ TRUE; -- used to determine rope operations printing useTraceAndSweep: BOOL _ FALSE; -- determines use of T&S collector swapTraceAndSweep: BOOL _ FALSE; -- determines alternate use of T&S Commander.Register["GoodTimes", GoodTimesCommand, "Some simple timing tests."]; END. :GoodTimes.mesa, some simple timing tests Copyright c 1984 by Xerox Corporation. All rights reserved. Russ Atkinson, December 20, 1984 3:33:08 am PST make sure that the IO system is pretty quiet try the initial flush of things into our cache higher priority makes our numbers somewhat sharper try to flush the dummyProc into the caches calc the overhead time calc the operation time increase the number of iterations priority is less important now... run some timing tests now try to exercise ropes and the allocator for living with others peacefully Κ˜šœ(™(Jšœ Οmœ1™˜DJ˜J˜—Jšœžœ˜šŸ œžœžœ˜Jšœ˜J˜J˜—šŸ œžœžœ˜JšžœD˜FJ˜J˜—š Ÿ œžœ žœžœžœ˜5Jšœžœ˜Jšžœžœžœžœ˜šžœžœžœž˜%J˜Jšžœ˜—J˜J˜J˜—JšŸ œžœžœžœžœžœžœ˜=J˜JšŸœžœ˜Jšœ žœ ˜JšŸ œžœžœ˜Jšœžœ˜$J˜Jšœ žœžœ˜Jšœ žœžœžœ˜Jšœžœžœžœ˜ Jš œ žœžœžœžœ˜:Jš œžœžœžœžœ ˜'J˜Jšœ žœ˜Jšœ žœ˜Jšœžœ ˜&J˜šœžœžœžœž˜+Jšœ žœ˜Jšœžœ˜Jšžœ˜ J˜—š Ÿ œžœžœžœžœžœ˜8š œžœžœžœžœ˜%Jšœžœ˜%Jšžœ ˜—Jšžœ0˜6J˜—šŸ œžœ žœžœ˜7Jšžœžœžœ˜Jšžœžœ#˜7Jšžœžœžœ˜@šœžœ˜(Jšœžœ˜"šž˜Jšœžœ˜šžœžœ˜J˜7Jšžœ˜—Jšžœ žœ˜$˜J˜J˜J˜—Jšžœ˜ ——J˜J˜—šŸ œžœžœ žœžœžœžœ˜GJšœžœ˜Jšœžœ˜Jšžœžœ˜"Jšžœ žœ ˜ Jšžœ žœ ˜šœžœ"˜-Jšœžœ˜$Jšœžœ˜ Jšœžœ˜Jšœžœ˜Jšœžœ˜"šžœžœžœ˜%Jšœžœ ˜"Jšœžœ ˜Jšœžœ ˜Jšœžœ ˜Jšœžœ ˜Jšœžœ ˜$Jšžœ˜—J˜—J˜J˜—Jšœžœžœ˜"J˜JšŸ œžœžœ ˜#J˜Jšœ žœžœ˜J˜Jšœžœ˜Jš œžœžœžœžœ˜1J˜šŸœžœžœ˜Jšœžœžœ˜.Jšœžœ˜)Jšœ žœ˜!Jšœžœžœ˜Jšœžœ˜Jšœžœ˜ Jšœžœ˜Jšœžœ˜Jšœ*˜*J˜šŸœžœžœ˜Jšœ"˜"Jšœ!˜!J˜J˜—šŸœž˜ Jš œžœžœžœžœ˜>Jšžœžœ žœ˜2J˜J˜J˜Jšœ žœ˜J˜Jšžœžœžœ˜4J˜Jšœ2™2Jšžœ˜J˜Jšœ4™4Jšœ˜J˜J˜Jšœ2™2J˜-J˜šžœž˜J˜J˜Jšœ*™*J˜J˜J˜Jšœ™J˜"J˜"šžœžœžœž˜ J˜Jšžœ˜—J˜)J˜0Jšœ™šžœžœ˜Jšœ Οc,˜5Jšœ  1˜;—J˜"J˜"šžœžœžœž˜ J˜Jšžœ˜—J˜)J˜/Jšžœžœžœ ˜IJšžœžœ žœžœ˜1Jšœ!™!J˜Jšžœ˜J˜—Jšœ!™!J˜-J˜Jšœžœ žœ˜*J˜.J˜J˜—šŸœž˜ Jš œžœžœžœžœžœ˜IJšœžœ˜ Jšœžœ˜&Jšœžœ,˜BJšœ žœ˜&Jšžœžœ4˜WJ˜$Jšœ*˜*J˜/J˜<šžœ žœ˜Jšœ'˜'Jšžœ žœžœ˜F—J˜J˜J˜—Jšœ žœžœžœ  ˜DJ˜Jšœ žœžœ ˜3J˜šœ žœžœ˜Jšœžœžœ˜Jšžœžœžœ˜J˜J˜—šœ žœžœ˜Jšœžœžœ˜Jšžœžœžœ˜J˜J˜—šœ žœžœ˜Jšœžœ ˜Jšœžœžœ˜J˜J˜—šœžœžœ˜!Jšœžœ ˜šžœžœž˜Jšœžœ˜Jšžœžœ˜—J˜J˜—šœžœžœ˜!Jšœžœ ˜šžœžœž˜Jšœžœ˜Jšœžœ˜Jšžœžœ˜—J˜J˜—šœžœžœ˜!Jšœžœ ˜šžœžœž˜Jšœžœ˜Jšœžœžœžœ˜Jšœžœ˜Jšžœžœ˜—J˜J˜—šœžœžœ˜$Jšœžœžœžœ ˜ šžœžœž˜J˜ Jšžœžœ˜—J˜J˜—šœžœžœ˜"Jšœžœžœ˜Jšœžœ  ˜2J˜J˜—šœžœžœ˜"J˜J˜J˜—šœžœžœ˜&J˜$J˜J˜—šœžœžœ˜%J˜"J˜J˜—šœžœžœ˜ J˜J˜J˜—šœžœžœ˜!J˜J˜J˜—šœ žœžœ˜Jšœ žœ˜J˜J˜—šœžœžœ˜*J˜Jšœ žœ˜J˜J˜—šœžœžœ˜&J˜Jšœ žœ˜J˜J˜—šœžœžœ˜'J˜Jšœ˜J˜J˜—šœžœžœ˜#J˜J˜J˜J˜—šœžœžœ˜!J˜J˜J˜—šœžœžœ˜"Jšœžœ ˜Jšœ˜J˜J˜—šœžœžœ˜"Jšœžœ ˜Jšœ˜J˜J˜—šœžœžœ˜#Jšœžœ ˜Jšœ˜J˜J˜—šœžœžœ˜"Jšœžœ ˜Jšœ˜J˜J˜—šœ žœžœ˜Jšœžœ˜J˜ J˜J˜—šœ žœžœ˜Jšœžœ˜J˜J˜J˜—šœžœžœ˜Jšœžœ˜J˜J˜J˜—šœ žœžœ˜Jšœžœ˜J˜J˜J˜—šœžœžœ˜Jšœžœ˜J˜ J˜J˜—šœžœžœ˜Jšœžœ˜J˜J˜J˜—šœžœžœ˜Jšœžœ˜J˜J˜J˜—šœžœžœ˜Jšœžœ˜J˜J˜J˜—šœžœžœ˜Jšœžœ˜ J˜J˜J˜—šœžœžœ˜Jšœžœ˜ J˜ J˜J˜—šœžœžœ˜Jšœžœ˜ J˜ J˜J˜—šœžœžœ˜Jšœžœ˜ J˜J˜J˜—šœ žœžœ˜Jšœžœ˜J˜J˜—šœ žœžœ˜Jšœžœ˜J˜J˜—šœžœžœ˜J˜ J˜J˜—šœžœžœ˜"J˜ J˜J˜—šœžœžœ˜$J˜J˜J˜—šœžœžœ˜'J˜J˜J˜—šœžœžœ˜#Jšœžœ˜"J˜J˜—šœ žœžœ˜J˜J˜J˜—šœžœžœ˜"Jšœžœžœžœ&˜8šžœžœžœ ž˜Jšœžœžœ ˜Jšžœ˜Jšžœ˜—Jšžœ ˜ J˜J˜—Jšœ™J˜˜Jšœžœ˜ Jšœ;žœžœ˜WJ˜Jšœ ˜,šžœžœžœž˜"J˜Jšžœ˜—š žœžœžœ žœž˜-J˜J˜J˜J˜J˜J˜J˜ J˜J˜Jšžœ˜—Jšžœ ˜ Jšžœ˜Jšœ4˜4J˜J˜—šŸœžœ žœ ˜Jšœžœžœ˜'J˜J˜—š Ÿœžœ žœ žœžœžœ˜;Jšœ!™!šžœ˜Jšžœžœ ˜%Jšžœ ˜—J˜J˜—˜+J˜J˜J˜—Jšœžœžœ 1˜GJšœžœžœ ,˜BJšœ žœžœ -˜EJšœžœžœ "˜BJšœžœžœ "˜CJ˜J˜OJ˜Jšžœ˜J˜J˜——…—MΘj‘