Skip to content
This repository has been archived by the owner on Jul 29, 2019. It is now read-only.

Timeline Issue: Sometimes the redraw cycle can become stuck in an infinite loop #450

Closed
brichbe opened this issue Nov 18, 2014 · 51 comments
Closed

Comments

@brichbe
Copy link

brichbe commented Nov 18, 2014

I've been using the timeline product (v3.6.4 - v3.7.0) for a few weeks now and so far it's been great for supporting my use case. My application provides a tree structure where the user can see all the data that's available to them, and then once they select a node of that tree, that sub-set of the user's data is displayed on the timeline.

The data being displayed on the timeline is relatively simple right now -- only a few groups, background items, and range items -- that span across 2-10 days. Each time the user chooses a new tree node to display, I populate the timeline with that new sub-set of data by completely re-creating my item and group DataSets. This is probably not the most elegant way to re-populate the timeline with different data (as opposed to something like a filter), but for my use case it's been working perfectly fine the majority of the time.

Unfortunately, the browser will sometimes completely freeze after giving a new sub-set of the data to the timeline for display. The freeze is caused by an infinite (or very long running) loop in the redraw cycle of the various timeline components.

When I give my user's data sub-set to the timeline, I do so in a few distinct back-to-back steps:

  • First I create the necessary group(s) in a new DataSet
  • Next I create the necessary background and range item(s) in another new DataSet
  • I set these two DataSets into the timeline
  • Finally I set the timeline window to span the entire range of those background/range items
  • (I really don't believe there are any issues with these steps, because like I said above, most of the time this all works perfectly fine)

After each of those steps occur, the timeline redraws itself via the Core redraw function

  • This Core function causes each of the timeline's top-level components to also redraw themselves as necessary
  • This Core function also ends up calling itself again if it's determined that one of the components was resized

Obviously, the Core redraw function calling itself should behave in a safe recursive manner so that sequence of calls stops relatively quickly and efficiently. Indeed, it normally does stop after a few redraw cycles.

However, I've found there are also times when that redraw cycle does not stop as it should. When this infinite looping issue occurs, so far I've been able to trace that the following is happening:

  • Each and every time the Core redraw function triggers a redraw of its components, the TimeAxis and ItemSet components continuously return true (identifying they've been resized and therefore the entire redraw cycle should repeat)
  • For the TimeAxis I've found the reason it always returns true is because it looks to see if its current width/height match the previous width/height
    • The props.width value is set from the frame.offsetWidth
    • I'm seeing each time through the redraw cycle, props.width is being set to alternating values for some strange reason (in my case, 1114, then 1116, then 1114 again, then 1116 again, and so on)
    • Because it alternates back and forth, the current width value is always different than the previous width value, thus the redraw cycle continues endlessly

I may continue to investigate if the ItemSet is continuously returning true for the same reason, but hopefully the info above is enough to help others investigate and reproduce this issue.

Since the browser becoming frozen is clearly a critical issue for my application, I'll try implementing a temporary workaround fix (like using a simple counter to set a maximum number of recursive redraws) for the near-term until a more official fix can be made.

@Blugh
Copy link

Blugh commented Nov 19, 2014

Hi brichbe

I have the exact same issue where the widths are inconsistent and causing infinite redraws. You have explained the issue a lot better than I did, so hopefully the guys can find a fix. Thank You.

@josdejong
Copy link
Contributor

@brichbe thanks for your detailed analysis. The alternating widths (1114, 1116, ...) sounds like an offset related to two borders of 1px.

@Blugh or @brichbe would it be possible to create a jsfiddle/jsbin to demonstrate the problem? I haven't yet succeeded in reproducing this issue, but its very important to get this fixed.

btw this is a duplicate of #441, started by @Blugh

@Blugh
Copy link

Blugh commented Nov 19, 2014

@josdejong can you try setting the item margin value to 0px or -1px and see if that reproduces the issue? My items currently have a 0px margin so that they do not stack if the end of 1 item = start of the next item. Otherwise it may take a while to create a js fiddle as my js is rather long.

@brichbe
Copy link
Author

brichbe commented Nov 19, 2014

Whoops didn't mean to submit a duplicate -- I'd read #441 the previous day but completely forgot about it once I completed my analysis and wrote it all up. Doh!

I agree with @Blugh -- I'm not so sure it will be easily duplicated with a simple demonstration, unfortunately, because of the fact that this issue does not occur consistently. I do in fact have some 1px borders around certain portions of my application (including the timeline) and I also do have some margin settings for my timeline items. But what makes this a difficult bug is that you would think if the problem is related to borders or margins, that the issue would happen all the time with the same setup, not just occasionally. Once my page is loaded, all the borders and margins are set, so it is certainly odd that I can update the timeline just fine sometimes but not others when there is no obvious difference in the data being used each time and the borders/margins aren't explicitly being changed any time either.

Rather than focus on borders/margins, should we instead consider the validity of the redraw cycle logic and whether the recursive design should be improved (since there's obvious potential for it to run continuously)? For example, is it fair to say that the redraw cycle should happen no more than 5 times in any situation (whether there are 2 groups/items or 2000 groups items)? Or do you expect that cycle to execute some number of times that's proportional to the number of groups/items being displayed? Either way, maybe the better long-term solution here is finding and implementing a maximum number of recursive redraw calls that can be made during any single update operation, rather than spending our time finding some very odd corner case of border/margin value that just so happens to trigger this bug.

@josdejong
Copy link
Contributor

@Blugh I haven't been able to reproduce this issue so far. I've tried margin 0, -1, 1/3, 0.1+0.2, etc.

To prevent this issue, I've added loop protection (see code). If I'm not mistaken a maximum loop count of 2 should do, but I have to do some more testing. This should at least prevent the browser from getting stuck in an infinite loop.

Still, we need to find the cause of this issue. Is there a way any of you can put some example online where the infinite loop happens somewhere so I can do some testing?

@josdejong josdejong mentioned this issue Nov 21, 2014
@josdejong
Copy link
Contributor

@Blugh @brichbe @ivan-kleshnin what OS and screen size you you guys have? Apparently its not "just" Chrome causing the issue.

@brichbe
Copy link
Author

brichbe commented Nov 21, 2014

@josdejong I implemented and tested my own workaround fix that's very similar to yours for loop protection and I agree with you -- 2 redraws does the job. So although yes it would be great to find the true root cause of this issue, it's good to know the loop protection is rather harmless (minimal performance impact and effect on the design) and could still be used to protect against similar future issues even if the root cause is found elsewhere.

I've been using:

  • Win7 Pro SP1
  • 27" monitor at 1920x1080
  • Chrome v38.0.2125.111

Also, my app layout is using some features of GWT, so it would be interesting if others having this problem are also using GWT?

@Blugh
Copy link

Blugh commented Nov 22, 2014

i am using a laptop, win 7 sp1 pro, 1600x900 res. same version of Chrome as @brichbe

@ivan-kleshnin
Copy link

I'm using OS X 10.9.5 with 1680 x 1050 resolution, Chrome 39.0.2171.65

@josdejong
Copy link
Contributor

@alex I think 2 redraws is enough, I've tested both Timeline and Graph2d. If these two redraws are exceeded, a console message is logged "WARNING: infinite loop in redraw?", so you can easily check this.

@ghost
Copy link

ghost commented Mar 18, 2015

I encountered the same problem in IE9 with vis version 3.11.0
Unfortunately i do not have the time to make a jsfiddle demo at this time but i did test some things which maybe helps by fixing the problem.

  • The bug is not showing in IE11 in IE9 mode, but it is in a actual IE9 browser
  • Option variations
    margin axis 1, item.horizontal 0, item.vertical 5 >>> a lot of infinite loop warnings in the console
    margin axis 1, item.horizontal -1, item.vertical 5 >>> 2x infinite loop warnings
    margin axis 1, item.horizontal -1, item.vertical 0 >>> 1x infinite loop warnings
    margin axis 0, item.horizontal -1, item.vertical 5 >>> 2x infinite loop warnings
    margin axis 0, item.horizontal -1, item.vertical 0 >>> NO infinite loop warnings

After being really happy with the empty console i added maxHeight: "800px" and minHeight: "400px" which again caused one infinite loop warning.
Changing it to maxHeight: "400px" , minHeight: "50px" seemed to be the solution (no warnings) , but after a redraw on changing one date (via the form on the page) caused a lot of infinite loop warnings in the console again. Until i clicked the calendar, which made the calendar redraw like it should ....

I hope this will help you find the problem
I'll make a demo once i have the time (and if it's still needed then)

@josdejong
Copy link
Contributor

Thanks for letting us know.

I've created a jsbin here with the options you describe: http://jsbin.com/vaheno/1/edit

I didn't succeed in reproducing the issue yet, maybe you can adjust the jsbin with your data.

@carueda
Copy link

carueda commented Mar 28, 2015

In one of my applications I'm just noticing the WARNING: infinite loop in redraw? only while in some browser zoom levels via the typical Cmd-+ or Cmd-- keystrokes (note: not via visJs's zoom capability).

This is on a Mac with OSX 10.10.2

  • Chrome 41.0.2272.101: warning only in first zoom-in level (right after one single Cmd-+)
  • Firefox 36.0.1: warning only in some zoom-out levels
  • Couldn't reproduce with: Safari 8.0.4, Opera 28, Canary 43.

Sorry, it would take some time to put a jsbin, but hope the above helps somehow.

@ignjat
Copy link

ignjat commented May 14, 2015

I can easily reproduce this when I set zoom factor to 67% in Chrome 42-44 on any OS. #1 bug in Graph2D IMHO. It happens with: http://visjs.org/graph2d_examples.html

@josdejong
Copy link
Contributor

Thanks for the feedback. I'm not aware of the existence of Chrome 43 and 44 but maybe you know more that me ;)

I've opened http://visjs.org/examples/graph2d/01_basic.html at 67% zoom in Chrome 42 on linux, Firefox 38 on linux, Chrome 42 on Win7. Also tried with other zoom levels. But no success in reproducing the issue so far :(.

@ignjat
Copy link

ignjat commented May 19, 2015

Since Chrome 42 is GA version Chrome 43 is beta and Chrome 44 is dev (also available as Canary nightly build). I use them often to test my apps against changes in upcoming versions. I personally tested on OS X and Windows 7 and a colleague of mine tested 42 on Linux and we could reproduce. One quick way to force it to happen is to quickly change zoom factor while it's being rendered (I get that this is a non realistic stress test but it may help with reproduction, for us it happens even without it fairly regularly). In about a week I hope to be able to spend some time on it if it doesn't get fixed by then since it's a major issue for one of my apps. Thanks.

@AlexDM0
Copy link
Contributor

AlexDM0 commented May 19, 2015

So is the layout messed up because of this or is the only real problem the console message? I assume it's pretty much just one pixel flicking back and forth?

@ignjat
Copy link

ignjat commented May 19, 2015

The graph doesn't get drawn at all and CPU gets consumed for a few seconds.

@josdejong
Copy link
Contributor

Thanks for the extra info. I now get the issue repeated when you load for example 01_basic.html, put your mouse on an empty area on the page, and start zooming the browser window like crazy using ctrl+scrollwheel. In my case the messages occur when zooming in the range of 110% to 175%. It does not freeze my browser though: there is a prevention mechanism which prevents getting stuck in an infinite loop and stops after 3 iterations (and logs a message in the console then), that seems to work fine.

Are you sure that the initial freeze on load is due to this infinite loop warning? Does this initial freeze also happen in these examples like 01_basic.html?

@ignjat
Copy link

ignjat commented May 19, 2015

I should have clarified. Apologies. The CPU consumption happens in my app because the graph falls in a loop and the dataset is really large. That specific symptom can not be reproduced by the example page. I was quickly responding to AlexDM0's question as to what kind of a problem this presents.
We believe we have found a workaround for now by doing:
document.firstElementChild.style.zoom = "reset";
While it has unwanted side effects it seems to prevent the problem.

@robbrit
Copy link

robbrit commented Mar 29, 2016

As a note, I was able to reliably reproduce the infinite loop on older versions of vis.js by just zooming in and out fairly quickly; but on the newest version on the examples I can't reproduce it at all. I'll try bumping our version of it to see if that fixes things and let you know.

@marcortw
Copy link
Contributor

Looks like a rather old issue, but I ran into this with firefox 46.0.1 (no problem with chrome 51.0.2704.63). I guess the issue was there before, but I never found it because i'm primarily testing with chrome. I'm using bootstrap and place multiple timelines on the same page with a bunch of nested containers. I don't know much about CSS, and i'm unsure what this change actually does, but my problem seemed to be solved when setting:

.vis-panel {
    box-sizing: content-box;
}

If that might help somebody...?

@jgorene
Copy link

jgorene commented Apr 16, 2017

Just for info...
For some time now, I do not find this message "WARNING: an infinite loop in redrawing?" That I had systematically before on timeline whatever the "size of the data", also on Chrome or Firefox with the latest update and using version 19.1
A prioiri, without significant impact on performance but good deal anyway, thank you...

@blin4444
Copy link

blin4444 commented Apr 18, 2017

This bug is still happening for me on 4.19.1. It seems to be related to the line:

var MAX_REDRAW = 5;

in Core.prototype._redraw.

I can reproduce this on my application by zooming in or zooming out on the page (browser zoom) 6 times. The graph will simply disappear. In some graphs it happens on the first zoom.

EDIT: The issue does not always happen on the 6th time. But it eventually happens when zooming multiple times.

@blin4444
Copy link

blin4444 commented Apr 18, 2017

The following page seems to exhibit the issue.

<!DOCTYPE html>
<html>
    <head>
        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/vis/4.19.1/vis.min.css" />
        <script src="https://cdnjs.cloudflare.com/ajax/libs/vis/4.19.1/vis.min.js"></script>
        
        <script>
            function initVis() {
                var container = document.getElementById('graph')

                items = [
                    {x: 0, y: 1},
                    {x: 1, y: 2},
                    {x: 2, y: 3}
                ]

                var options = {
                   height: '400px'
                }

                new vis.Graph2d(container, items, null, options)

                //problem does not occur with:
                //new vis.Graph2d(container, items)
            }

            document.addEventListener("DOMContentLoaded", initVis);
        </script>
    </head>
    <body>
        <div class="graph" id="graph">
        </div>
    </body>
</html>

http://jsbin.com/puweyikisi/edit?html

The problem occurs when zooming in or out multiple times. For me, the graph disappears in the following cases:

  • Safari 10.0.3: start at 100%, zoom in 4 times with (Cmd-+)
  • Chrome 57.0.2987.133: start at 100%, zoom in 4 times to 175%
  • Firefox 52.0.2: start at 100%, zoom out once (Cmd--)
  • Internet Explorer 11.0.9600.18538: could not reproduce problem

It seems the issue disappears if I remove these lines in LineGraph.prototype._updateGraph:

if (changeCalled == true) {
  DOMutil.cleanupElements(this.svgElements);
  this.abortedGraphUpdate = true;
  return true;
}

Seemingly, this is an optimization that cancels the current graph update because another one is needed, but the expected graph update does not occur because the redraw limit gets reached.

Resolution: 1920×1200
OS: macOS Sierra 10.12.3

@murli2308
Copy link

I am also facing the same issue. timeline is continuously redrawing. I am using the latest version of it 4.19.1.

I tried all the solutions mentioned above but none of it working for me. I am facing this issue on macbook pro safari and chrome and on windows VM.

@blin4444
Copy link

This issue is still happening for me on Vis 4.20.0. If you zoom in and out enough times, the graph will eventually disappear.

@bradh
Copy link
Contributor

bradh commented May 23, 2017

I tried on Windows with Firefox, wasn't able to reproduce.

@blin4444
Copy link

blin4444 commented May 23, 2017

I can still consistently reproduce this on Firefox 53.0.3 on Windows 8.1, with a resolution of 1920×1200. Starting at 100%, zooming in 3 times to 133% causes the graph to disappear on the JS Bin. I can also still reproduce it in Safari and Chrome on macOS.

@Swolebrain
Copy link

Issue is still around with 4.20

@HZooly
Copy link

HZooly commented Oct 2, 2017

Same for 4.20.1 on first draw with Chrome 61

@yotamberk
Copy link
Contributor

@torzuoliH Can you try the develop branch? Can you supply a jsbin with this happening?

@HZooly
Copy link

HZooly commented Oct 2, 2017

@yotamberk Is it possible to switch on dev branch with Vis installed as a NPM dependency ?

@antonelepfl
Copy link

Actually a workaround that worked for me was

.vis-panel {
    box-sizing: border-box;
}

@HZooly
Copy link

HZooly commented Oct 4, 2017

@antonelepfl not 100% fix for me. Are you on master or develop branch?

@antonelepfl
Copy link

@torzuoliH I'm using

So I guess it is master
This other solution did not fix it either #450 (comment)?

@jtmarmon
Copy link

jtmarmon commented Oct 18, 2017

vis is actually redrawing in an infinite loop (I can see the graph repeatedly adjusting visually) along with logging the infinite redraw warning. It took me a long time to figure out thanks to this comment that the issue is resolved by zooming my browser to 100%, or down to 80%. 90% is what I was on and was causing the issue.

Another solution for me was to remain at 90% zoom but reduce the width of the containing div. For example, if I have the timeline at 100% width, the bug occurs. If I set the width to 99%, it does not.

Not sure what this implies but hope the extra info helps the maintainers figure it out.

@balteo
Copy link

balteo commented Jan 3, 2018

We are facing the same WARNING: infinite loop in redraw issue.

Is a fix planned in a future version of vis?

@tml123
Copy link

tml123 commented Feb 11, 2018

In v 4.21.0, I hacked the code a bit to at least cut down on the number of times that the console logged "Infinite loop on redraw" by changing MAX_REDRAW to 2 (instead of 5) and taking this.redrawCount = 0 out of the else block that it is inside of in the source. I noticed that this stopped the redrawCount / redraw call from firing after about 2 - 4 redraws. Again, not necessarily pretty, but it at least stopped the infinite loop for me.

Start at about line 10405 in /dist/vis.js:

var MAX_REDRAW = 2;
  if (resized) {
    if (this.redrawCount < MAX_REDRAW) {
      this.body.emitter.emit('_change');
      return;
    } else {
      console.log('WARNING: infinite loop in redraw?');
    }
  }
  this.redrawCount = 0;

Right above (this.redrawCount = 0) used to be inside of an else block in the source, but I taking it out stopped the infinite loop for me.

@meadboater
Copy link

meadboater commented Feb 26, 2018

I have been able to reproduce this using just the example pages.
In Safari (and pretty sure Firefox too) on Mac OS X 10.13.3, zoom in on the page (command +) twice to at least 125% and the problem will occur. I have tested and confirmed this with http://visjs.org/examples/graph2d/05_bothAxis.html
Every graph I have tried zoomed in at least 125% has this problem. Sometimes the entire graph shifts up and down about 1 pixel continuously.
I have found this gets worse if you try to hide/show groups interactively, the graphs are unpredictable as to what will show, sometimes just a blank graph, sometimes takes a while to display anything in the graph.
Hope this helps...

Sadi-1992 pushed a commit to Sadi-1992/vis that referenced this issue Jun 22, 2018
@Sadi-1992
Copy link

Got that fixed. It might be hacky, but its working like a charm. ;)

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

No branches or pull requests