Pharo-dev
By thread
pharo-dev@lists.pharo.org
By month
Messages by month
- ----- 2026 -----
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
August 2011
- 104 participants
- 1359 messages
Re: [Pharo-project] [squeak-dev] something we lost with events [was Optimizing RunArray]
by Igor Stasenko
On 3 August 2011 03:00, Nicolas Cellier
<nicolas.cellier.aka.nice(a)gmail.com> wrote:
> I've got the feeling that we've lost one feature:
>
> When you're typing super fast, characters would be inserted several at
> once in a st80 ParagraphEditor
> That typically happens when the displaying or more probably the
> paragraph re-composition is slow.
> The composition/display cycle would occur after first key - giving the
> impression of a non responsive UI - but then consecutive key strokes
> would flow all in once thanks to the while loops in #readKeyboard and
> the buffered Queue of events.
>
> Not the most interactive UI ever, but now things are worse with
> current event implementation.
> There is a one by one keystroke / composition / display, and the
> result is a less responsive UI than polling !
> If you edit a Smalltalk method, no problem, but try editing your 45
> MByte change log just to see how deadly it feels, super fast means 0.2
> Hz on my machine.
>
> I wonder how we could restore this feature...
>
My take is that we should optimize Text data structure for editing.
Because right now, its contents are stored in a single blobby string.
And every time you modifying it,
you have to create new string.. which consuming a lot of energy when
you editing 45Mbytes :)
> Nicolas
>
--
Best regards,
Igor Stasenko AKA sig.
Aug. 3, 2011
Re: [Pharo-project] Disable the debugger
by Igor Stasenko
On 2 August 2011 22:04, Stéphane Ducasse <stephane.ducasse(a)inria.fr> wrote:
> would be nice to have a class responsible for that and that slowly we get a complete system ready for this kind of deployement
>
I think best would be to adopt this with Pharo-Kernel , since it
unloads a lot of stuff and knows how to do that w/o errors.
Maybe adding option(s) there like "strip dev tools" would be nice.
> Stef
>
> On Aug 2, 2011, at 7:06 PM, Mariano Martinez Peck wrote:
>
>> Check in older Pharo images like 1.1.1 all the stuff in #disableProgrammerFacilities
>>
>>
>> disableProgrammerFacilities
>> Â Â "Warning: do not call this lightly! Â It disables all access to menus, debuggers, halos. Â There is no guaranteed return from this, which is to say, you cannot necessarily reenable these things once they are disabled -- you can only use whatever the UI of the current project affords, and you cannot even snapshot -- you can only quit.
>>
>> Â Â Â You can completely reverse the work of this method by calling the dual Preferences method enableProgrammerFacilities, provided you have left yourself leeway to bring about a call to that method.
>> (does not reverse the ToolSet registrations)
>>
>> Â Â To set up a system that will come up in such a state, you have to request the snapshot in the same breath as you disable the programmer facilities. Â To do this, put the following line into the 'do' menu and then evaluate it from that 'do' menu:
>>
>> Â Â Â Â Â Preferences disableProgrammerFacilities.
>>
>> You will be prompted for a new image name under which to save the resulting image."
>> Â Â self deprecated: 'No replacement for now'.
>>
>> Â Â Beeper beep.
>> Â Â (self
>> Â Â Â Â confirm: 'CAUTION!!
>> This is a drastic step!
>> Do you really want to do this?')
>> Â Â Â Â Â Â ifFalse:
>> Â Â Â Â Â Â Â Â [Beeper beep.
>> Â Â Â Â Â Â Â Â ^self inform: 'whew!'].
>> Â Â self disable: #cmdDotEnabled. Â Â "No user-interrupt-into-debugger"
>> Â Â self disable: #editableStringMorphs. "turn off shift-click editing"
>> Â Â ToolSet registeredClasses copy do: [:c | ToolSet unregister: c].
>> Â Â ToolSet default: nil. "unregister and make sure default is nil to really prevent debug windows"
>> Â Â Â Â "also now takes care of low space watcher interrupts"
>> Â Â self compileHardCodedPref: #cmdGesturesEnabled enable: false. Â Â "No halos, etc."
>> Â Â self compileHardCodedPref: #cmdKeysInText enable: false. Â Â "No user commands invokable via cmd-key combos in text editor"
>> Â Â self enable: #noviceMode. Â Â "No control-menu"
>> Â Â self disable: #warnIfNoSourcesFile.
>> Â Â self disable: #warnIfNoChangesFile.
>> Â Â Smalltalk saveAs
>>
>> On Tue, Aug 2, 2011 at 5:59 PM, laurent laffont <laurent.laffont(a)gmail.com> wrote:
>> Hi,
>>
>> is it possible to disable the debugger in a Seaside image for production ?
>>
>> Laurent Laffont - @lolgzs
>>
>> Pharo Smalltalk Screencasts: http://www.pharocasts.com/
>> Blog: http://magaloma.blogspot.com/
>> Developer group: http://cara74.seasidehosting.st
>>
>>
>>
>>
>> --
>> Mariano
>> http://marianopeck.wordpress.com
>>
>
>
>
--
Best regards,
Igor Stasenko AKA sig.
Aug. 3, 2011
[Pharo-project] something we lost with events [was Optimizing RunArray]
by Nicolas Cellier
I've got the feeling that we've lost one feature:
When you're typing super fast, characters would be inserted several at
once in a st80 ParagraphEditor
That typically happens when the displaying or more probably the
paragraph re-composition is slow.
The composition/display cycle would occur after first key - giving the
impression of a non responsive UI - but then consecutive key strokes
would flow all in once thanks to the while loops in #readKeyboard and
the buffered Queue of events.
Not the most interactive UI ever, but now things are worse with
current event implementation.
There is a one by one keystroke / composition / display, and the
result is a less responsive UI than polling !
If you edit a Smalltalk method, no problem, but try editing your 45
MByte change log just to see how deadly it feels, super fast means 0.2
Hz on my machine.
I wonder how we could restore this feature...
Nicolas
Aug. 3, 2011
Re: [Pharo-project] [squeak-dev] Re: Optimizing RunArray
by Nicolas Cellier
One thing that super upset me is that TextEditor is still using the
old selectors #readKeyboard #keyboard #keyboardPeek instead of using
events.
Look #handleInteraction:fromEvent:
It still has this hackish code to transform event driven Morph into
st-80-polling-ParagraphEditor-friendly-Sensor-like
self editor sensor: (KeyboardBuffer new startingEvent: evt).
IMO,
self handleInteraction: [ editor readKeyboard ] fromEvent: evt.
should be replaced with
self handleInteraction: [ editor keyStroke: evt ].
and the hack should be delegated to the TextMorphEditor (ParagraphEditor)
keyStrocke: anEvent
"Pass the event to a polling friendly sensor like so that old st-80
code shall still work"
self sensor: (KeyboardBuffer new startingEvent: evt).
self readKeyboard.
Then TextEditor>>keyStrocke: should dispatchKeyboardEvent: anEvent
with: typeAhead and stop querying a pseudo sensor.
Of course, that means changing a lot of methods in TextEditor (any
method with 'sensor' in source).
But if TextEditor is just a place holder for copying the st-80
ParagraphEditor code and the early Morphic hacks, I just don't see the
point of making such a copy ;)
Nicolas
2011/8/2 Nicolas Cellier <nicolas.cellier.aka.nice(a)gmail.com>:
> I have tried again with huge text (my 45 MByte change log).
> Main contributor seems to be Text composition.
> A marginal gain (2 to 3% when resizing the window) is to remove the
> indirection in TextStopConditions, and replace instance variable stops
> with direct integer slots (variableSubclass)
>
> No guaranty the fileIn of attachment will work, modifying Text
> processing is dangerous...
>
> Nicolas
>
> 2011/8/2 Stéphane Ducasse <stephane.ducasse(a)inria.fr>:
>> Yes I was wondering about the same (for athens too :))
>>
>> Stef
>>
>> On Aug 2, 2011, at 2:16 PM, Igor Stasenko wrote:
>>
>>> Does it impacts the text rendering/processing speed?
>>>
>>>
>>> On 2 August 2011 12:11, Nicolas Cellier
>>> <nicolas.cellier.aka.nice(a)gmail.com> wrote:
>>>> To complete myself, the fast #collect: already exists and is named
>>>> #mapValues: except that it modifies the RunArray in place and also
>>>> won't coalesce...
>>>>
>>>> I also gain a huge factor for #collect:as: be defining this method:
>>>>
>>>> RunArray>>fillFrom: aCollection with: aBlock
>>>> Â Â Â Â "Evaluate aBlock with each of aCollections's elements as the argument.
>>>> Â Â Â Â Collect the resulting values into self. Answer self."
>>>> Â Â Â Â | newRuns newValues lastLength lastValue |
>>>> Â Â Â Â newRuns := (Array new: aCollection size) writeStream.
>>>> Â Â Â Â newValues := (Array new: aCollection size) writeStream.
>>>> Â Â Â Â lastLength := 0.
>>>> Â Â Â Â lastValue := Object new.
>>>> Â Â Â Â aCollection do: [:each |
>>>> Â Â Â Â Â Â Â Â | value |
>>>> Â Â Â Â Â Â Â Â value := aBlock value: each.
>>>> Â Â Â Â Â Â Â Â lastValue = value
>>>> Â Â Â Â Â Â Â Â Â Â Â Â ifTrue: [lastLength := lastLength + 1]
>>>> Â Â Â Â Â Â Â Â Â Â Â Â ifFalse:
>>>> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â [lastLength > 0
>>>> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â ifTrue:
>>>> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â [newRuns nextPut: lastLength.
>>>> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â newValues nextPut: lastValue].
>>>> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â lastLength := 1.
>>>> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â lastValue := value]].
>>>> Â Â Â Â lastLength > 0
>>>> Â Â Â Â Â Â Â Â ifTrue:
>>>> Â Â Â Â Â Â Â Â Â Â Â Â [newRuns nextPut: lastLength.
>>>> Â Â Â Â Â Â Â Â Â Â Â Â newValues nextPut: lastValue].
>>>> Â Â Â Â self setRuns: newRuns contents setValues: newValues contents
>>>>
>>>> [ (Array new: 1000) collect: [:e | 4 atRandom] as: RunArray] bench.
>>>> BEFORE: '25.1 per second.'
>>>> AFTER: Â '1,080 per second.'
>>>>
>>>> It's worth a few lines of code.
>>>>
>>>> Nicolas
>>>>
>>>> 2011/8/2 Nicolas Cellier <nicolas.cellier.aka.nice(a)gmail.com>:
>>>>> I played a bit with RunArray, and found some un-optimized features.
>>>>> First, I don't know why RunArray is an ArrayedCollection. It cannot
>>>>> #add: but it can #addFirst: and #addLast:.
>>>>> It cannot #add:withOccurrences: but it can #addLast:times:. Why
>>>>> inventing new selectors for old behaviours ?
>>>>> These operations will cost a realloc it the last value is different,
>>>>> so the underlying runs/values could better be an OrderedCollection if
>>>>> these operations are used often.
>>>>> A RunArray cannot remove at all.
>>>>> Very weird collection species, I don't like the implementation too much.
>>>>>
>>>>> Then, #do: loops could be far faster. They rely on ArrayedCollection
>>>>> which inlines do: loops with #to:do: and #at:
>>>>> But #at: is not that fast. Scanning the runs and counting elements
>>>>> would result in a n^2 cost.
>>>>> Fortunately there is a cache lastIndex,lastRun,lastOffset to keep a cost n.
>>>>> Nonetheless, all the tests cost, and the loop is suboptimal.
>>>>> Let use see:
>>>>>
>>>>> version 1:
>>>>> RunArray>>fastDo: aBlock
>>>>> Â Â Â Â runs with: values do: [:r :v |
>>>>> Â Â Â Â Â Â Â Â r timesRepeat: [aBlock value: v]].
>>>>>
>>>>> | tmp |
>>>>> tmp := ((Array new: 1000) collect: [:e | 4 atRandom]) as: RunArray.
>>>>> {
>>>>> [ tmp do: [:e |]] bench.
>>>>> [ tmp fastDo: [:e |]] bench.
>>>>> }
>>>>> #('3,220 per second.' '6,290 per second.')
>>>>>
>>>>> But timesRepeat: is slow, it is unoptimized by the compiler and costs
>>>>> a message send.
>>>>> I think we should implement BlockClosure>>repeat: and optimize that
>>>>> call in Compiler.
>>>>> But let's not do it, and rather inline by ourself:
>>>>>
>>>>> version 2:
>>>>> Â Â Â Â runs with: values do: [:r :v |
>>>>> Â Â Â Â Â Â Â Â 1 to: r do: [:i | aBlock value: v]].
>>>>>
>>>>> | tmp |
>>>>> tmp := ((Array new: 1000) collect: [:e | 4 atRandom]) as: RunArray.
>>>>> {
>>>>> [ tmp do: [:e |]] bench.
>>>>> [ tmp do2: [:e |]] bench.
>>>>> }
>>>>> #('3,070 per second.' '25,500 per second.')
>>>>>
>>>>> We can even inline the with:do: loop itself:
>>>>> version 3:
>>>>> Â Â Â Â 1 to: runs size do: [:i |
>>>>> Â Â Â Â Â Â Â Â | r v |
>>>>> Â Â Â Â Â Â Â Â v := values at: i.
>>>>> Â Â Â Â Â Â Â Â r := runs at: i.
>>>>> Â Â Â Â Â Â Â Â [( r := r - 1) >= 0]
>>>>> Â Â Â Â Â Â Â Â Â Â Â Â whileTrue: [aBlock value: v]].
>>>>>
>>>>> | tmp |
>>>>> tmp := ((Array new: 1000) collect: [:e | 4 atRandom]) as: RunArray.
>>>>> {
>>>>> [ tmp do: [:e |]] bench.
>>>>> [ tmp do2: [:e |]] bench.
>>>>> }
>>>>> #('3,370 per second.' '32,200 per second.')
>>>>>
>>>>> Now the operation I wanted to use was reverseDo: so I implemented:
>>>>> RunArray>>fastReverseDo: aBlock
>>>>> Â Â Â Â | i |
>>>>> Â Â Â Â i := runs size.
>>>>> Â Â Â Â [i > 0]
>>>>> Â Â Â Â Â Â Â Â whileTrue:
>>>>> Â Â Â Â Â Â Â Â Â Â Â Â [ | r v |
>>>>> Â Â Â Â Â Â Â Â Â Â Â Â v := values at: i.
>>>>> Â Â Â Â Â Â Â Â Â Â Â Â r := runs at: i.
>>>>> Â Â Â Â Â Â Â Â Â Â Â Â i := i - 1.
>>>>> Â Â Â Â Â Â Â Â Â Â Â Â [( r := r - 1) >= 0]
>>>>> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â whileTrue: [aBlock value: v]].
>>>>> | tmp |
>>>>> tmp := ((Array new: 1000) collect: [:e | 4 atRandom]) as: RunArray.
>>>>> {
>>>>> [ tmp reverseDo: [:e |]] bench.
>>>>> [ tmp reverseDo2: [:e |]] bench.
>>>>> }
>>>>> Â #('83.9 per second.' '32,600 per second.')
>>>>>
>>>>> Ouch! The cache is missing a lot of indices, and our loop turns into a n^2 cost.
>>>>> I know, premature optimization bla bla bla, but a factor x400 is worth
>>>>> some inlining no?
>>>>>
>>>>> I guess these features are never used.
>>>>> By now RunArray is kind of private utility for Text implementation.
>>>>> But it could / should be generic.
>>>>>
>>>>> I also have proposals for count: / select: / collect:. etc...
>>>>> It would be to evaluate the block only once per group of values.
>>>>> For example
>>>>> RunArray>>collect: aBlock
>>>>> Â Â Â Â "Beware, the block will be evaluated only once per group of values."
>>>>> Â Â Â Â ^(self class runs: (runs collect: aBlock) contents values: values
>>>>> copy) coalesce
>>>>> But that's controversial, it would make the RunArray behave
>>>>> differently if the block has side effects...
>>>>>
>>>>> | i tmp tmp2 tmp3 |
>>>>> tmp := ((Array new: 1000) collect: [:e | 4 atRandom]).
>>>>> i := 0.
>>>>> tmp2 := tmp collect: [:e | i := i + 1].
>>>>> i := 0.
>>>>> tmp3 := (tmp as: RunArray) collect: [:e | i := i + 1].
>>>>> tmp2 = tmp3 asArray
>>>>> ==> false
>>>>>
>>>>> Nicolas
>>>>>
>>>>
>>>>
>>>
>>>
>>>
>>> --
>>> Best regards,
>>> Igor Stasenko AKA sig.
>>>
>>
>>
>>
>
Aug. 2, 2011
Re: [Pharo-project] building from PharoKernel
by laurent laffont
Is it actually possible to load ConfigurationOfSeaside30 in PharoKernel ?
I've tried using
https://ci.lille.inria.fr/pharo/job/Pharo%20Kernel%20Gofer/6/artifact/Pharo…
it seems to do nothing...
Note that builds #7 and #8 .zip seem to contain a PharoCore and not
PharoKernel.
Laurent
On Tue, Aug 2, 2011 at 11:08 PM, Pavel Krivanek <pavel.krivanek(a)gmail.com>wrote:
> We still do not have MinimalMorphic image equivalent so there is no
> reason to use it for DrGeo. However you may try to create DrGeo image,
> then start with Gefer image, load all methods that are not present in
> the Gofer image in form of a proxy method that will log the method
> call, loads the right code and executes it. Some supporting code is on
> the wiki of http://www.squeaksource.com/KernelImage.html.
> MinimalMorphic was created partly using this way.
>
> -- Pavel
>
> On Tue, Aug 2, 2011 at 3:41 PM, Hilaire Fernandes
> <hilaire.fernandes(a)edu.ge.ch> wrote:
> > I would like to build a DrGeo image from PharoKernel. Is it something
> > possible? I guess I am not the only one wondering about that
> >
> > Hilaire
> >
> >
> > --
> > Education 0.2 -- http://blog.ofset.org/hilaire
> >
> >
> >
>
>
Aug. 2, 2011
Re: [Pharo-project] [squeak-dev] Re: Optimizing RunArray
by Nicolas Cellier
I have tried again with huge text (my 45 MByte change log).
Main contributor seems to be Text composition.
A marginal gain (2 to 3% when resizing the window) is to remove the
indirection in TextStopConditions, and replace instance variable stops
with direct integer slots (variableSubclass)
No guaranty the fileIn of attachment will work, modifying Text
processing is dangerous...
Nicolas
2011/8/2 Stéphane Ducasse <stephane.ducasse(a)inria.fr>:
> Yes I was wondering about the same (for athens too :))
>
> Stef
>
> On Aug 2, 2011, at 2:16 PM, Igor Stasenko wrote:
>
>> Does it impacts the text rendering/processing speed?
>>
>>
>> On 2 August 2011 12:11, Nicolas Cellier
>> <nicolas.cellier.aka.nice(a)gmail.com> wrote:
>>> To complete myself, the fast #collect: already exists and is named
>>> #mapValues: except that it modifies the RunArray in place and also
>>> won't coalesce...
>>>
>>> I also gain a huge factor for #collect:as: be defining this method:
>>>
>>> RunArray>>fillFrom: aCollection with: aBlock
>>> Â Â Â Â "Evaluate aBlock with each of aCollections's elements as the argument.
>>> Â Â Â Â Collect the resulting values into self. Answer self."
>>> Â Â Â Â | newRuns newValues lastLength lastValue |
>>> Â Â Â Â newRuns := (Array new: aCollection size) writeStream.
>>> Â Â Â Â newValues := (Array new: aCollection size) writeStream.
>>> Â Â Â Â lastLength := 0.
>>> Â Â Â Â lastValue := Object new.
>>> Â Â Â Â aCollection do: [:each |
>>> Â Â Â Â Â Â Â Â | value |
>>> Â Â Â Â Â Â Â Â value := aBlock value: each.
>>> Â Â Â Â Â Â Â Â lastValue = value
>>> Â Â Â Â Â Â Â Â Â Â Â Â ifTrue: [lastLength := lastLength + 1]
>>> Â Â Â Â Â Â Â Â Â Â Â Â ifFalse:
>>> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â [lastLength > 0
>>> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â ifTrue:
>>> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â [newRuns nextPut: lastLength.
>>> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â newValues nextPut: lastValue].
>>> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â lastLength := 1.
>>> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â lastValue := value]].
>>> Â Â Â Â lastLength > 0
>>> Â Â Â Â Â Â Â Â ifTrue:
>>> Â Â Â Â Â Â Â Â Â Â Â Â [newRuns nextPut: lastLength.
>>> Â Â Â Â Â Â Â Â Â Â Â Â newValues nextPut: lastValue].
>>> Â Â Â Â self setRuns: newRuns contents setValues: newValues contents
>>>
>>> [ (Array new: 1000) collect: [:e | 4 atRandom] as: RunArray] bench.
>>> BEFORE: '25.1 per second.'
>>> AFTER: Â '1,080 per second.'
>>>
>>> It's worth a few lines of code.
>>>
>>> Nicolas
>>>
>>> 2011/8/2 Nicolas Cellier <nicolas.cellier.aka.nice(a)gmail.com>:
>>>> I played a bit with RunArray, and found some un-optimized features.
>>>> First, I don't know why RunArray is an ArrayedCollection. It cannot
>>>> #add: but it can #addFirst: and #addLast:.
>>>> It cannot #add:withOccurrences: but it can #addLast:times:. Why
>>>> inventing new selectors for old behaviours ?
>>>> These operations will cost a realloc it the last value is different,
>>>> so the underlying runs/values could better be an OrderedCollection if
>>>> these operations are used often.
>>>> A RunArray cannot remove at all.
>>>> Very weird collection species, I don't like the implementation too much.
>>>>
>>>> Then, #do: loops could be far faster. They rely on ArrayedCollection
>>>> which inlines do: loops with #to:do: and #at:
>>>> But #at: is not that fast. Scanning the runs and counting elements
>>>> would result in a n^2 cost.
>>>> Fortunately there is a cache lastIndex,lastRun,lastOffset to keep a cost n.
>>>> Nonetheless, all the tests cost, and the loop is suboptimal.
>>>> Let use see:
>>>>
>>>> version 1:
>>>> RunArray>>fastDo: aBlock
>>>> Â Â Â Â runs with: values do: [:r :v |
>>>> Â Â Â Â Â Â Â Â r timesRepeat: [aBlock value: v]].
>>>>
>>>> | tmp |
>>>> tmp := ((Array new: 1000) collect: [:e | 4 atRandom]) as: RunArray.
>>>> {
>>>> [ tmp do: [:e |]] bench.
>>>> [ tmp fastDo: [:e |]] bench.
>>>> }
>>>> #('3,220 per second.' '6,290 per second.')
>>>>
>>>> But timesRepeat: is slow, it is unoptimized by the compiler and costs
>>>> a message send.
>>>> I think we should implement BlockClosure>>repeat: and optimize that
>>>> call in Compiler.
>>>> But let's not do it, and rather inline by ourself:
>>>>
>>>> version 2:
>>>> Â Â Â Â runs with: values do: [:r :v |
>>>> Â Â Â Â Â Â Â Â 1 to: r do: [:i | aBlock value: v]].
>>>>
>>>> | tmp |
>>>> tmp := ((Array new: 1000) collect: [:e | 4 atRandom]) as: RunArray.
>>>> {
>>>> [ tmp do: [:e |]] bench.
>>>> [ tmp do2: [:e |]] bench.
>>>> }
>>>> #('3,070 per second.' '25,500 per second.')
>>>>
>>>> We can even inline the with:do: loop itself:
>>>> version 3:
>>>> Â Â Â Â 1 to: runs size do: [:i |
>>>> Â Â Â Â Â Â Â Â | r v |
>>>> Â Â Â Â Â Â Â Â v := values at: i.
>>>> Â Â Â Â Â Â Â Â r := runs at: i.
>>>> Â Â Â Â Â Â Â Â [( r := r - 1) >= 0]
>>>> Â Â Â Â Â Â Â Â Â Â Â Â whileTrue: [aBlock value: v]].
>>>>
>>>> | tmp |
>>>> tmp := ((Array new: 1000) collect: [:e | 4 atRandom]) as: RunArray.
>>>> {
>>>> [ tmp do: [:e |]] bench.
>>>> [ tmp do2: [:e |]] bench.
>>>> }
>>>> #('3,370 per second.' '32,200 per second.')
>>>>
>>>> Now the operation I wanted to use was reverseDo: so I implemented:
>>>> RunArray>>fastReverseDo: aBlock
>>>> Â Â Â Â | i |
>>>> Â Â Â Â i := runs size.
>>>> Â Â Â Â [i > 0]
>>>> Â Â Â Â Â Â Â Â whileTrue:
>>>> Â Â Â Â Â Â Â Â Â Â Â Â [ | r v |
>>>> Â Â Â Â Â Â Â Â Â Â Â Â v := values at: i.
>>>> Â Â Â Â Â Â Â Â Â Â Â Â r := runs at: i.
>>>> Â Â Â Â Â Â Â Â Â Â Â Â i := i - 1.
>>>> Â Â Â Â Â Â Â Â Â Â Â Â [( r := r - 1) >= 0]
>>>> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â whileTrue: [aBlock value: v]].
>>>> | tmp |
>>>> tmp := ((Array new: 1000) collect: [:e | 4 atRandom]) as: RunArray.
>>>> {
>>>> [ tmp reverseDo: [:e |]] bench.
>>>> [ tmp reverseDo2: [:e |]] bench.
>>>> }
>>>> Â #('83.9 per second.' '32,600 per second.')
>>>>
>>>> Ouch! The cache is missing a lot of indices, and our loop turns into a n^2 cost.
>>>> I know, premature optimization bla bla bla, but a factor x400 is worth
>>>> some inlining no?
>>>>
>>>> I guess these features are never used.
>>>> By now RunArray is kind of private utility for Text implementation.
>>>> But it could / should be generic.
>>>>
>>>> I also have proposals for count: / select: / collect:. etc...
>>>> It would be to evaluate the block only once per group of values.
>>>> For example
>>>> RunArray>>collect: aBlock
>>>> Â Â Â Â "Beware, the block will be evaluated only once per group of values."
>>>> Â Â Â Â ^(self class runs: (runs collect: aBlock) contents values: values
>>>> copy) coalesce
>>>> But that's controversial, it would make the RunArray behave
>>>> differently if the block has side effects...
>>>>
>>>> | i tmp tmp2 tmp3 |
>>>> tmp := ((Array new: 1000) collect: [:e | 4 atRandom]).
>>>> i := 0.
>>>> tmp2 := tmp collect: [:e | i := i + 1].
>>>> i := 0.
>>>> tmp3 := (tmp as: RunArray) collect: [:e | i := i + 1].
>>>> tmp2 = tmp3 asArray
>>>> ==> false
>>>>
>>>> Nicolas
>>>>
>>>
>>>
>>
>>
>>
>> --
>> Best regards,
>> Igor Stasenko AKA sig.
>>
>
>
>
Aug. 2, 2011
Re: [Pharo-project] building from PharoKernel
by Pavel Krivanek
We still do not have MinimalMorphic image equivalent so there is no
reason to use it for DrGeo. However you may try to create DrGeo image,
then start with Gefer image, load all methods that are not present in
the Gofer image in form of a proxy method that will log the method
call, loads the right code and executes it. Some supporting code is on
the wiki of http://www.squeaksource.com/KernelImage.html.
MinimalMorphic was created partly using this way.
-- Pavel
On Tue, Aug 2, 2011 at 3:41 PM, Hilaire Fernandes
<hilaire.fernandes(a)edu.ge.ch> wrote:
> I would like to build a DrGeo image from PharoKernel. Is it something
> possible? I guess I am not the only one wondering about that
>
> Hilaire
>
>
> --
> Education 0.2 -- http://blog.ofset.org/hilaire
>
>
>
Aug. 2, 2011
[Pharo-project] [update 1.4] #14072
by Stéphane Ducasse
14072
-----
- Issue 3433: Color improvement
http://code.google.com/p/pharo/issues/detail?id=3433
- Better class comment for FlatListMessageBrowser
Aug. 2, 2011
Re: [Pharo-project] [squeak-dev] Re: Optimizing RunArray
by Stéphane Ducasse
Yes I was wondering about the same (for athens too :))
Stef
On Aug 2, 2011, at 2:16 PM, Igor Stasenko wrote:
> Does it impacts the text rendering/processing speed?
>
>
> On 2 August 2011 12:11, Nicolas Cellier
> <nicolas.cellier.aka.nice(a)gmail.com> wrote:
>> To complete myself, the fast #collect: already exists and is named
>> #mapValues: except that it modifies the RunArray in place and also
>> won't coalesce...
>>
>> I also gain a huge factor for #collect:as: be defining this method:
>>
>> RunArray>>fillFrom: aCollection with: aBlock
>> "Evaluate aBlock with each of aCollections's elements as the argument.
>> Collect the resulting values into self. Answer self."
>> | newRuns newValues lastLength lastValue |
>> newRuns := (Array new: aCollection size) writeStream.
>> newValues := (Array new: aCollection size) writeStream.
>> lastLength := 0.
>> lastValue := Object new.
>> aCollection do: [:each |
>> | value |
>> value := aBlock value: each.
>> lastValue = value
>> ifTrue: [lastLength := lastLength + 1]
>> ifFalse:
>> [lastLength > 0
>> ifTrue:
>> [newRuns nextPut: lastLength.
>> newValues nextPut: lastValue].
>> lastLength := 1.
>> lastValue := value]].
>> lastLength > 0
>> ifTrue:
>> [newRuns nextPut: lastLength.
>> newValues nextPut: lastValue].
>> self setRuns: newRuns contents setValues: newValues contents
>>
>> [ (Array new: 1000) collect: [:e | 4 atRandom] as: RunArray] bench.
>> BEFORE: '25.1 per second.'
>> AFTER: '1,080 per second.'
>>
>> It's worth a few lines of code.
>>
>> Nicolas
>>
>> 2011/8/2 Nicolas Cellier <nicolas.cellier.aka.nice(a)gmail.com>:
>>> I played a bit with RunArray, and found some un-optimized features.
>>> First, I don't know why RunArray is an ArrayedCollection. It cannot
>>> #add: but it can #addFirst: and #addLast:.
>>> It cannot #add:withOccurrences: but it can #addLast:times:. Why
>>> inventing new selectors for old behaviours ?
>>> These operations will cost a realloc it the last value is different,
>>> so the underlying runs/values could better be an OrderedCollection if
>>> these operations are used often.
>>> A RunArray cannot remove at all.
>>> Very weird collection species, I don't like the implementation too much.
>>>
>>> Then, #do: loops could be far faster. They rely on ArrayedCollection
>>> which inlines do: loops with #to:do: and #at:
>>> But #at: is not that fast. Scanning the runs and counting elements
>>> would result in a n^2 cost.
>>> Fortunately there is a cache lastIndex,lastRun,lastOffset to keep a cost n.
>>> Nonetheless, all the tests cost, and the loop is suboptimal.
>>> Let use see:
>>>
>>> version 1:
>>> RunArray>>fastDo: aBlock
>>> runs with: values do: [:r :v |
>>> r timesRepeat: [aBlock value: v]].
>>>
>>> | tmp |
>>> tmp := ((Array new: 1000) collect: [:e | 4 atRandom]) as: RunArray.
>>> {
>>> [ tmp do: [:e |]] bench.
>>> [ tmp fastDo: [:e |]] bench.
>>> }
>>> #('3,220 per second.' '6,290 per second.')
>>>
>>> But timesRepeat: is slow, it is unoptimized by the compiler and costs
>>> a message send.
>>> I think we should implement BlockClosure>>repeat: and optimize that
>>> call in Compiler.
>>> But let's not do it, and rather inline by ourself:
>>>
>>> version 2:
>>> runs with: values do: [:r :v |
>>> 1 to: r do: [:i | aBlock value: v]].
>>>
>>> | tmp |
>>> tmp := ((Array new: 1000) collect: [:e | 4 atRandom]) as: RunArray.
>>> {
>>> [ tmp do: [:e |]] bench.
>>> [ tmp do2: [:e |]] bench.
>>> }
>>> #('3,070 per second.' '25,500 per second.')
>>>
>>> We can even inline the with:do: loop itself:
>>> version 3:
>>> 1 to: runs size do: [:i |
>>> | r v |
>>> v := values at: i.
>>> r := runs at: i.
>>> [( r := r - 1) >= 0]
>>> whileTrue: [aBlock value: v]].
>>>
>>> | tmp |
>>> tmp := ((Array new: 1000) collect: [:e | 4 atRandom]) as: RunArray.
>>> {
>>> [ tmp do: [:e |]] bench.
>>> [ tmp do2: [:e |]] bench.
>>> }
>>> #('3,370 per second.' '32,200 per second.')
>>>
>>> Now the operation I wanted to use was reverseDo: so I implemented:
>>> RunArray>>fastReverseDo: aBlock
>>> | i |
>>> i := runs size.
>>> [i > 0]
>>> whileTrue:
>>> [ | r v |
>>> v := values at: i.
>>> r := runs at: i.
>>> i := i - 1.
>>> [( r := r - 1) >= 0]
>>> whileTrue: [aBlock value: v]].
>>> | tmp |
>>> tmp := ((Array new: 1000) collect: [:e | 4 atRandom]) as: RunArray.
>>> {
>>> [ tmp reverseDo: [:e |]] bench.
>>> [ tmp reverseDo2: [:e |]] bench.
>>> }
>>> #('83.9 per second.' '32,600 per second.')
>>>
>>> Ouch! The cache is missing a lot of indices, and our loop turns into a n^2 cost.
>>> I know, premature optimization bla bla bla, but a factor x400 is worth
>>> some inlining no?
>>>
>>> I guess these features are never used.
>>> By now RunArray is kind of private utility for Text implementation.
>>> But it could / should be generic.
>>>
>>> I also have proposals for count: / select: / collect:. etc...
>>> It would be to evaluate the block only once per group of values.
>>> For example
>>> RunArray>>collect: aBlock
>>> "Beware, the block will be evaluated only once per group of values."
>>> ^(self class runs: (runs collect: aBlock) contents values: values
>>> copy) coalesce
>>> But that's controversial, it would make the RunArray behave
>>> differently if the block has side effects...
>>>
>>> | i tmp tmp2 tmp3 |
>>> tmp := ((Array new: 1000) collect: [:e | 4 atRandom]).
>>> i := 0.
>>> tmp2 := tmp collect: [:e | i := i + 1].
>>> i := 0.
>>> tmp3 := (tmp as: RunArray) collect: [:e | i := i + 1].
>>> tmp2 = tmp3 asArray
>>> ==> false
>>>
>>> Nicolas
>>>
>>
>>
>
>
>
> --
> Best regards,
> Igor Stasenko AKA sig.
>
Aug. 2, 2011
Re: [Pharo-project] Optimizing RunArray
by Stéphane Ducasse
Excellent!
Stef
On Aug 2, 2011, at 12:11 PM, Nicolas Cellier wrote:
> To complete myself, the fast #collect: already exists and is named
> #mapValues: except that it modifies the RunArray in place and also
> won't coalesce...
>
> I also gain a huge factor for #collect:as: be defining this method:
>
> RunArray>>fillFrom: aCollection with: aBlock
> "Evaluate aBlock with each of aCollections's elements as the argument.
> Collect the resulting values into self. Answer self."
> | newRuns newValues lastLength lastValue |
> newRuns := (Array new: aCollection size) writeStream.
> newValues := (Array new: aCollection size) writeStream.
> lastLength := 0.
> lastValue := Object new.
> aCollection do: [:each |
> | value |
> value := aBlock value: each.
> lastValue = value
> ifTrue: [lastLength := lastLength + 1]
> ifFalse:
> [lastLength > 0
> ifTrue:
> [newRuns nextPut: lastLength.
> newValues nextPut: lastValue].
> lastLength := 1.
> lastValue := value]].
> lastLength > 0
> ifTrue:
> [newRuns nextPut: lastLength.
> newValues nextPut: lastValue].
> self setRuns: newRuns contents setValues: newValues contents
>
> [ (Array new: 1000) collect: [:e | 4 atRandom] as: RunArray] bench.
> BEFORE: '25.1 per second.'
> AFTER: '1,080 per second.'
>
> It's worth a few lines of code.
>
> Nicolas
>
> 2011/8/2 Nicolas Cellier <nicolas.cellier.aka.nice(a)gmail.com>:
>> I played a bit with RunArray, and found some un-optimized features.
>> First, I don't know why RunArray is an ArrayedCollection. It cannot
>> #add: but it can #addFirst: and #addLast:.
>> It cannot #add:withOccurrences: but it can #addLast:times:. Why
>> inventing new selectors for old behaviours ?
>> These operations will cost a realloc it the last value is different,
>> so the underlying runs/values could better be an OrderedCollection if
>> these operations are used often.
>> A RunArray cannot remove at all.
>> Very weird collection species, I don't like the implementation too much.
>>
>> Then, #do: loops could be far faster. They rely on ArrayedCollection
>> which inlines do: loops with #to:do: and #at:
>> But #at: is not that fast. Scanning the runs and counting elements
>> would result in a n^2 cost.
>> Fortunately there is a cache lastIndex,lastRun,lastOffset to keep a cost n.
>> Nonetheless, all the tests cost, and the loop is suboptimal.
>> Let use see:
>>
>> version 1:
>> RunArray>>fastDo: aBlock
>> runs with: values do: [:r :v |
>> r timesRepeat: [aBlock value: v]].
>>
>> | tmp |
>> tmp := ((Array new: 1000) collect: [:e | 4 atRandom]) as: RunArray.
>> {
>> [ tmp do: [:e |]] bench.
>> [ tmp fastDo: [:e |]] bench.
>> }
>> #('3,220 per second.' '6,290 per second.')
>>
>> But timesRepeat: is slow, it is unoptimized by the compiler and costs
>> a message send.
>> I think we should implement BlockClosure>>repeat: and optimize that
>> call in Compiler.
>> But let's not do it, and rather inline by ourself:
>>
>> version 2:
>> runs with: values do: [:r :v |
>> 1 to: r do: [:i | aBlock value: v]].
>>
>> | tmp |
>> tmp := ((Array new: 1000) collect: [:e | 4 atRandom]) as: RunArray.
>> {
>> [ tmp do: [:e |]] bench.
>> [ tmp do2: [:e |]] bench.
>> }
>> #('3,070 per second.' '25,500 per second.')
>>
>> We can even inline the with:do: loop itself:
>> version 3:
>> 1 to: runs size do: [:i |
>> | r v |
>> v := values at: i.
>> r := runs at: i.
>> [( r := r - 1) >= 0]
>> whileTrue: [aBlock value: v]].
>>
>> | tmp |
>> tmp := ((Array new: 1000) collect: [:e | 4 atRandom]) as: RunArray.
>> {
>> [ tmp do: [:e |]] bench.
>> [ tmp do2: [:e |]] bench.
>> }
>> #('3,370 per second.' '32,200 per second.')
>>
>> Now the operation I wanted to use was reverseDo: so I implemented:
>> RunArray>>fastReverseDo: aBlock
>> | i |
>> i := runs size.
>> [i > 0]
>> whileTrue:
>> [ | r v |
>> v := values at: i.
>> r := runs at: i.
>> i := i - 1.
>> [( r := r - 1) >= 0]
>> whileTrue: [aBlock value: v]].
>> | tmp |
>> tmp := ((Array new: 1000) collect: [:e | 4 atRandom]) as: RunArray.
>> {
>> [ tmp reverseDo: [:e |]] bench.
>> [ tmp reverseDo2: [:e |]] bench.
>> }
>> #('83.9 per second.' '32,600 per second.')
>>
>> Ouch! The cache is missing a lot of indices, and our loop turns into a n^2 cost.
>> I know, premature optimization bla bla bla, but a factor x400 is worth
>> some inlining no?
>>
>> I guess these features are never used.
>> By now RunArray is kind of private utility for Text implementation.
>> But it could / should be generic.
>>
>> I also have proposals for count: / select: / collect:. etc...
>> It would be to evaluate the block only once per group of values.
>> For example
>> RunArray>>collect: aBlock
>> "Beware, the block will be evaluated only once per group of values."
>> ^(self class runs: (runs collect: aBlock) contents values: values
>> copy) coalesce
>> But that's controversial, it would make the RunArray behave
>> differently if the block has side effects...
>>
>> | i tmp tmp2 tmp3 |
>> tmp := ((Array new: 1000) collect: [:e | 4 atRandom]).
>> i := 0.
>> tmp2 := tmp collect: [:e | i := i + 1].
>> i := 0.
>> tmp3 := (tmp as: RunArray) collect: [:e | i := i + 1].
>> tmp2 = tmp3 asArray
>> ==> false
>>
>> Nicolas
>>
>
Aug. 2, 2011