displayingProgress on demand
Hello everyone, Is there a reason why #collect:displayingProgress: was removed or never included? And as more general question, is there any pointer to automatically add progress bar to iterator messages? For example doing: SmalltalkImage setDisplayProgressTo: MyClass. SmalltalkImage setDisplayProgressTo: MyPackage. and then having all enumeration messages sent in MyClass or MyPackage with a progress bar collect: collect:as: collect:into: collect:thenDo: select: select:as: select:thenDo: select:thenCollect:as: ... Hernán
Probably because it was badly done. Le 6/12/15 20:05, Hernán Morales Durand a écrit :
Hello everyone,
Is there a reason why #collect:displayingProgress: was removed or never included?
And as more general question, is there any pointer to automatically add progress bar to iterator messages?
For example doing:
SmalltalkImage setDisplayProgressTo: MyClass. SmalltalkImage setDisplayProgressTo: MyPackage.
and then having all enumeration messages sent in MyClass or MyPackage with a progress bar
collect: collect:as: collect:into: collect:thenDo: select: select:as: select:thenDo: select:thenCollect:as: ...
Hernán
There is still #do:displayingProgress: There is Job. In general, the collection API should not be concerned with GUI matters, does it ? We can't have equivalents of all collection methods for displaying progress, nor can it be a (semi-) global setting. If you look at how HTTPProgress is implemented/used, as a Notification, that might be a part of a solution, but I would not want to pay that performance price in the general API. I think there is no 'free' or 'easy' solution.
On 06 Dec 2015, at 21:23, stepharo <stepharo@free.fr> wrote:
Probably because it was badly done.
Le 6/12/15 20:05, Hernán Morales Durand a écrit :
Hello everyone,
Is there a reason why #collect:displayingProgress: was removed or never included?
And as more general question, is there any pointer to automatically add progress bar to iterator messages?
For example doing:
SmalltalkImage setDisplayProgressTo: MyClass. SmalltalkImage setDisplayProgressTo: MyPackage.
and then having all enumeration messages sent in MyClass or MyPackage with a progress bar
collect: collect:as: collect:into: collect:thenDo: select: select:as: select:thenDo: select:thenCollect:as: ...
Hernán
On 06 Dec 2015, at 21:34, Sven Van Caekenberghe <sven@stfx.eu> wrote:
There is still #do:displayingProgress:
There is Job.
In general, the collection API should not be concerned with GUI matters, does it ?
this. also including notifications âjust in case someone needs itâ will slowdown the system in general. as always: if want it, you can extend it in your programs. The API we propose is Job, so everybody can create their own âinformingâ versions.
We can't have equivalents of all collection methods for displaying progress, nor can it be a (semi-) global setting.
this too
If you look at how HTTPProgress is implemented/used, as a Notification, that might be a part of a solution, but I would not want to pay that performance price in the general API.
+42 Esteban
I think there is no 'free' or 'easy' solution.
On 06 Dec 2015, at 21:23, stepharo <stepharo@free.fr> wrote:
Probably because it was badly done.
Le 6/12/15 20:05, Hernán Morales Durand a écrit :
Hello everyone,
Is there a reason why #collect:displayingProgress: was removed or never included?
And as more general question, is there any pointer to automatically add progress bar to iterator messages?
For example doing:
SmalltalkImage setDisplayProgressTo: MyClass. SmalltalkImage setDisplayProgressTo: MyPackage.
and then having all enumeration messages sent in MyClass or MyPackage with a progress bar
collect: collect:as: collect:into: collect:thenDo: select: select:as: select:thenDo: select:thenCollect:as: ...
Hernán
Hi Sven 2015-12-06 17:34 GMT-03:00 Sven Van Caekenberghe <sven@stfx.eu>:
There is still #do:displayingProgress:
There is Job.
In general, the collection API should not be concerned with GUI matters, does it ?
Believe me when you're executing a large workflow processing 50Gb files with 5 other people expecting feedback from the screen, the least of your concerns is the purity of collection API. I don't know what other coders do, kick your co-workers off the room? Sit to see a blank Pharo screen? To me the key is to have feedback from the system without having to change your 20 iterators in a group of client classes where you NEED to see progress. Anyway I agree with you Collection should not have GUI dependencies, that's the reason I took a different approach and that's why I asked with an expression like: SmalltalkImage setDisplayProgressTo: MyClass. with such kind of expression you never touch the Collection API. You just walk MyClass for every enumeration messsage send (of your interest) and perform a transformation. Note the same "technique" could be applied for logging and/or profiling.
We can't have equivalents of all collection methods for displaying progress, nor can it be a (semi-) global setting.
Sure, that would be the anti-object technology :) So I implemented a prototype which injects JobProgress code in methods using RBParseSearchTree. On uninstall I plan to recover the previous version of marked methods. No need to touch the Collection API at all, nor a setting. I am sure the same could be done with MethodWrappers but RB can manipulate AST nodes. However if there is a better idea I would love to hear about it. If you look at how HTTPProgress is implemented/used, as a Notification,
that might be a part of a solution, but I would not want to pay that performance price in the general API.
Sure.
I think there is no 'free' or 'easy' solution.
Absolutely, this is not an easy problem. It would be cool anyone with enough Java experience can comment how they apply this kind of transformations. Hernán
On 06 Dec 2015, at 21:23, stepharo <stepharo@free.fr> wrote:
Probably because it was badly done.
Le 6/12/15 20:05, Hernán Morales Durand a écrit :
Hello everyone,
Is there a reason why #collect:displayingProgress: was removed or never included?
And as more general question, is there any pointer to automatically add progress bar to iterator messages?
For example doing:
SmalltalkImage setDisplayProgressTo: MyClass. SmalltalkImage setDisplayProgressTo: MyPackage.
and then having all enumeration messages sent in MyClass or MyPackage with a progress bar
collect: collect:as: collect:into: collect:thenDo: select: select:as: select:thenDo: select:thenCollect:as: ...
Hernán
Hi Hernán, Le 07/12/2015 18:16, Hernán Morales Durand a écrit :
Hi Sven
2015-12-06 17:34 GMT-03:00 Sven Van Caekenberghe <sven@stfx.eu <mailto:sven@stfx.eu>>:
There is still #do:displayingProgress:
There is Job.
In general, the collection API should not be concerned with GUI matters, does it ?
Believe me when you're executing a large workflow processing 50Gb files with 5 other people expecting feedback from the screen, the least of your concerns is the purity of collection API. I don't know what other coders do, kick your co-workers off the room? Sit to see a blank Pharo screen? To me the key is to have feedback from the system without having to change your 20 iterators in a group of client classes where you NEED to see progress.
Anyway I agree with you Collection should not have GUI dependencies, that's the reason I took a different approach and that's why I asked with an expression like:
SmalltalkImage setDisplayProgressTo: MyClass.
with such kind of expression you never touch the Collection API. You just walk MyClass for every enumeration messsage send (of your interest) and perform a transformation. Note the same "technique" could be applied for logging and/or profiling.
Yes. The Jejak tracer uses a similar technique. I'd guess others do as well.
We can't have equivalents of all collection methods for displaying progress, nor can it be a (semi-) global setting.
Sure, that would be the anti-object technology :)
So I implemented a prototype which injects JobProgress code in methods using RBParseSearchTree. On uninstall I plan to recover the previous version of marked methods. No need to touch the Collection API at all, nor a setting. I am sure the same could be done with MethodWrappers but RB can manipulate AST nodes.
However if there is a better idea I would love to hear about it.
Could you put your RBParseTreeRewriter scripts somewhere? I'm interested. Technically, you used one of the best solutions out there to reach your goal. Now, some would suggest aspect-oriented programming, but, for me, this is a limited, easier to use API over a rewrite engine like RB or the Metalinks of Marcus. Regards, Thierry
Hi Thierry 2015-12-07 14:43 GMT-03:00 Thierry Goubier <thierry.goubier@gmail.com>:
Hi Hernán,
Le 07/12/2015 18:16, Hernán Morales Durand a écrit :
Hi Sven
2015-12-06 17:34 GMT-03:00 Sven Van Caekenberghe <sven@stfx.eu <mailto:sven@stfx.eu>>:
There is still #do:displayingProgress:
There is Job.
In general, the collection API should not be concerned with GUI matters, does it ?
Believe me when you're executing a large workflow processing 50Gb files with 5 other people expecting feedback from the screen, the least of your concerns is the purity of collection API. I don't know what other coders do, kick your co-workers off the room? Sit to see a blank Pharo screen? To me the key is to have feedback from the system without having to change your 20 iterators in a group of client classes where you NEED to see progress.
Anyway I agree with you Collection should not have GUI dependencies, that's the reason I took a different approach and that's why I asked with an expression like:
SmalltalkImage setDisplayProgressTo: MyClass.
with such kind of expression you never touch the Collection API. You just walk MyClass for every enumeration messsage send (of your interest) and perform a transformation. Note the same "technique" could be applied for logging and/or profiling.
Yes. The Jejak tracer uses a similar technique. I'd guess others do as well.
Will have a look to Jejak, thanks.
We can't have equivalents of all collection methods for displaying
progress, nor can it be a (semi-) global setting.
Sure, that would be the anti-object technology :)
So I implemented a prototype which injects JobProgress code in methods using RBParseSearchTree. On uninstall I plan to recover the previous version of marked methods. No need to touch the Collection API at all, nor a setting. I am sure the same could be done with MethodWrappers but RB can manipulate AST nodes.
However if there is a better idea I would love to hear about it.
Could you put your RBParseTreeRewriter scripts somewhere? I'm interested.
Ok for the first part create a FooClass>>foo: method foo: aString aString asFileReference entries collect: [ : fileEntry | self openOnFileNamed: fileEntry fullName ] this one injects a node inside the Job block: http://ws.stfx.eu/5H7LNMMLIXEX For the next one, first add RBSequenceNode>>addNode: aNode after: anotherNode | index | index := self indexOfNode: anotherNode. index = 0 ifTrue: [ ^ self addNode: aNode ]. statements := statements asOrderedCollection add: aNode afterIndex: index; yourself. aNode parent: self. ^ aNode but now I am failing to see how to replace #collect: with #collect:thenDo: using the rewriter: http://ws.stfx.eu/MOWS947F000O Regards, Hernán
Here is my take on it. http://smalltalkhub.com/#!/~Latsabben/GafletFremgangFremviser Best regards, Henrik From: Pharo-dev [mailto:pharo-dev-bounces@lists.pharo.org] On Behalf Of Hernán Morales Durand Sent: Tuesday, December 8, 2015 12:28 AM To: Pharo Development List <pharo-dev@lists.pharo.org> Subject: Re: [Pharo-dev] displayingProgress on demand Hi Thierry 2015-12-07 14:43 GMT-03:00 Thierry Goubier <thierry.goubier@gmail.com<mailto:thierry.goubier@gmail.com>>: Hi Hernán, Le 07/12/2015 18:16, Hernán Morales Durand a écrit : Hi Sven 2015-12-06 17:34 GMT-03:00 Sven Van Caekenberghe <sven@stfx.eu<mailto:sven@stfx.eu> <mailto:sven@stfx.eu<mailto:sven@stfx.eu>>>: There is still #do:displayingProgress: There is Job. In general, the collection API should not be concerned with GUI matters, does it ? Believe me when you're executing a large workflow processing 50Gb files with 5 other people expecting feedback from the screen, the least of your concerns is the purity of collection API. I don't know what other coders do, kick your co-workers off the room? Sit to see a blank Pharo screen? To me the key is to have feedback from the system without having to change your 20 iterators in a group of client classes where you NEED to see progress. Anyway I agree with you Collection should not have GUI dependencies, that's the reason I took a different approach and that's why I asked with an expression like: SmalltalkImage setDisplayProgressTo: MyClass. with such kind of expression you never touch the Collection API. You just walk MyClass for every enumeration messsage send (of your interest) and perform a transformation. Note the same "technique" could be applied for logging and/or profiling. Yes. The Jejak tracer uses a similar technique. I'd guess others do as well. Will have a look to Jejak, thanks. We can't have equivalents of all collection methods for displaying progress, nor can it be a (semi-) global setting. Sure, that would be the anti-object technology :) So I implemented a prototype which injects JobProgress code in methods using RBParseSearchTree. On uninstall I plan to recover the previous version of marked methods. No need to touch the Collection API at all, nor a setting. I am sure the same could be done with MethodWrappers but RB can manipulate AST nodes. However if there is a better idea I would love to hear about it. Could you put your RBParseTreeRewriter scripts somewhere? I'm interested. Ok for the first part create a FooClass>>foo: method foo: aString aString asFileReference entries collect: [ : fileEntry | self openOnFileNamed: fileEntry fullName ] this one injects a node inside the Job block: http://ws.stfx.eu/5H7LNMMLIXEX For the next one, first add RBSequenceNode>>addNode: aNode after: anotherNode | index | index := self indexOfNode: anotherNode. index = 0 ifTrue: [ ^ self addNode: aNode ]. statements := statements asOrderedCollection add: aNode afterIndex: index; yourself. aNode parent: self. ^ aNode but now I am failing to see how to replace #collect: with #collect:thenDo: using the rewriter: http://ws.stfx.eu/MOWS947F000O Regards, Hernán
Hi Henrik I checked, thank you for sharing an elegant approach (although my issue with automatic code transformation remains). May you comment why you implemented another progress bar? Does support stacked progress bars? Do you plan to add labels? Hernán 2015-12-07 21:04 GMT-03:00 Henrik Nergaard <henrin10@student.uia.no>:
Here is my take on it.
http://smalltalkhub.com/#!/~Latsabben/GafletFremgangFremviser
Best regards,
Henrik
*From:* Pharo-dev [mailto:pharo-dev-bounces@lists.pharo.org] *On Behalf Of *Hernán Morales Durand *Sent:* Tuesday, December 8, 2015 12:28 AM *To:* Pharo Development List <pharo-dev@lists.pharo.org> *Subject:* Re: [Pharo-dev] displayingProgress on demand
Hi Thierry
2015-12-07 14:43 GMT-03:00 Thierry Goubier <thierry.goubier@gmail.com>:
Hi Hernán,
Le 07/12/2015 18:16, Hernán Morales Durand a écrit :
Hi Sven
2015-12-06 17:34 GMT-03:00 Sven Van Caekenberghe <sven@stfx.eu <mailto:sven@stfx.eu>>:
There is still #do:displayingProgress:
There is Job.
In general, the collection API should not be concerned with GUI matters, does it ?
Believe me when you're executing a large workflow processing 50Gb files with 5 other people expecting feedback from the screen, the least of your concerns is the purity of collection API. I don't know what other coders do, kick your co-workers off the room? Sit to see a blank Pharo screen? To me the key is to have feedback from the system without having to change your 20 iterators in a group of client classes where you NEED to see progress.
Anyway I agree with you Collection should not have GUI dependencies, that's the reason I took a different approach and that's why I asked with an expression like:
SmalltalkImage setDisplayProgressTo: MyClass.
with such kind of expression you never touch the Collection API. You just walk MyClass for every enumeration messsage send (of your interest) and perform a transformation. Note the same "technique" could be applied for logging and/or profiling.
Yes. The Jejak tracer uses a similar technique. I'd guess others do as well.
Will have a look to Jejak, thanks.
We can't have equivalents of all collection methods for displaying progress, nor can it be a (semi-) global setting.
Sure, that would be the anti-object technology :)
So I implemented a prototype which injects JobProgress code in methods using RBParseSearchTree. On uninstall I plan to recover the previous version of marked methods. No need to touch the Collection API at all, nor a setting. I am sure the same could be done with MethodWrappers but RB can manipulate AST nodes.
However if there is a better idea I would love to hear about it.
Could you put your RBParseTreeRewriter scripts somewhere? I'm interested.
Ok for the first part create a FooClass>>foo: method
foo: aString
aString asFileReference entries collect: [ : fileEntry | self openOnFileNamed: fileEntry fullName ]
this one injects a node inside the Job block:
http://ws.stfx.eu/5H7LNMMLIXEX
For the next one, first add
RBSequenceNode>>addNode: aNode after: anotherNode | index | index := self indexOfNode: anotherNode. index = 0 ifTrue: [ ^ self addNode: aNode ]. statements := statements asOrderedCollection add: aNode afterIndex: index; yourself. aNode parent: self. ^ aNode
but now I am failing to see how to replace #collect: with #collect:thenDo: using the rewriter:
http://ws.stfx.eu/MOWS947F000O
Regards,
Hernán
Hi To let you know finally I used the RewriteRuleBuilder http://myfuncoding.blogspot.cz/2015/02/video-presentation-of-rewrite-tool.ht... which generated the rule and installed the code (the only minor detail is that class methods are not browsed by the rule browser): [ : job | | index | index := 0. job title: 'Starting.'. ``@object1 collect: `@block1 thenDo: [ :fileEntry | index := index + 1. JobProgress progress: 0.1 * index; title: ' Procesing ' , index asString ] ] asJob run Cheers, Hernán 2015-12-07 20:27 GMT-03:00 Hernán Morales Durand <hernan.morales@gmail.com>:
Hi Thierry
2015-12-07 14:43 GMT-03:00 Thierry Goubier <thierry.goubier@gmail.com>:
Hi Hernán,
Le 07/12/2015 18:16, Hernán Morales Durand a écrit :
Hi Sven
2015-12-06 17:34 GMT-03:00 Sven Van Caekenberghe <sven@stfx.eu <mailto:sven@stfx.eu>>:
There is still #do:displayingProgress:
There is Job.
In general, the collection API should not be concerned with GUI matters, does it ?
Believe me when you're executing a large workflow processing 50Gb files with 5 other people expecting feedback from the screen, the least of your concerns is the purity of collection API. I don't know what other coders do, kick your co-workers off the room? Sit to see a blank Pharo screen? To me the key is to have feedback from the system without having to change your 20 iterators in a group of client classes where you NEED to see progress.
Anyway I agree with you Collection should not have GUI dependencies, that's the reason I took a different approach and that's why I asked with an expression like:
SmalltalkImage setDisplayProgressTo: MyClass.
with such kind of expression you never touch the Collection API. You just walk MyClass for every enumeration messsage send (of your interest) and perform a transformation. Note the same "technique" could be applied for logging and/or profiling.
Yes. The Jejak tracer uses a similar technique. I'd guess others do as well.
Will have a look to Jejak, thanks.
We can't have equivalents of all collection methods for displaying
progress, nor can it be a (semi-) global setting.
Sure, that would be the anti-object technology :)
So I implemented a prototype which injects JobProgress code in methods using RBParseSearchTree. On uninstall I plan to recover the previous version of marked methods. No need to touch the Collection API at all, nor a setting. I am sure the same could be done with MethodWrappers but RB can manipulate AST nodes.
However if there is a better idea I would love to hear about it.
Could you put your RBParseTreeRewriter scripts somewhere? I'm interested.
Ok for the first part create a FooClass>>foo: method
foo: aString
aString asFileReference entries collect: [ : fileEntry | self openOnFileNamed: fileEntry fullName ]
this one injects a node inside the Job block:
http://ws.stfx.eu/5H7LNMMLIXEX
For the next one, first add
RBSequenceNode>>addNode: aNode after: anotherNode | index | index := self indexOfNode: anotherNode. index = 0 ifTrue: [ ^ self addNode: aNode ]. statements := statements asOrderedCollection add: aNode afterIndex: index; yourself. aNode parent: self. ^ aNode
but now I am failing to see how to replace #collect: with #collect:thenDo: using the rewriter:
http://ws.stfx.eu/MOWS947F000O
Regards,
Hernán
On 12/7/2015 5:27 PM, Hernán Morales Durand wrote:
but now I am failing to see how to replace #collect: with #collect:thenDo: using the rewriter:
You don't need to first search using the RBParseTreeSearcher. The RBParseTreeRewriter works with search patterns. What your code is really doing is searching for the literal pattern that it found from the RBParseTreeSearcher in the FooClass>>foo: method: aString asFileReference entries collect: [ : fileEntry | self openOnFileNamed: fileEntry fullName ] It then tries to replace it with the pattern: `@collection collect: `@arg1 thenDo: [ : fileEntry | index := index + 1. JobProgress progress: (0.1 * index); title: 'Procesing...', index asString ] However, since neither `@collection nor `@arg1 appear in your search pattern, you get an error. Here's a version that works: | cm rewriteRule replacement | cm := FooClass >> #foo:. replacement := '`@collection collect: `@arg1 thenDo: [ : fileEntry | index := index + 1. JobProgress progress: (0.1 * index); title: ''Procesing...'', index asString ]'. rewriteRule := RBParseTreeRewriter new replace: '`@collection collect: `@arg1' with: replacement. rewriteRule executeTree: cm parseTree. rewriteRule tree newSource Essentially, I used the same search pattern you used, but I used it for the RBParseTreeRewriter and removed all of the RBParseTreeSearcher code. If you want to change all #collect: sends in a method, then you should probably change `@aCollection and `@arg1 to ``@aCollection and ``@arg1. John Brant
Hi John, Thank you for your feedback and help! I started a ProgressBarInstaller using your corrections. Unfortunately SmalltalkHub is not working for me right now but will check tomorrow and share the link. Best regards, Hernán 2015-12-08 13:56 GMT-03:00 John Brant <brant@refactoryworkers.com>:
On 12/7/2015 5:27 PM, Hernán Morales Durand wrote:
but now I am failing to see how to replace #collect: with #collect:thenDo: using the rewriter:
You don't need to first search using the RBParseTreeSearcher. The RBParseTreeRewriter works with search patterns. What your code is really doing is searching for the literal pattern that it found from the RBParseTreeSearcher in the FooClass>>foo: method:
aString asFileReference entries collect: [ : fileEntry | self openOnFileNamed: fileEntry fullName ]
It then tries to replace it with the pattern:
`@collection collect: `@arg1 thenDo: [ : fileEntry | index := index + 1. JobProgress progress: (0.1 * index); title: 'Procesing...', index asString ]
However, since neither `@collection nor `@arg1 appear in your search pattern, you get an error.
Here's a version that works:
| cm rewriteRule replacement | cm := FooClass >> #foo:. replacement := '`@collection collect: `@arg1 thenDo: [ : fileEntry | index := index + 1. JobProgress progress: (0.1 * index); title: ''Procesing...'', index asString ]'. rewriteRule := RBParseTreeRewriter new replace: '`@collection collect: `@arg1' with: replacement. rewriteRule executeTree: cm parseTree. rewriteRule tree newSource
Essentially, I used the same search pattern you used, but I used it for the RBParseTreeRewriter and removed all of the RBParseTreeSearcher code. If you want to change all #collect: sends in a method, then you should probably change `@aCollection and `@arg1 to ``@aCollection and ``@arg1.
John Brant
http://www.smalltalkhub.com/#!/~hernan/ProgressBarInstaller Public write access Cheers, Hernán 2015-12-08 20:40 GMT-03:00 Hernán Morales Durand <hernan.morales@gmail.com>:
Hi John,
Thank you for your feedback and help!
I started a ProgressBarInstaller using your corrections. Unfortunately SmalltalkHub is not working for me right now but will check tomorrow and share the link.
Best regards,
Hernán
2015-12-08 13:56 GMT-03:00 John Brant <brant@refactoryworkers.com>:
On 12/7/2015 5:27 PM, Hernán Morales Durand wrote:
but now I am failing to see how to replace #collect: with #collect:thenDo: using the rewriter:
You don't need to first search using the RBParseTreeSearcher. The RBParseTreeRewriter works with search patterns. What your code is really doing is searching for the literal pattern that it found from the RBParseTreeSearcher in the FooClass>>foo: method:
aString asFileReference entries collect: [ : fileEntry | self openOnFileNamed: fileEntry fullName ]
It then tries to replace it with the pattern:
`@collection collect: `@arg1 thenDo: [ : fileEntry | index := index + 1. JobProgress progress: (0.1 * index); title: 'Procesing...', index asString ]
However, since neither `@collection nor `@arg1 appear in your search pattern, you get an error.
Here's a version that works:
| cm rewriteRule replacement | cm := FooClass >> #foo:. replacement := '`@collection collect: `@arg1 thenDo: [ : fileEntry | index := index + 1. JobProgress progress: (0.1 * index); title: ''Procesing...'', index asString ]'. rewriteRule := RBParseTreeRewriter new replace: '`@collection collect: `@arg1' with: replacement. rewriteRule executeTree: cm parseTree. rewriteRule tree newSource
Essentially, I used the same search pattern you used, but I used it for the RBParseTreeRewriter and removed all of the RBParseTreeSearcher code. If you want to change all #collect: sends in a method, then you should probably change `@aCollection and `@arg1 to ``@aCollection and ``@arg1.
John Brant
Thanks Hernan. I love your attitude: - packaging and sharing Keep pushing Stef Le 9/12/15 07:03, Hernán Morales Durand a écrit :
http://www.smalltalkhub.com/#!/~hernan/ProgressBarInstaller <http://www.smalltalkhub.com/#%21/%7Ehernan/ProgressBarInstaller>
Public write access
Cheers,
Hernán
2015-12-08 20:40 GMT-03:00 Hernán Morales Durand <hernan.morales@gmail.com <mailto:hernan.morales@gmail.com>>:
Hi John,
Thank you for your feedback and help!
I started a ProgressBarInstaller using your corrections. Unfortunately SmalltalkHub is not working for me right now but will check tomorrow and share the link.
Best regards,
Hernán
2015-12-08 13:56 GMT-03:00 John Brant <brant@refactoryworkers.com <mailto:brant@refactoryworkers.com>>:
On 12/7/2015 5:27 PM, Hernán Morales Durand wrote:
but now I am failing to see how to replace #collect: with #collect:thenDo: using the rewriter:
http://ws.stfx.eu/MOWS947F000O
You don't need to first search using the RBParseTreeSearcher. The RBParseTreeRewriter works with search patterns. What your code is really doing is searching for the literal pattern that it found from the RBParseTreeSearcher in the FooClass>>foo: method:
aString asFileReference entries collect: [ : fileEntry | self openOnFileNamed: fileEntry fullName ]
It then tries to replace it with the pattern:
`@collection collect: `@arg1 thenDo: [ : fileEntry | index := index + 1. JobProgress progress: (0.1 * index); title: 'Procesing...', index asString ]
However, since neither `@collection nor `@arg1 appear in your search pattern, you get an error.
Here's a version that works:
| cm rewriteRule replacement | cm := FooClass >> #foo:. replacement := '`@collection collect: `@arg1 thenDo: [ : fileEntry | index := index + 1. JobProgress progress: (0.1 * index); title: ''Procesing...'', index asString ]'. rewriteRule := RBParseTreeRewriter new replace: '`@collection collect: `@arg1' with: replacement. rewriteRule executeTree: cm parseTree. rewriteRule tree newSource
Essentially, I used the same search pattern you used, but I used it for the RBParseTreeRewriter and removed all of the RBParseTreeSearcher code. If you want to change all #collect: sends in a method, then you should probably change `@aCollection and `@arg1 to ``@aCollection and ``@arg1.
John Brant
I would like to see this code injector too. Stef Le 7/12/15 18:43, Thierry Goubier a écrit :
Hi Hernán,
Le 07/12/2015 18:16, Hernán Morales Durand a écrit :
Hi Sven
2015-12-06 17:34 GMT-03:00 Sven Van Caekenberghe <sven@stfx.eu <mailto:sven@stfx.eu>>:
There is still #do:displayingProgress:
There is Job.
In general, the collection API should not be concerned with GUI matters, does it ?
Believe me when you're executing a large workflow processing 50Gb files with 5 other people expecting feedback from the screen, the least of your concerns is the purity of collection API. I don't know what other coders do, kick your co-workers off the room? Sit to see a blank Pharo screen? To me the key is to have feedback from the system without having to change your 20 iterators in a group of client classes where you NEED to see progress.
Anyway I agree with you Collection should not have GUI dependencies, that's the reason I took a different approach and that's why I asked with an expression like:
SmalltalkImage setDisplayProgressTo: MyClass.
with such kind of expression you never touch the Collection API. You just walk MyClass for every enumeration messsage send (of your interest) and perform a transformation. Note the same "technique" could be applied for logging and/or profiling.
Yes. The Jejak tracer uses a similar technique. I'd guess others do as well.
We can't have equivalents of all collection methods for displaying progress, nor can it be a (semi-) global setting.
Sure, that would be the anti-object technology :)
So I implemented a prototype which injects JobProgress code in methods using RBParseSearchTree. On uninstall I plan to recover the previous version of marked methods. No need to touch the Collection API at all, nor a setting. I am sure the same could be done with MethodWrappers but RB can manipulate AST nodes.
However if there is a better idea I would love to hear about it.
Could you put your RBParseTreeRewriter scripts somewhere? I'm interested.
Technically, you used one of the best solutions out there to reach your goal. Now, some would suggest aspect-oriented programming, but, for me, this is a limited, easier to use API over a rewrite engine like RB or the Metalinks of Marcus.
Regards,
Thierry
Few years ago I try another approach which was work in my test. Instead of code rewriting to make loop iteration announcing steps you can track periodically (in background) process which progress you want to report. You can scan full call stack of it suspended context for loops and analyse it progress variables (index and bounds). You can provide required meta information to find exact places you want (like you doing with your rewriting approach). Plus of my approach that it is not touch runnable code which not required progress reporting. And it should not influence performance of target process. Best regards, Denis 2015-12-07 18:16 GMT+01:00 Hernán Morales Durand <hernan.morales@gmail.com>:
Hi Sven
2015-12-06 17:34 GMT-03:00 Sven Van Caekenberghe <sven@stfx.eu>:
There is still #do:displayingProgress:
There is Job.
In general, the collection API should not be concerned with GUI matters, does it ?
Believe me when you're executing a large workflow processing 50Gb files with 5 other people expecting feedback from the screen, the least of your concerns is the purity of collection API. I don't know what other coders do, kick your co-workers off the room? Sit to see a blank Pharo screen? To me the key is to have feedback from the system without having to change your 20 iterators in a group of client classes where you NEED to see progress.
Anyway I agree with you Collection should not have GUI dependencies, that's the reason I took a different approach and that's why I asked with an expression like:
SmalltalkImage setDisplayProgressTo: MyClass.
with such kind of expression you never touch the Collection API. You just walk MyClass for every enumeration messsage send (of your interest) and perform a transformation. Note the same "technique" could be applied for logging and/or profiling.
We can't have equivalents of all collection methods for displaying progress, nor can it be a (semi-) global setting.
Sure, that would be the anti-object technology :)
So I implemented a prototype which injects JobProgress code in methods using RBParseSearchTree. On uninstall I plan to recover the previous version of marked methods. No need to touch the Collection API at all, nor a setting. I am sure the same could be done with MethodWrappers but RB can manipulate AST nodes.
However if there is a better idea I would love to hear about it.
If you look at how HTTPProgress is implemented/used, as a Notification,
that might be a part of a solution, but I would not want to pay that performance price in the general API.
Sure.
I think there is no 'free' or 'easy' solution.
Absolutely, this is not an easy problem. It would be cool anyone with enough Java experience can comment how they apply this kind of transformations.
Hernán
On 06 Dec 2015, at 21:23, stepharo <stepharo@free.fr> wrote:
Probably because it was badly done.
Le 6/12/15 20:05, Hernán Morales Durand a écrit :
Hello everyone,
Is there a reason why #collect:displayingProgress: was removed or never included?
And as more general question, is there any pointer to automatically add progress bar to iterator messages?
For example doing:
SmalltalkImage setDisplayProgressTo: MyClass. SmalltalkImage setDisplayProgressTo: MyPackage.
and then having all enumeration messages sent in MyClass or MyPackage with a progress bar
collect: collect:as: collect:into: collect:thenDo: select: select:as: select:thenDo: select:thenCollect:as: ...
Hernán
Hi Denis, 2015-12-08 9:58 GMT+01:00 Denis Kudriashov <dionisiydk@gmail.com>:
Few years ago I try another approach which was work in my test.
Instead of code rewriting to make loop iteration announcing steps you can track periodically (in background) process which progress you want to report. You can scan full call stack of it suspended context for loops and analyse it progress variables (index and bounds). You can provide required meta information to find exact places you want (like you doing with your rewriting approach).
Do you have that code somewhere? I think it would be interesting to have a general framework for that (since this is a trace/profiling by sampling approach).
Plus of my approach that it is not touch runnable code which not required progress reporting. And it should not influence performance of target process.
Wishfull thinking: you have a tradeoff when you do that, you interrupt running code and so changes timings and synchronisations, your scan takes time, and things below your sampling frequency are not visible. That being said, and if you take those factors into account, then your approach is sound. Just don't say it is a miracle solution. Regards, Thierry
Best regards, Denis
2015-12-07 18:16 GMT+01:00 Hernán Morales Durand <hernan.morales@gmail.com
:
Hi Sven
2015-12-06 17:34 GMT-03:00 Sven Van Caekenberghe <sven@stfx.eu>:
There is still #do:displayingProgress:
There is Job.
In general, the collection API should not be concerned with GUI matters, does it ?
Believe me when you're executing a large workflow processing 50Gb files with 5 other people expecting feedback from the screen, the least of your concerns is the purity of collection API. I don't know what other coders do, kick your co-workers off the room? Sit to see a blank Pharo screen? To me the key is to have feedback from the system without having to change your 20 iterators in a group of client classes where you NEED to see progress.
Anyway I agree with you Collection should not have GUI dependencies, that's the reason I took a different approach and that's why I asked with an expression like:
SmalltalkImage setDisplayProgressTo: MyClass.
with such kind of expression you never touch the Collection API. You just walk MyClass for every enumeration messsage send (of your interest) and perform a transformation. Note the same "technique" could be applied for logging and/or profiling.
We can't have equivalents of all collection methods for displaying progress, nor can it be a (semi-) global setting.
Sure, that would be the anti-object technology :)
So I implemented a prototype which injects JobProgress code in methods using RBParseSearchTree. On uninstall I plan to recover the previous version of marked methods. No need to touch the Collection API at all, nor a setting. I am sure the same could be done with MethodWrappers but RB can manipulate AST nodes.
However if there is a better idea I would love to hear about it.
If you look at how HTTPProgress is implemented/used, as a Notification,
that might be a part of a solution, but I would not want to pay that performance price in the general API.
Sure.
I think there is no 'free' or 'easy' solution.
Absolutely, this is not an easy problem. It would be cool anyone with enough Java experience can comment how they apply this kind of transformations.
Hernán
On 06 Dec 2015, at 21:23, stepharo <stepharo@free.fr> wrote:
Probably because it was badly done.
Le 6/12/15 20:05, Hernán Morales Durand a écrit :
Hello everyone,
Is there a reason why #collect:displayingProgress: was removed or never included?
And as more general question, is there any pointer to automatically add progress bar to iterator messages?
For example doing:
SmalltalkImage setDisplayProgressTo: MyClass. SmalltalkImage setDisplayProgressTo: MyPackage.
and then having all enumeration messages sent in MyClass or MyPackage with a progress bar
collect: collect:as: collect:into: collect:thenDo: select: select:as: select:thenDo: select:thenCollect:as: ...
Hernán
2015-12-08 10:16 GMT+01:00 Thierry Goubier <thierry.goubier@gmail.com>:
Wishfull thinking:
you have a tradeoff when you do that, you interrupt running code and so changes timings and synchronisations, your scan takes time, and things below your sampling frequency are not visible.
That being said, and if you take those factors into account, then your approach is sound. Just don't say it is a miracle solution.
Yes, of course. I mean that such approach should not has so big impact on performance as direct announcing inside loop. Most time it will spend on updating/drawing progress bar. And it is not comparable to time which required to scan call chain. In most cases call chain has very small deep. And retrieving information about progress looks like trivial operation. Besides this analysing happens only when track process wake up. So It gives seconds to run code without interruption. I will try find code. But it was not ready to use solution. Just very little experiment for my UI framework Presenty.
2015-12-08 10:29 GMT+01:00 Denis Kudriashov <dionisiydk@gmail.com>:
2015-12-08 10:16 GMT+01:00 Thierry Goubier <thierry.goubier@gmail.com>:
Wishfull thinking:
you have a tradeoff when you do that, you interrupt running code and so changes timings and synchronisations, your scan takes time, and things below your sampling frequency are not visible.
That being said, and if you take those factors into account, then your approach is sound. Just don't say it is a miracle solution.
Yes, of course. I mean that such approach should not has so big impact on performance as direct announcing inside loop. Most time it will spend on updating/drawing progress bar. And it is not comparable to time which required to scan call chain. In most cases call chain has very small deep. And retrieving information about progress looks like trivial operation. Besides this analysing happens only when track process wake up. So It gives seconds to run code without interruption.
Hum you give interesting insights into it, like that the call chain isn't very deep. Good to know :)
I will try find code. But it was not ready to use solution. Just very little experiment for my UI framework Presenty.
It could be very nice to have for many long-running computations. I think the models used by Serge in SciSmalltalk / Kendrick? could benefit a lot from that. Thierry
If this would work, that would make many people happy ! It would be basically make tracking progress a no-cost option.
On 08 Dec 2015, at 10:29, Denis Kudriashov <dionisiydk@gmail.com> wrote:
2015-12-08 10:16 GMT+01:00 Thierry Goubier <thierry.goubier@gmail.com>: Wishfull thinking:
you have a tradeoff when you do that, you interrupt running code and so changes timings and synchronisations, your scan takes time, and things below your sampling frequency are not visible.
That being said, and if you take those factors into account, then your approach is sound. Just don't say it is a miracle solution.
Yes, of course. I mean that such approach should not has so big impact on performance as direct announcing inside loop. Most time it will spend on updating/drawing progress bar. And it is not comparable to time which required to scan call chain. In most cases call chain has very small deep. And retrieving information about progress looks like trivial operation. Besides this analysing happens only when track process wake up. So It gives seconds to run code without interruption.
I will try find code. But it was not ready to use solution. Just very little experiment for my UI framework Presenty.
I found code. It was work only in my test where I show progress of "(1 to: 1000) do: [:i | 1 seconds wait]". stack := executionProcess suspendedContext stack reversed. progressContext := stack detect: [:each | each receiver isKindOf: SequenceableCollection] ifNone: [nil]. progressContext ifNil: [^self]. info := progressContext progressInfo. "And here you can show progress as " info currentPosition asString, '/', info endPosition asString. Context>>progressInfo ^self receiver fetchProgressInfoFrom: self Interval>>fetchProgressInfoFrom: aContext ^PtyProgressInfo currentPosition: (aContext tempAt: 3) end: self size 2015-12-08 9:58 GMT+01:00 Denis Kudriashov <dionisiydk@gmail.com>:
Few years ago I try another approach which was work in my test.
Instead of code rewriting to make loop iteration announcing steps you can track periodically (in background) process which progress you want to report. You can scan full call stack of it suspended context for loops and analyse it progress variables (index and bounds). You can provide required meta information to find exact places you want (like you doing with your rewriting approach). Plus of my approach that it is not touch runnable code which not required progress reporting. And it should not influence performance of target process.
Best regards, Denis
2015-12-07 18:16 GMT+01:00 Hernán Morales Durand <hernan.morales@gmail.com
:
Hi Sven
2015-12-06 17:34 GMT-03:00 Sven Van Caekenberghe <sven@stfx.eu>:
There is still #do:displayingProgress:
There is Job.
In general, the collection API should not be concerned with GUI matters, does it ?
Believe me when you're executing a large workflow processing 50Gb files with 5 other people expecting feedback from the screen, the least of your concerns is the purity of collection API. I don't know what other coders do, kick your co-workers off the room? Sit to see a blank Pharo screen? To me the key is to have feedback from the system without having to change your 20 iterators in a group of client classes where you NEED to see progress.
Anyway I agree with you Collection should not have GUI dependencies, that's the reason I took a different approach and that's why I asked with an expression like:
SmalltalkImage setDisplayProgressTo: MyClass.
with such kind of expression you never touch the Collection API. You just walk MyClass for every enumeration messsage send (of your interest) and perform a transformation. Note the same "technique" could be applied for logging and/or profiling.
We can't have equivalents of all collection methods for displaying progress, nor can it be a (semi-) global setting.
Sure, that would be the anti-object technology :)
So I implemented a prototype which injects JobProgress code in methods using RBParseSearchTree. On uninstall I plan to recover the previous version of marked methods. No need to touch the Collection API at all, nor a setting. I am sure the same could be done with MethodWrappers but RB can manipulate AST nodes.
However if there is a better idea I would love to hear about it.
If you look at how HTTPProgress is implemented/used, as a Notification,
that might be a part of a solution, but I would not want to pay that performance price in the general API.
Sure.
I think there is no 'free' or 'easy' solution.
Absolutely, this is not an easy problem. It would be cool anyone with enough Java experience can comment how they apply this kind of transformations.
Hernán
On 06 Dec 2015, at 21:23, stepharo <stepharo@free.fr> wrote:
Probably because it was badly done.
Le 6/12/15 20:05, Hernán Morales Durand a écrit :
Hello everyone,
Is there a reason why #collect:displayingProgress: was removed or never included?
And as more general question, is there any pointer to automatically add progress bar to iterator messages?
For example doing:
SmalltalkImage setDisplayProgressTo: MyClass. SmalltalkImage setDisplayProgressTo: MyPackage.
and then having all enumeration messages sent in MyClass or MyPackage with a progress bar
collect: collect:as: collect:into: collect:thenDo: select: select:as: select:thenDo: select:thenCollect:as: ...
Hernán
Could we have a synthesis of the discussion? It would be good to have a list of working solutions with pointers. Stef
Here is what I understand. Option 1: an aspect oriented solution where all usages of iterations get rewritten inside a scope to use progress - People showed examples using the RBTreeRewriter - I think that reflectivity should be also considered Option 2: stack introspection - this would not initially create a performance overhead if progress is not used - but there is the side effect of reifying the stack (that should be measured) - anyways, using the notification also reifies the stack so... Orthogonal, I think that an alternative solution to rewrite callers is to use some kind of decorators For example, a wrapper on the collection can handle the progress and be polymorphic to a collection. This simplifies the collection API, and extracts the progress concern into a composable object. Users do not care if a collection is a normal collection or a progress enabled collection. Moreover, the progress object can have a direct reference to a Job, avoiding notifications, and then, maybe having a less impact in performance (due to stack reification). OrderedCollection new do: [ ... ] => normal iteration OrderedCollection new showingProgress do: [ ... ] Then, to deploy such a collection, a code rewriter will just replace every "OrderedCollection new" by "OrderedCollection new showingProgressâ. This goes in the direction of the iterators that were discussed in the other thread. Guille
On 8 dic 2015, at 10:59 a.m., stepharo <stepharo@free.fr> wrote:
Could we have a synthesis of the discussion?
It would be good to have a list of working solutions with pointers.
Stef
2015-12-08 13:53 GMT+01:00 Guillermo Polito <guillermopolito@gmail.com>:
Option 2: stack introspection - this would not initially create a performance overhead if progress is not used - but there is the side effect of reifying the stack (that should be measured)
Interesting how much it is slow comparing to visually updating progress bar. I feel that it should be less than few percents of it.
- anyways, using the notification also reifies the stack so...
I was sure that current job approach uses announcement instead of Exceptions mechanism. Am I wrong?
2015-12-08 13:53 GMT+01:00 Guillermo Polito <guillermopolito@gmail.com>:
Here is what I understand.
Option 1: an aspect oriented solution where all usages of iterations get rewritten inside a scope to use progress - People showed examples using the RBTreeRewriter - I think that reflectivity should be also considered
Yes. Solutions would also include an adequate kind of watchpoint/metalink (but the RB stuff may still be necessary to know where to put that watch point).
Option 2: stack introspection - this would not initially create a performance overhead if progress is not used - but there is the side effect of reifying the stack (that should be measured) - anyways, using the notification also reifies the stack so...
Orthogonal, I think that an alternative solution to rewrite callers is to use some kind of decorators For example, a wrapper on the collection can handle the progress and be polymorphic to a collection. This simplifies the collection API, and extracts the progress concern into a composable object. Users do not care if a collection is a normal collection or a progress enabled collection. Moreover, the progress object can have a direct reference to a Job, avoiding notifications, and then, maybe having a less impact in performance (due to stack reification).
OrderedCollection new do: [ ... ] => normal iteration
OrderedCollection new showingProgress do: [ ... ]
Then, to deploy such a collection, a code rewriter will just replace every "OrderedCollection new" by "OrderedCollection new showingProgressâ.
This goes in the direction of the iterators that were discussed in the other thread.
Hum. This solution looks a bit more elegant that 1-, but it is finally as complex (need for a wrapper, need for a rewriting pass anyway, maybe simpler than 1)... However, it may be useful if one want to have a progress on only certain classes users of collections. But, then, 2- is even better since it may be able to customize per instance behavior, not only per caller code. Thierry
Guille
On 8 dic 2015, at 10:59 a.m., stepharo <stepharo@free.fr> wrote:
Could we have a synthesis of the discussion?
It would be good to have a list of working solutions with pointers.
Stef
participants (9)
-
Denis Kudriashov -
Esteban Lorenzano -
Guillermo Polito -
Henrik Nergaard -
Hernán Morales Durand -
John Brant -
stepharo -
Sven Van Caekenberghe -
Thierry Goubier