[Home] [Downloads] [Search] [Help/forum]


Register forum user name Search FAQ

Gammon Forum

[Folder]  Entire forum
-> [Folder]  MUSHclient
. -> [Folder]  Bug reports
. . -> [Subject]  performance problem in AddHotspot

performance problem in AddHotspot

It is now over 60 days since the last post. This thread is closed.     [Refresh] Refresh page


Posted by Fiendish   USA  (2,514 posts)  [Biography] bio   Global Moderator
Date Thu 23 Jun 2016 06:23 PM (UTC)

Amended on Thu 23 Jun 2016 06:30 PM (UTC) by Fiendish

Message
The code for mouseover detection for a newly added hotspot in WindowAddHotspot is extremely heavy. It loops over so many things and things in things and other things just to find out what hotspot the mouse is actually over and to call a mouseover function on it.
But you already know that the only thing you need to check is the one hotspot that has just been created because nothing else has changed.

I'm reporting this as a bug and not just an oddity because display code for a high density mapper with 11700 rooms showing takes only 0.12 seconds to do all of the multicolor paintbrushed WindowCircleOps without any hotspots, which is fine, .28 seconds to do the same with hotspots included but the mouse far away from the miniwindow, which is just acceptable with the work broken up into chunks, and 6.5 seconds to do the same while the mouse is over the miniwindow, which is extremely painful and unusable.

https://github.com/fiendish/aardwolfclientpackage
[Go to top] top

Posted by Nick Gammon   Australia  (22,975 posts)  [Biography] bio   Forum Administrator
Date Reply #1 on Thu 23 Jun 2016 08:24 PM (UTC)
Message
What has newly-added got to do with it?

I don't see any loops in AddHotspot.

Quote:

But you already know that the only thing you need to check is the one hotspot that has just been created because nothing else has changed.


Are you saying that hotspot detection, with the mouse over the miniwindow, and there are lots of hotspots, is slow in general?

Can you make up a test case?

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Nick Gammon   Australia  (22,975 posts)  [Biography] bio   Forum Administrator
Date Reply #2 on Fri 24 Jun 2016 02:20 AM (UTC)

Amended on Fri 24 Jun 2016 02:22 AM (UTC) by Nick Gammon

Message
I tested with this alias:


<aliases>
  <alias
   match="hst"
   enabled="y"
   send_to="12"
   sequence="100"
  >
  <send>

win = "test_" .. GetPluginID ()  -- get a unique name, ensure not empty if outside plugin

WindowDelete (win)
WindowCreate (win, 0, 0, 700, 700, miniwin.pos_center_right, 0, ColourNameToRGB("white"))  -- create window
WindowShow (win,  true)  -- show it 


size = 5
offset = 6

function mouseover (flags, hotspot_id)
  SetStatus ("Over " .. hotspot_id)
end -- mouseover 

start = utils.timer ()
for x = 1, 110 do
  for y = 1, 110 do

    WindowRectOp(win, miniwin.rect_frame, x * offset, y * offset, x * offset + size, y * offset + size, 0)

    WindowAddHotspot(win, string.format ("hotspot_x%%d_y%%d", x, y),  
                   x * offset, y * offset, x * offset + size, y * offset + size,   -- rectangle
                   "mouseover", 
                   nil, -- "cancelmouseover", 
                   nil, -- "mousedown",
                   nil, -- "cancelmousedown", 
                   nil, -- "mouseup", 
                   "Click here for fun times",  -- tooltip text
                   miniwin.cursor_hand, 0)  -- hand cursor

  end
end

finish = utils.timer ()

print (string.format ("Took %%0.3f seconds to do that", finish - start))

</send>
  </alias>
</aliases>



Running that takes around 119 milliseconds:


Took 0.119 seconds to do that


That is deleting and re-creating 12100 hotspots. Doesn't seem to be affected if the mouse is over the miniwindow.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Fiendish   USA  (2,514 posts)  [Biography] bio   Global Moderator
Date Reply #3 on Fri 24 Jun 2016 04:13 AM (UTC)

Amended on Fri 24 Jun 2016 04:14 AM (UTC) by Fiendish

Message
Remove the line calling WindowDelete(win) and try it again.

Now that's an interesting result.

https://github.com/fiendish/aardwolfclientpackage
[Go to top] top

Posted by Nick Gammon   Australia  (22,975 posts)  [Biography] bio   Forum Administrator
Date Reply #4 on Fri 24 Jun 2016 04:54 AM (UTC)
Message
OK, it's 10 times as slow. Why, I'm not sure unless it is this code:


  // in mouse was over hotspot when it was created, do a "mouse move" to detect this
  if (status == eOK)
    {
    for(POSITION pos=GetFirstViewPosition();pos!=NULL;)
	    {
	    CView* pView = GetNextView(pos);
	    
	    if (pView->IsKindOf(RUNTIME_CLASS(CMUSHView)))
        ((CMUSHView*)pView)->Mouse_Move_MiniWindow (this, m_lastMousePosition);
      } // end of looping through views
    } // end of added hotspot OK


Can you delete all hotspots in your scenario?

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Nick Gammon   Australia  (22,975 posts)  [Biography] bio   Forum Administrator
Date Reply #5 on Fri 24 Jun 2016 04:55 AM (UTC)
Message
In your test case, are you adding lots of hotspots? Or just deleting and re-adding one?

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Nick Gammon   Australia  (22,975 posts)  [Biography] bio   Forum Administrator
Date Reply #6 on Fri 24 Jun 2016 05:00 AM (UTC)
Message
In case anyone is wondering, this is what 12100 hotspots look like:


- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Fiendish   USA  (2,514 posts)  [Biography] bio   Global Moderator
Date Reply #7 on Fri 24 Jun 2016 04:29 PM (UTC)

Amended on Fri 24 Jun 2016 05:10 PM (UTC) by Fiendish

Message
Quick test. In the version of the hst alias without any call to WindowDelete, run it first without your mouse in the miniwindow, then try running it with your mouse in the top left hotspot. And then run it with your mouse in the bottom right hotspot. I get 0.212, 1.1, and 6.3 seconds respectively.

My first thought is that this is because hotspot activity stops looking for callbacks on first hit, which is why we can't overlap hotspots. My second thought is that the search must be happening in reverse order of creation. My third thought is that only the new hotspot is changing, not the mouse or anything else, so there shouldn't be any kind of search happening at all.

I see a similar time effect in my plugin where the closer the mouse is to the middle of the map (where the player is, and where rooms first start being drawn) the longer it takes to complete.

Quote:
In your test case, are you adding lots of hotspots? Or just deleting and re-adding one?

In my plugin I am calling WindowDeleteAllHotspots and then creating 12000 new hotspots. Using WindowDelete+WindowCreate instead of WindowDeleteAllHotspots has some slight improving effect, but is still quite slow in my plugin in a way that doesn't yet seem to be reproduced by your alias. It also introduces some other visual complications that make it painful to change to.

(But in the both cases, why does omitting WindowDelete have any effect at all?)

https://github.com/fiendish/aardwolfclientpackage
[Go to top] top

Posted by Nick Gammon   Australia  (22,975 posts)  [Biography] bio   Forum Administrator
Date Reply #8 on Fri 24 Jun 2016 09:50 PM (UTC)
Message
I would have to do some profiling to work out exactly where the problem area is. Every a few dozen microseconds, multiplied by 10000, is going to be noticeable.

Quote:

In my plugin I am calling WindowDeleteAllHotspots and then creating 12000 new hotspots.


I don't think offhand that the problem is with a particular hotspot, just that for every AddHotspot some test is taking longer because some initial condition is met (eg. the mouse being over the miniwindow) and that test is then done 10000 times. So it isn't a case of only doing it for the most recent hotspot, it is a case of making the test faster.

Quote:

And then run it with your mouse in the bottom right hotspot. I get 0.212, 1.1, and 6.3 seconds respectively.


I seem to be getting slower response on the RH side in general (X being high) rather than top to bottom per se.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Nick Gammon   Australia  (22,975 posts)  [Biography] bio   Forum Administrator
Date Reply #9 on Fri 24 Jun 2016 10:11 PM (UTC)

Amended on Sat 25 Jun 2016 04:40 AM (UTC) by Nick Gammon

Message
As a quick test I commented out the code in reply #4 and the time now seems constant. So it is definitely that test that is doing it. And I suspect that the more hotspots that have to be checked (and therefore ruled in/out) the slower it is.

To summarize:


  • When you add a hotspot it fakes a "mouse move" in order to detect if the mouse is now over the new hotspot (and generate the correct function callbacks)
  • If the mouse is not over the miniwindow the test is quick, and takes 30 µs.
  • If the mouse is over an early hotspot in the list, the test is slower and takes 123 µs.
  • If the mouse is over a late hotspot in the list, the test (presumably done more times) is slower again and takes 627 µs.


None of these times are earth-shatteringly slow, however when you do then 12000 times, then you notice the difference.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Nick Gammon   Australia  (22,975 posts)  [Biography] bio   Forum Administrator
Date Reply #10 on Fri 24 Jun 2016 10:26 PM (UTC)
Message
Fiendish said:

My first thought is that this is because hotspot activity stops looking for callbacks on first hit, which is why we can't overlap hotspots. My second thought is that the search must be happening in reverse order of creation.


The function Mouse_Over_Miniwindow is definitely the one that causes the slowdown. If I comment that out the time is fast. Or - the fact that it gets a match slows things down - I am still experimenting with that.

You can overlap hotspots, and one on top is the one detected.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Nick Gammon   Australia  (22,975 posts)  [Biography] bio   Forum Administrator
Date Reply #11 on Sat 25 Jun 2016 03:44 AM (UTC)
Message
I've added an optimization:

https://github.com/nickgammon/mushclient/commit/bd54a9d

This seems to help with my test case.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Nick Gammon   Australia  (22,975 posts)  [Biography] bio   Forum Administrator
Date Reply #12 on Sat 25 Jun 2016 04:30 AM (UTC)
Message
There may be side-effects. I suggest you keep an eye on the behaviour when you test it. Basically what the test does is only do the time-consuming stuff if we think the cursor is over the newly-added hotspot. So if you are adding 10000 hotspots, the lower-level tests will be done once, not 10000 times.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Fiendish   USA  (2,514 posts)  [Biography] bio   Global Moderator
Date Reply #13 on Sat 25 Jun 2016 05:04 AM (UTC)
Message
Nick Gammon said:

There may be side-effects.

I can't think of any scenario that would cause one given that it looks you still loop on an actual match. So conceivably if you were going to do cancelmouseout on an underneath hotspot it'd still happen.

https://github.com/fiendish/aardwolfclientpackage
[Go to top] top

Posted by Nick Gammon   Australia  (22,975 posts)  [Biography] bio   Forum Administrator
Date Reply #14 on Sat 25 Jun 2016 06:56 AM (UTC)
Message
Agreed. But bugs have a way of subtly introducing themselves. :)

I suggest you test extensively before deploying.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

The dates and times for posts above are shown in Universal Co-ordinated Time (UTC).

To show them in your local time you can join the forum, and then set the 'time correction' field in your profile to the number of hours difference between your location and UTC time.


28,924 views.

It is now over 60 days since the last post. This thread is closed.     [Refresh] Refresh page

Go to topic:           Search the forum


[Go to top] top

Quick links: MUSHclient. MUSHclient help. Forum shortcuts. Posting templates. Lua modules. Lua documentation.

Information and images on this site are licensed under the Creative Commons Attribution 3.0 Australia License unless stated otherwise.

[Home]


Written by Nick Gammon - 5K   profile for Nick Gammon on Stack Exchange, a network of free, community-driven Q&A sites   Marriage equality

Comments to: Gammon Software support
[RH click to get RSS URL] Forum RSS feed ( https://gammon.com.au/rss/forum.xml )

[Best viewed with any browser - 2K]    [Hosted at HostDash]