Re: [Pharo-dev] Should Job use SystemAnnouncer?
Camillo wrote:
in this case it is only the instance of Job which knows the status. Thread-safeness is not an issue since the progress bar is pure approximation.
The problem is not approximation. Objects are not reentrant, getting the value out of a model while it is reorganizing its datastructure is likely to give interesting and difficult to reproduce results (dividing by 0, nil-pointer exceptions).
that does not work properly and inaccurately reports long running jobs, for instance when running tests. Usually tests take far less than 1 ms, in which case this scheme works perfectly. However from time to time you have 1 test that runs for a couple of seconds. If you run 5000 tests you have to run quite a few tests to get that 1% update margin, so very often the UI does not correctly report the current status.
That is not a solvable problem. A progress bar depends on a value increasing from min to max. The model is responsible for making reasonable steps.
Anyway, this requires quite some changes in the current ProgressBarMorph, so any other improvement until then is welcome :)
I've put together a new slice in the 30 Inbox with the combined changes. Where should I put a backport for 2.0?
On 2013-09-03, at 18:57, Stephan Eggermont <stephan@stack.nl> wrote:
Camillo wrote:
in this case it is only the instance of Job which knows the status. Thread-safeness is not an issue since the progress bar is pure approximation.
The problem is not approximation. Objects are not reentrant, getting the value out of a model while it is reorganizing its datastructure is likely to give interesting and difficult to reproduce results (dividing by 0, nil-pointer exceptions).
that does not work properly and inaccurately reports long running jobs, for instance when running tests. Usually tests take far less than 1 ms, in which case this scheme works perfectly. However from time to time you have 1 test that runs for a couple of seconds. If you run 5000 tests you have to run quite a few tests to get that 1% update margin, so very often the UI does not correctly report the current status.
That is not a solvable problem. A progress bar depends on a value increasing from min to max. The model is responsible for making reasonable steps.
ok, different question, how do you solve this very use-case without polling? 1. run test 1 [1ms] ..... N. run test N [1ms] ------------------------------------------- Progress Bar update limit reached after a) either N update calls b) N ms => next update will happen in a) N calls b) N ms ------------------------------------------- N+1. run test N+1 [1000 ms] That means that the UI shows the wrong value (run test N) instead of the current progress value (run test N+1), which is not interesting. The model, in this case the test runner, properly informed the UI about every change, but the update limitations in the ProgressBarMorph cannot properly detect such a case. - either you update way to often => performance overhead - or you update not often enough => inaccurate progress indication when progress step times differ a lot There is simply no way you can properly solve this case without active polling. As for your doubts about thread-safeness: The model for the ProgressBar is the Job class. It is hence the only entry point for the PogressBar and thus can easily be made threadsafe. My use-case is simply that I want to see in which test-case the test runner hangs.
On Sep 4, 2013, at 12:12 , Camillo Bruni <camillobruni@gmail.com> wrote:
On 2013-09-03, at 18:57, Stephan Eggermont <stephan@stack.nl> wrote:
Camillo wrote:
in this case it is only the instance of Job which knows the status. Thread-safeness is not an issue since the progress bar is pure approximation.
The problem is not approximation. Objects are not reentrant, getting the value out of a model while it is reorganizing its datastructure is likely to give interesting and difficult to reproduce results (dividing by 0, nil-pointer exceptions).
that does not work properly and inaccurately reports long running jobs, for instance when running tests. Usually tests take far less than 1 ms, in which case this scheme works perfectly. However from time to time you have 1 test that runs for a couple of seconds. If you run 5000 tests you have to run quite a few tests to get that 1% update margin, so very often the UI does not correctly report the current status.
That is not a solvable problem. A progress bar depends on a value increasing from min to max. The model is responsible for making reasonable steps.
ok, different question, how do you solve this very use-case without polling?
1. run test 1 [1ms] ..... N. run test N [1ms] ------------------------------------------- Progress Bar update limit reached after a) either N update calls b) N ms => next update will happen in a) N calls b) N ms ------------------------------------------- N+1. run test N+1 [1000 ms]
That means that the UI shows the wrong value (run test N) instead of the current progress value (run test N+1), which is not interesting. The model, in this case the test runner, properly informed the UI about every change, but the update limitations in the ProgressBarMorph cannot properly detect such a case. - either you update way to often => performance overhead - or you update not often enough => inaccurate progress indication when progress step times differ a lot
There is simply no way you can properly solve this case without active polling.
Sure there is. (Assuming tests are run at lower-than GUI priority so it actually gets a chance to update without forced refresh directly from the code) - Record the state of Job when it's announced. - Check a boolean for whether a GUI update is already scheduled. - If not, check the last update time - If update interval since then has passed, send an invalidate to the GUI (with you as model, painting current value of the state last recorded in you), and record the new update time - If less than interval, set the GUI update schedule boolean to true, fork of a process (at a higher-than-current priority) which waits for the remainder before doing the same as the none-delayed path, then resetting the GUI update boolean. Cheers, Henry
On 2013-09-06, at 04:52, Henrik Johansen <henrik.s.johansen@veloxit.no> wrote:
On Sep 4, 2013, at 12:12 , Camillo Bruni <camillobruni@gmail.com> wrote:
On 2013-09-03, at 18:57, Stephan Eggermont <stephan@stack.nl> wrote:
Camillo wrote:
in this case it is only the instance of Job which knows the status. Thread-safeness is not an issue since the progress bar is pure approximation.
The problem is not approximation. Objects are not reentrant, getting the value out of a model while it is reorganizing its datastructure is likely to give interesting and difficult to reproduce results (dividing by 0, nil-pointer exceptions).
that does not work properly and inaccurately reports long running jobs, for instance when running tests. Usually tests take far less than 1 ms, in which case this scheme works perfectly. However from time to time you have 1 test that runs for a couple of seconds. If you run 5000 tests you have to run quite a few tests to get that 1% update margin, so very often the UI does not correctly report the current status.
That is not a solvable problem. A progress bar depends on a value increasing from min to max. The model is responsible for making reasonable steps.
ok, different question, how do you solve this very use-case without polling?
1. run test 1 [1ms] ..... N. run test N [1ms] ------------------------------------------- Progress Bar update limit reached after a) either N update calls b) N ms => next update will happen in a) N calls b) N ms ------------------------------------------- N+1. run test N+1 [1000 ms]
That means that the UI shows the wrong value (run test N) instead of the current progress value (run test N+1), which is not interesting. The model, in this case the test runner, properly informed the UI about every change, but the update limitations in the ProgressBarMorph cannot properly detect such a case. - either you update way to often => performance overhead - or you update not often enough => inaccurate progress indication when progress step times differ a lot
There is simply no way you can properly solve this case without active polling.
Sure there is. (Assuming tests are run at lower-than GUI priority so it actually gets a chance to update without forced refresh directly from the code) - Record the state of Job when it's announced. - Check a boolean for whether a GUI update is already scheduled. - If not, check the last update time - If update interval since then has passed, send an invalidate to the GUI (with you as model, painting current value of the state last recorded in you), and record the new update time - If less than interval, set the GUI update schedule boolean to true, fork of a process (at a higher-than-current priority) which waits for the remainder before doing the same as the none-delayed path, then resetting the GUI update boolean.
... which is 2 tmes more complicated than polling, but ok, it is possible
On Sep 6, 2013, at 1:35 , Camillo Bruni <camillobruni@gmail.com> wrote:
On 2013-09-06, at 04:52, Henrik Johansen <henrik.s.johansen@veloxit.no> wrote:
On Sep 4, 2013, at 12:12 , Camillo Bruni <camillobruni@gmail.com> wrote:
On 2013-09-03, at 18:57, Stephan Eggermont <stephan@stack.nl> wrote:
Camillo wrote:
in this case it is only the instance of Job which knows the status. Thread-safeness is not an issue since the progress bar is pure approximation.
The problem is not approximation. Objects are not reentrant, getting the value out of a model while it is reorganizing its datastructure is likely to give interesting and difficult to reproduce results (dividing by 0, nil-pointer exceptions).
that does not work properly and inaccurately reports long running jobs, for instance when running tests. Usually tests take far less than 1 ms, in which case this scheme works perfectly. However from time to time you have 1 test that runs for a couple of seconds. If you run 5000 tests you have to run quite a few tests to get that 1% update margin, so very often the UI does not correctly report the current status.
That is not a solvable problem. A progress bar depends on a value increasing from min to max. The model is responsible for making reasonable steps.
ok, different question, how do you solve this very use-case without polling?
1. run test 1 [1ms] ..... N. run test N [1ms] ------------------------------------------- Progress Bar update limit reached after a) either N update calls b) N ms => next update will happen in a) N calls b) N ms ------------------------------------------- N+1. run test N+1 [1000 ms]
That means that the UI shows the wrong value (run test N) instead of the current progress value (run test N+1), which is not interesting. The model, in this case the test runner, properly informed the UI about every change, but the update limitations in the ProgressBarMorph cannot properly detect such a case. - either you update way to often => performance overhead - or you update not often enough => inaccurate progress indication when progress step times differ a lot
There is simply no way you can properly solve this case without active polling.
Sure there is. (Assuming tests are run at lower-than GUI priority so it actually gets a chance to update without forced refresh directly from the code) - Record the state of Job when it's announced. - Check a boolean for whether a GUI update is already scheduled. - If not, check the last update time - If update interval since then has passed, send an invalidate to the GUI (with you as model, painting current value of the state last recorded in you), and record the new update time - If less than interval, set the GUI update schedule boolean to true, fork of a process (at a higher-than-current priority) which waits for the remainder before doing the same as the none-delayed path, then resetting the GUI update boolean.
... which is 2 tmes more complicated than polling, but ok, it is possible
The simplest thing is of course to just invalidate on each state change, instead of duplicating DamageRecorder logic to avoid the normal refresh of 50 fps. I don't quite see how N registrations of a small damage rect + 50 refreshes a second of the ProgressBar should make a significant performance impact, but oh well. Cheers, Henry
+1 even more than that: it makes no sense to update something like progress bar on the screen at a rate higher than 20-30 per second, because humans will be unable to notice that anyways.. so if you updating screen more often, know that you just wasting cpu cycles for nothing. That's why the progress bar update should be decoupled from actual job progress and should be updated only when World UI cycle does that but not ASAP. On 6 September 2013 09:52, Henrik Johansen <henrik.s.johansen@veloxit.no>wrote:
On Sep 4, 2013, at 12:12 , Camillo Bruni <camillobruni@gmail.com> wrote:
On 2013-09-03, at 18:57, Stephan Eggermont <stephan@stack.nl> wrote:
Camillo wrote:
in this case it is only the instance of Job which knows the status. Thread-safeness is not an issue since the progress bar is pure approximation.
The problem is not approximation. Objects are not reentrant, getting the value out of a model while it is reorganizing its datastructure is likely to give interesting and difficult to reproduce results (dividing by 0, nil-pointer exceptions).
that does not work properly and inaccurately reports long running jobs, for instance when running tests. Usually tests take far less than 1 ms, in which case this scheme works perfectly. However from time to time you have 1 test that runs for a couple of seconds. If you run 5000 tests you have to run quite a few tests to get that 1% update margin, so very often the UI does not correctly report the current status.
That is not a solvable problem. A progress bar depends on a value increasing from min to max. The model is responsible for making reasonable steps.
ok, different question, how do you solve this very use-case without polling?
1. run test 1 [1ms] ..... N. run test N [1ms] ------------------------------------------- Progress Bar update limit reached after a) either N update calls b) N ms => next update will happen in a) N calls b) N ms ------------------------------------------- N+1. run test N+1 [1000 ms]
That means that the UI shows the wrong value (run test N) instead of the current progress value (run test N+1), which is not interesting. The model, in this case the test runner, properly informed the UI about every change, but the update limitations in the ProgressBarMorph cannot properly detect such a case. - either you update way to often => performance overhead - or you update not often enough => inaccurate progress indication when progress step times differ a lot
There is simply no way you can properly solve this case without active polling.
Sure there is. (Assuming tests are run at lower-than GUI priority so it actually gets a chance to update without forced refresh directly from the code) - Record the state of Job when it's announced. - Check a boolean for whether a GUI update is already scheduled. - If not, check the last update time - If update interval since then has passed, send an invalidate to the GUI (with you as model, painting current value of the state last recorded in you), and record the new update time - If less than interval, set the GUI update schedule boolean to true, fork of a process (at a higher-than-current priority) which waits for the remainder before doing the same as the none-delayed path, then resetting the GUI update boolean.
Cheers, Henry
-- Best regards, Igor Stasenko.
participants (4)
-
Camillo Bruni -
Henrik Johansen -
Igor Stasenko -
Stephan Eggermont