Le 22/02/2015 11:32, Tudor Girba a écrit :
Hi,
On Sat, Feb 21, 2015 at 11:46 PM, Thierry Goubier
<thierry.goubier(a)gmail.com <mailto:thierry.goubier@gmail.com>> wrote:
Le 21/02/2015 23:18, Tudor Girba a écrit :
Hi,
On Sat, Feb 21, 2015 at 11:03 PM, Thierry Goubier
<thierry.goubier(a)gmail.com <mailto:thierry.goubier@gmail.com>
<mailto:thierry.goubier@gmail.__com
<mailto:thierry.goubier@gmail.com>>> wrote:
Hi Doru,
the low hanging fruit is the time needed to create a PP
parser (time
for new).
I still do not see the low hanging fruit. Do you have a concrete
idea of
how to make it faster?
Look at that instantiation code, cache the result.
- Make a copy when you instantiate.
- Recreate / recompute if you execute a method extending the parser
on the resulting object.
- Have a copy parser method which cleanly creates a new instance.
(i.e. summarized as: new should memoize and make a copy of the
memoized version)
This would go against the understood meaning of new which should return
a new instance, not a cached one.
new would clone a pre-existing instance. Just the Self way.
Ok, it's cheating a bit, but it could work (hypothesis: making a copy of
a PP parser instance isn't expensive)
Or look into reflection for making some methods
trigger code
generation, as if parser combinators were written in pragmas :)
I do not understand.
Well, one of the way to look at PetitParser is that it provides an
object-oriented API to the creation of grammars. So, I could very well
write an SmaCC layer which would allow a PetitParser parser design to
generate a Grammar (and maybe keep some of the semantic actions, but
probably not all).
This would be some of the same ideas.
When one writes a method like:
array
^ ${ asParser smalltalkToken , (expression delimitedBy: periodToken)
optional , $} asParser smalltalkToken
One in truth describe two things: a declarative way of writing a grammar
production which in SmaCC would be :
array: "{" (expression ".")* "}" ;
(approximately)
And a resolution (i.e. the code to execute the parse) as well.
One of the idea would be to execute and generate the declarative part of
the method above, so that, when you instantiate the parser, not much is
left to do.
3 times slower in Pharo 4.
And this benchmark does not show any effect linked to long files;
it's only a list of fairly short methods (all Object and Morph methods).
3 times slower comparing what to what? :) Is this the benchmark
comparing a hand-written parser with the PPSmalltalkParser? If yes,
where can we see it the code? If the benchmark is calling new multiple
times, it is not particularly relevant.
I said PetitParser is slower than it used to be (3 times slower).
I used the relative speed of that benchmark to estimate. Ranking is:
RBParser: 400ms
SmaCC StParser: 2100ms
PPSmalltalkParser: 9000ms where I expected it to be, from Lukas numbers,
at 3000ms or less. Hence 3 times slower than it used to be (and 22 times
slower than the hand written parser)
I have a fair idea of where SmaCC is slow, and its totally not where I
expected it. But as it has no asymptotic performance problem, it works
well as a compiler front-end for C, for example.
Bench is simply to run:
ObjectAndMorph do: [ :each | PPSmalltalkParser parse: each ]
(replace with RBParser>>parseMethod:, StParser>>parseMethod: to compare)
With, somewhere, in a global, this:
ObjectAndMorph := Object allMethods , Morph allMethods collect: #sourceCode
to avoid having the sourceCode polluting the profile.
(Note: run times on Spur don't differ much, so no gain there to expect).
Thierry