2017-11-21 14:19 GMT+01:00 Nicolas Cellier <nicolas.cellier.aka.nice@gmail.com >:If I rewrite self class compiler evaluate: the test times out.The test was naively written with Compiler evaluate: and was using the legacy Compiler.������ (ArbitraryPrecisionFloat readFrom: '1.123' readStream numBits: 10)I have an ArbitraryPrecisionFloatTests doing an exhaustive test for printing and reevaluating all positve half precision float.That's about 2^15 or approximately 32k loop which evaluate snippets likeLet's see what increase is necessary:������ [ ArbitraryPrecisionFloatTest new testPrintAndEvaluate�� ] timeToRun.������ -> 3s with legacy Compiler������ -> 14s with OpalCompilerIt's not unexpected that intermediate representation (IR) reification has a cost, but here the 4.5x is a bit too much...This test did account for 1/4 of total test duration already (3s out of 12s).With Opal, the total test duration doubles... (14s out of 23s)So let's analyze the hot spot with:������ MessageTally�� spyOn: [ ArbitraryPrecisionFloatTest new testPrintAndEvaluate�� ].(I didn't use AndreasSystemProfiler becuase outputs seems a bit garbbled, no matter since the primitives do not account that much, a MessageTally will do the job)I first see a hot spot which does not seem that necessary:���������� |������ |24.6% {3447ms} RBMethodNode(RBProgramNode)>>formattedCode From the comments I understand that AST-based stuff requires a pattern (DoIt) and an explicit return (^), but this expensive formatting seems too much for just evaluating. i think that we should change that.Then comes:���������� |������ |20.7% {2902ms} RBMethodNode>>generate:which is split in two halves, ATS->IR and IR->bytecode���� ���� |������ |�� |9.3% {1299ms} RBMethodNode>>generateIR
������������ |������ |�� |�� |11.4% {1596ms} IRMethod>>generate:But then I see this cost a 2nd time which also leave room for progress:���������� |������������������������������ |10.9% {1529ms} RBMethodNode>>generateIR���������� |������������������������������ |�� |12.9% {1814ms} IRMethod>>generate:The first is in RBMethodNode>>generateWithSource, the second in OpalCompiler>>compile Last comes the parse time (sourceCode -> AST)���������� |���������������������������������� 13.2% {1858ms} OpalCompiler>>parseAlong with semantic analysis���������� |���������������������������������� 6.0% {837ms} OpalCompiler>>doSemanticAnalysis ----------------------------------- For comparison, the legacy Compiler decomposes into:���������� |�������������� |61.5% {2223ms} Parser>>parse:class:category:noPattern:context:notifying:ifF ail: which more or less covers parse time + semantic analysis time.That means that Opal does a fair work for this stage.Then, the direct AST->byteCode phase is:�������� |���������� 16.9% {609ms} MethodNode>>generateIR costs almost a 5x on this phase, but we know it's the price to pay for the additional features that it potentially offers. If only we would do it once...And that's all for the legacy one...-------------------------------------- This little exercize shows that a 2x acceleration of OpalCompiler evaluate seems achievable:- simplify the uselessely expensive formatted code- generate bytecodes once, not twiceThen it will be a bit more 2x slower than legacy, which is a better trade for yet to come superior features potentially brought by Opal.It would be interesting to carry same analysis on method compilation��Digging further here is what I find:compile sends generate: and answer a CompiledMethodtranslate sends compile but throw the CompiledMethod away, and just answer the AST.Most senders of translate will also generate: (thus we generate: twice quite often, loosing a 2x factor in compilation).A 2x gain is a huge gain when installing big code bases, especially if the custom is to throw image away and reconstruct.No matter if a bot does the job, it does it for twice many watts and at the end, we're waiting for the bot.However, before changing anything, further clarification is required:translate does one more thing, it catches ReparseAfterSourceEditing and retry compilation (once).So my question: are there some cases when generate: will cause ReparseAfterSourceEditing?
That could happen in generation phase if some byte code limit is exceeded, and an interactive handling corrects code...I did not see any such condition, but code base is huge...