Thanks to visit codestin.com
Credit goes to github.com

Skip to content

MNT: overhaul stale handling #4738

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 30 commits into from
Aug 14, 2015

Conversation

tacaswell
Copy link
Member

Closes #4732

@tacaswell tacaswell added this to the next point release milestone Jul 18, 2015
Only propagate stale state to the figure from it's direct children,
not all artists.  This is to prevent double call backs when using
interactive mode with backends which do not implement an asynchronous
draw_idle.
This is to match the behavior of artists being uniquely associated with
a single Axes.
If a draw has been forced, but either the figure or axes is not stale
some of the draw processes will cause them to become scale (because
the current implementation is naive and does no check if values have
changed so no-op sets still mark the artist as stale).  By setting
_stale to be True the stale events will not propagate past the
axes/figure and schedule another redraw.

This only really matters for Canvas classes which do not implement an
asynchronous `draw_idle`.  If there is an asynchronous `draw_idle` the
additional draw requests will be ignored until the current draw
is finished anyway.
@WeatherGod
Copy link
Member

This PR actually only has a single failure (the same in all python versions):

======================================================================
FAIL: matplotlib.tests.test_offsetbox.test_offsetbox_clip_children
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/travis/build/matplotlib/matplotlib/venv/lib/python2.6/site-packages/nose/case.py", line 197, in runTest
    self.test(*self.arg)
  File "/home/travis/build/matplotlib/matplotlib/venv/lib/python2.6/site-packages/matplotlib-1.5.dev1-py2.6-linux-x86_64.egg/matplotlib/testing/decorators.py", line 110, in wrapped_function
    func(*args, **kwargs)
  File "/home/travis/build/matplotlib/matplotlib/venv/lib/python2.6/site-packages/matplotlib-1.5.dev1-py2.6-linux-x86_64.egg/matplotlib/tests/test_offsetbox.py", line 83, in test_offsetbox_clip_children
    assert_true(fig.stale)
AssertionError

When setting the axes of an offset box to propagate to it's children.
@tacaswell
Copy link
Member Author

Turns out the issue was that funny things were happening with the offsetbox subclasses which was getting masked by the fact that before artists were pinging both the axes and the figure, now they just hit the figure.

There are probably a bunch more issues like this that we will slowly find...

@tacaswell tacaswell force-pushed the fix_repl_ensure_fig_unstale branch from d168e59 to b39fd90 Compare July 31, 2015 04:05
@tacaswell
Copy link
Member Author

@rmorshea the stale callbacks have been simplified to not use pchanged anymore. I think this will make replicating the current proposed behavior easier.

Always propagate stale up (even if immediate parent is stale)
@mdboom
Copy link
Member

mdboom commented Aug 6, 2015

I definitely see this as an improvement, modulo investigating the Travis failure. Possibly more to do over time, but I don't see any reason not to do this much now.

@tacaswell
Copy link
Member Author

The travis issue is triggering draws in a draw. This is caused by:

  • not checking if anything actually changed, just setting stale on every setter so stale gets triggered during draws
  • the stale state now propagating past existing stale = True states
  • Agg not having an asynchronous draw method and draw_idle just passing through to draw.

@mdehoon makes the very good point that due to our late validation of values if you set an invalid value you don't find out until draw time. If the stale state does not propagate past the existing stale artists and you are using plain python then a re-draw won't be triggered the next time the value is changed (as implemented with IPython it will work fine as-is).

The solutions to this that I see are:

  • put back in the short circuit logic back in and tell people not to use plain python (I am +0 on this, and @mdehoon is -1)
  • do proper validation and change determination in ever setter (I am -1 on this as traitlets will take care of this)
  • make Agg's draw_idle re-entrant (I am +0 and am guessing @mdehoon is +1)

I am working on adding a commit to make the base draw_idle re-entrant.

Calling `draw_idle` while executing a `draw_idle` will no-longer
infinitely recurse.
@tacaswell
Copy link
Member Author

I think this is ready to go again.

@WeatherGod
Copy link
Member

Still, I don't see the value in using sets here, and I don't like that it works now on a technicality. A list would work just fine. It isn't like we are expecting to have many figures to check against. At the extreme end, i would imagine someone doing something fancy with 10 figures, but typically, only 1 or 3 figures.

@dopplershift
Copy link
Contributor

I disagree about it working on a "technicality"--this is documented python behavior, essentially making the in check work using is. In fact, using in (which uses __eq__) ends up on the same code path as hash:

User-defined classes have __eq__() and __hash__() methods by default; with them,
all objects compare unequal (except with themselves) and x.__hash__() returns an
appropriate value such that x == y implies both that x is y and hash(x) == hash(y).

(https://docs.python.org/3/reference/datamodel.html#object.__eq__)

However, I do agree that there is essentially no performance difference in our real-world scenarios here.

@WeatherGod
Copy link
Member

Ok, just tried out this branch. I was doing an imshow of a very large array (3600x7000), and a basemap plot and using the TkAgg backend. Watching "top" in another terminal, I see the memory usage increasing every time my mouse passes over the figure window. It never goes back down. The amount of memory increases by hundreds of MB for a quick pass over the window.

I don't know yet if it is because of this PR, or if it is due to some unfixed issue with stale flags, or something else entirely. Just noting it here for the moment.

@WeatherGod
Copy link
Member

Joys... this is on master and this branch. Furthermore, once you pass over the figure window, the memory usage keeps creeping up, even though the mouse is no longer over the window.

@tacaswell
Copy link
Member Author

Try commenting out the mouse hover logic in backed base.

On Wed, Aug 12, 2015, 2:27 PM Benjamin Root [email protected]
wrote:

Joys... this is on master and this branch. Furthermore, once you pass over
the figure window, the memory usage keeps creeping up, even though the
mouse is no longer over the window.


Reply to this email directly or view it on GitHub
#4738 (comment)
.

@WeatherGod
Copy link
Member

Yup, looks like commenting out the contents of NavigationToolbar2.mouse_move "fixed" the problem. Do you think it is a bug to be dealt with here or shall I file a new issue?

@tacaswell
Copy link
Member Author

Tack it on to the pr where i am working on removing hit list

On Wed, Aug 12, 2015, 2:41 PM Benjamin Root [email protected]
wrote:

Yup, looks like commenting out the contents of
NavigationToolbar2.mouse_move "fixed" the problem. Do you think it is a
bug to be dealt with here or shall I file a new issue?


Reply to this email directly or view it on GitHub
#4738 (comment)
.

tacaswell added a commit to tacaswell/matplotlib that referenced this pull request Aug 14, 2015
 - disconnect the stale_callback (this assumes that matplotlib#4738 goes in)
 - remove the artist from the Axes.mousover_set
 - marks the parent axes/figure as stale
 - resets the artist's axes/figure to None
James Evans and others added 7 commits August 13, 2015 21:42
Artists do not properly guard against being removed from figures or Axes
when tracking 'stale'. This will keep them from throwing an exception if
they become stale after being removed from an Axes or Figure.
Look at figures, not axes, and use a set
 - short circuit if not really chaning state
 - don't fire stale trigger on changing animation state
When using blitting in animation make sure to set the blitted artsts as
animated so that changing their state does not trigger the normal stale
-> draw_idle cascade.
@tacaswell tacaswell force-pushed the fix_repl_ensure_fig_unstale branch from ce80568 to 25079bf Compare August 14, 2015 01:43
@jenshnielsen
Copy link
Member

I can still reproduce the original issue in #4732 when interactivity is on i.e. plt.ion()
However I can also reproduce the issue on 1.4.3 so I not really cure what to make of this

@jenshnielsen
Copy link
Member

I.e if I call set_dashes('--') it triggers that exception on every draw until call set_dashes((1,1)) or whatever but surely that is just missing input validation?

@tacaswell
Copy link
Member Author

That is the expected behavior, the problem was that previously correcting
the value would not trigger a redraw at all and the was no obvious way to
do so.

On Fri, Aug 14, 2015, 4:25 PM Jens Hedegaard Nielsen <
[email protected]> wrote:

I.e if I call set_dashes('--') it triggers that exception on every draw
until call set_dashes((1,1)) or whatever but surely that is just missing
input validation?


Reply to this email directly or view it on GitHub
#4738 (comment)
.

@jenshnielsen
Copy link
Member

@tacaswell That makes sense. However, I can't reproduce that on current master.

set_dashes((3,'3)) after set_dashes(('--')) correctly triggers the redraw so it seems that either this has already been fixed by something else or I am doing something stupid. In any case this is an improvement to the stale login so I will go ahead and merge it

jenshnielsen added a commit that referenced this pull request Aug 14, 2015
@jenshnielsen jenshnielsen merged commit 212b0ff into matplotlib:master Aug 14, 2015
@tacaswell
Copy link
Member Author

Are you using ipython or plain python? The redraw logic is different in the
two cases.

On Fri, Aug 14, 2015, 4:46 PM Jens Hedegaard Nielsen <
[email protected]> wrote:

Merged #4738 #4738.


Reply to this email directly or view it on GitHub
#4738 (comment).

@jenshnielsen
Copy link
Member

plain python

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants