fltkhs icon indicating copy to clipboard operation
fltkhs copied to clipboard

addAndGetMenuItem is suprisingly slow

Open ericu opened this issue 4 years ago • 8 comments

I was profiling to figure out why an operation in my code was slow, and it turned out that it wasn't at all--it was that I was updating a few menus with the result of the operation. Apparently down inside addAndGetMenuItem in my app there are 32454 calls to getMenuItemByIndex'. I do have a lot of stuff in my menus [I generate them based on what's in my database, so that you can select from any defined item]; it looks like I have somewhere north of 8000 of them, though far less than 32K. Here I'm updating a submenu with about a dozen entries by clearing it, putting back the standard items, and adding a new one to represent a newly-created object. What's the fast way to do this, or can addAndGetMenuItem be sped up?

The reason I'm using addAndGetMenuItem is to have a handle to the menu item [a toggle button] so that I can call "set" on it if it's the active item. If I could just add it with some flag that makes it set, I'd do that instead, but I don't see a flag for that. Perhaps I'm missing something?

ericu avatar Jul 24 '20 23:07 ericu

         addAndGetMenuItem                                                       Graphics.UI.FLTK.LowLevel.Hierarchy                 src/Graphics/UI/FLTK/LowLevel/Hierarchy.hs:2700:164-293             65390          3    0.0    0.0    66.2   88.5
          dispatch                                                               Graphics.UI.FLTK.LowLevel.Dispatch                  src/Graphics/UI/FLTK/LowLevel/Dispatch.hs:151:1-83                  65396         12    0.0    0.0    66.2   88.5
           castTo                                                                Graphics.UI.FLTK.LowLevel.Dispatch                  src/Graphics/UI/FLTK/LowLevel/Dispatch.hs:134:1-24                  65398         12    0.0    0.0     0.0    0.0
           runOp                                                                 Graphics.UI.FLTK.LowLevel.Base.MenuPrim             src/Graphics/UI/FLTK/LowLevel/Base/MenuPrim.chs:243:3-63            65460          3    0.0    0.0     0.0    0.0
            withRef                                                              Graphics.UI.FLTK.LowLevel.Fl_Types                  src/Graphics/UI/FLTK/LowLevel/Fl_Types.chs:(467,1)-(473,8)          65461          3    0.0    0.0     0.0    0.0
             throwStackOnError                                                   Graphics.UI.FLTK.LowLevel.Fl_Types                  src/Graphics/UI/FLTK/LowLevel/Fl_Types.chs:(446,1)-(450,47)         65462          3    0.0    0.0     0.0    0.0
           runOp                                                                 Graphics.UI.FLTK.LowLevel.Base.MenuPrim             src/Graphics/UI/FLTK/LowLevel/Base/MenuPrim.chs:(144,3)-(156,29)    65449          3    0.0    0.0     0.0    0.0
            withRef                                                              Graphics.UI.FLTK.LowLevel.Fl_Types                  src/Graphics/UI/FLTK/LowLevel/Fl_Types.chs:(467,1)-(473,8)          65450          3    0.0    0.0     0.0    0.0
             throwStackOnError                                                   Graphics.UI.FLTK.LowLevel.Fl_Types                  src/Graphics/UI/FLTK/LowLevel/Fl_Types.chs:(446,1)-(450,47)         65451          3    0.0    0.0     0.0    0.0
           runOp                                                                 Graphics.UI.FLTK.LowLevel.Base.MenuPrim             src/Graphics/UI/FLTK/LowLevel/Base/MenuPrim.chs:(229,3)-(230,91)    65405          3    0.0    0.0     0.0    0.0
            addMenuItem                                                          Graphics.UI.FLTK.LowLevel.Base.MenuItem             src/Graphics/UI/FLTK/LowLevel/Base/MenuItem.chs:(287,1)-(328,29)    65406          3    0.0    0.0     0.0    0.0
             addMenuItem.\                                                       Graphics.UI.FLTK.LowLevel.Base.MenuItem             src/Graphics/UI/FLTK/LowLevel/Base/MenuItem.chs:(289,18)-(290,73)   65407          3    0.0    0.0     0.0    0.0
              withRef                                                            Graphics.UI.FLTK.LowLevel.Fl_Types                  src/Graphics/UI/FLTK/LowLevel/Fl_Types.chs:(467,1)-(473,8)          65408          3    0.0    0.0     0.0    0.0
               throwStackOnError                                                 Graphics.UI.FLTK.LowLevel.Fl_Types                  src/Graphics/UI/FLTK/LowLevel/Fl_Types.chs:(446,1)-(450,47)         65409          3    0.0    0.0     0.0    0.0
             addMenuItem.go                                                      Graphics.UI.FLTK.LowLevel.Base.MenuItem             src/Graphics/UI/FLTK/LowLevel/Base/MenuItem.chs:(296,7)-(328,29)    65424          0    0.0    0.0     0.0    0.0
              addMenuItem.go.combinedFlags                                       Graphics.UI.FLTK.LowLevel.Base.MenuItem             src/Graphics/UI/FLTK/LowLevel/Base/MenuItem.chs:297:13-52           65438          0    0.0    0.0     0.0    0.0
               menuItemFlagsToInt                                                Graphics.UI.FLTK.LowLevel.Utils                     src/Graphics/UI/FLTK/LowLevel/Utils.hs:387:1-74                     65439          0    0.0    0.0     0.0    0.0
                combine                                                          Graphics.UI.FLTK.LowLevel.Utils                     src/Graphics/UI/FLTK/LowLevel/Utils.hs:159:1-52                     65440          0    0.0    0.0     0.0    0.0
                 fromEnum                                                        Graphics.UI.FLTK.LowLevel.Fl_Types                  src/Graphics/UI/FLTK/LowLevel/Fl_Types.chs:(263,3)-(272,35)         65441          3    0.0    0.0     0.0    0.0
              copyTextToCString                                                  Graphics.UI.FLTK.LowLevel.Utils                     src/Graphics/UI/FLTK/LowLevel/Utils.hs:(441,1)-(444,30)             65425          0    0.0    0.0     0.0    0.0
               copyTextToCString.bs                                              Graphics.UI.FLTK.LowLevel.Utils                     src/Graphics/UI/FLTK/LowLevel/Utils.hs:442:7-25                     65426          0    0.0    0.0     0.0    0.0
           runOp                                                                 Graphics.UI.FLTK.LowLevel.Base.MenuPrim             src/Graphics/UI/FLTK/LowLevel/Base/MenuPrim.chs:(233,3)-(239,195)   65397          3    0.0    0.0    66.2   88.5
            add                                                                  Graphics.UI.FLTK.LowLevel.Hierarchy                 src/Graphics/UI/FLTK/LowLevel/Hierarchy.hs:1978:106-207             65399          3    0.0    0.0     0.0    0.0
             withRef                                                             Graphics.UI.FLTK.LowLevel.Fl_Types                  src/Graphics/UI/FLTK/LowLevel/Fl_Types.chs:(467,1)-(473,8)          65400          3    0.0    0.0     0.0    0.0
              throwStackOnError                                                  Graphics.UI.FLTK.LowLevel.Fl_Types                  src/Graphics/UI/FLTK/LowLevel/Fl_Types.chs:(446,1)-(450,47)         65401          3    0.0    0.0     0.0    0.0
               withRef.\                                                         Graphics.UI.FLTK.LowLevel.Fl_Types                  src/Graphics/UI/FLTK/LowLevel/Fl_Types.chs:(470,25)-(472,29)        65402          3    0.0    0.0     0.0    0.0
                add.\                                                            Graphics.UI.FLTK.LowLevel.Hierarchy                 src/Graphics/UI/FLTK/LowLevel/Hierarchy.hs:1978:156-164             65404          3    0.0    0.0     0.0    0.0
                toRefPtr                                                         Graphics.UI.FLTK.LowLevel.Fl_Types                  src/Graphics/UI/FLTK/LowLevel/Fl_Types.chs:(460,1)-(464,21)         65403          3    0.0    0.0     0.0    0.0
            getMenu                                                              Graphics.UI.FLTK.LowLevel.Hierarchy                 src/Graphics/UI/FLTK/LowLevel/Hierarchy.hs:2680:122-231             65443          3    0.0    0.0     0.0    0.0
             withRef                                                             Graphics.UI.FLTK.LowLevel.Fl_Types                  src/Graphics/UI/FLTK/LowLevel/Fl_Types.chs:(467,1)-(473,8)          65444          3    0.0    0.0     0.0    0.0
              throwStackOnError                                                  Graphics.UI.FLTK.LowLevel.Fl_Types                  src/Graphics/UI/FLTK/LowLevel/Fl_Types.chs:(446,1)-(450,47)         65445          3    0.0    0.0     0.0    0.0
               withRef.\                                                         Graphics.UI.FLTK.LowLevel.Fl_Types                  src/Graphics/UI/FLTK/LowLevel/Fl_Types.chs:(470,25)-(472,29)        65446          3    0.0    0.0     0.0    0.0
                getMenu.\                                                        Graphics.UI.FLTK.LowLevel.Hierarchy                 src/Graphics/UI/FLTK/LowLevel/Hierarchy.hs:2680:176-184             65448          3    0.0    0.0     0.0    0.0
                toRefPtr                                                         Graphics.UI.FLTK.LowLevel.Fl_Types                  src/Graphics/UI/FLTK/LowLevel/Fl_Types.chs:(460,1)-(464,21)         65447          3    0.0    0.0     0.0    0.0
            runOp.mi                                                             Graphics.UI.FLTK.LowLevel.Base.MenuPrim             src/Graphics/UI/FLTK/LowLevel/Base/MenuPrim.chs:236:9-23            65478          3    0.0    0.0     0.0    0.0
            runOp                                                                Graphics.UI.FLTK.LowLevel.Base.MenuPrim             src/Graphics/UI/FLTK/LowLevel/Base/MenuPrim.chs:(144,3)-(156,29)    65452          0    0.0    0.0    66.2   88.5
             withRef                                                             Graphics.UI.FLTK.LowLevel.Fl_Types                  src/Graphics/UI/FLTK/LowLevel/Fl_Types.chs:(467,1)-(473,8)          65453          3    0.0    0.0    66.2   88.5
              throwStackOnError                                                  Graphics.UI.FLTK.LowLevel.Fl_Types                  src/Graphics/UI/FLTK/LowLevel/Fl_Types.chs:(446,1)-(450,47)         65454      32454    0.0    0.0    66.2   88.5
               withRef.\                                                         Graphics.UI.FLTK.LowLevel.Fl_Types                  src/Graphics/UI/FLTK/LowLevel/Fl_Types.chs:(470,25)-(472,29)        65455          9    0.0    0.0    66.2   88.5
                toRefPtr                                                         Graphics.UI.FLTK.LowLevel.Fl_Types                  src/Graphics/UI/FLTK/LowLevel/Fl_Types.chs:(460,1)-(464,21)         65456          9    0.0    0.0     0.0    0.0
                getSize.\                                                        Graphics.UI.FLTK.LowLevel.Hierarchy                 src/Graphics/UI/FLTK/LowLevel/Hierarchy.hs:2612:176-184             65459          3    0.0    0.0     0.0    0.0
                runOp.\                                                          Graphics.UI.FLTK.LowLevel.Base.MenuPrim             src/Graphics/UI/FLTK/LowLevel/Base/MenuPrim.chs:243:50-63           65464          3    0.0    0.0     0.0    0.0
                 size'                                                           Graphics.UI.FLTK.LowLevel.Base.MenuPrim             src/Graphics/UI/FLTK/LowLevel/Base/MenuPrim.chs:(242,1)-(246,15)    65465          3    0.0    0.0     0.0    0.0
                  size'.\                                                        Graphics.UI.FLTK.LowLevel.Base.MenuPrim             src/Graphics/UI/FLTK/LowLevel/Base/MenuPrim.chs:(245,3)-(246,15)    65467          3    0.0    0.0     0.0    0.0
                   size'.\.res'                                                  Graphics.UI.FLTK.LowLevel.Base.MenuPrim             src/Graphics/UI/FLTK/LowLevel/Base/MenuPrim.chs:245:8-30            65468          3    0.0    0.0     0.0    0.0
                  size'.a1'                                                      Graphics.UI.FLTK.LowLevel.Base.MenuPrim             src/Graphics/UI/FLTK/LowLevel/Base/MenuPrim.chs:243:8-18            65466          3    0.0    0.0     0.0    0.0
                runOp.\                                                          Graphics.UI.FLTK.LowLevel.Base.MenuPrim             src/Graphics/UI/FLTK/LowLevel/Base/MenuPrim.chs:(144,50)-(148,32)   65457          3    0.0    0.0    66.2   88.5
                 runOp.go                                                        Graphics.UI.FLTK.LowLevel.Base.MenuPrim             src/Graphics/UI/FLTK/LowLevel/Base/MenuPrim.chs:(150,9)-(156,29)    65469      32454   66.1   88.3    66.2   88.5
                  getMenuItemByIndex'                                            Graphics.UI.FLTK.LowLevel.Base.MenuPrim             src/Graphics/UI/FLTK/LowLevel/Base/MenuPrim.chs:(143,1)-(148,15)    65470      32451    0.0    0.0     0.0    0.0
                   getMenuItemByIndex'.\                                         Graphics.UI.FLTK.LowLevel.Base.MenuPrim             src/Graphics/UI/FLTK/LowLevel/Base/MenuPrim.chs:(147,3)-(148,15)    65473      32451    0.0    0.0     0.0    0.0
                    getMenuItemByIndex'.\.res'                                   Graphics.UI.FLTK.LowLevel.Base.MenuPrim             src/Graphics/UI/FLTK/LowLevel/Base/MenuPrim.chs:147:8-20            65475      32451    0.0    0.0     0.0    0.0
                   getMenuItemByIndex'.a1'                                       Graphics.UI.FLTK.LowLevel.Base.MenuPrim             src/Graphics/UI/FLTK/LowLevel/Base/MenuPrim.chs:144:8-18            65471      32451    0.0    0.0     0.0    0.0
                   getMenuItemByIndex'.a2'                                       Graphics.UI.FLTK.LowLevel.Base.MenuPrim             src/Graphics/UI/FLTK/LowLevel/Base/MenuPrim.chs:145:8-18            65472      32451    0.0    0.0     0.0    0.0
                  toMaybeRef                                                     Graphics.UI.FLTK.LowLevel.Utils                     src/Graphics/UI/FLTK/LowLevel/Utils.hs:357:1-90                     65474      32451    0.0    0.0     0.1    0.1
                   toRef                                                         Graphics.UI.FLTK.LowLevel.Utils                     src/Graphics/UI/FLTK/LowLevel/Utils.hs:(326,1)-(330,35)             65476      32451    0.0    0.0     0.1    0.1
                    wrapNonNull                                                  Graphics.UI.FLTK.LowLevel.Utils                     src/Graphics/UI/FLTK/LowLevel/Utils.hs:(190,1)-(195,57)             65477      32451    0.1    0.1     0.1    0.1
                    toRef.result                                                 Graphics.UI.FLTK.LowLevel.Utils                     src/Graphics/UI/FLTK/LowLevel/Utils.hs:329:25-45                    65483          3    0.0    0.0     0.0    0.0
                 getSize                                                         Graphics.UI.FLTK.LowLevel.Hierarchy                 src/Graphics/UI/FLTK/LowLevel/Hierarchy.hs:2612:122-231             65458          3    0.0    0.0     0.0    0.0
                 runOp

ericu avatar Jul 24 '20 23:07 ericu

It occurs to me that in the C FLTK the AtIndex is much more useful. You can call menu() to get the underlying array of menus, and then menu()[atIndex] should be the menu item you want to modify. In your wrapper, there's no way I see to do that, so I had to use this function that does a linear search.

Huh. Looking at the source of AddAndGetMenuItem really looks like it's doing what I'd want to do. I think it must be doing something per-menu-item that's not obvious from the code, which looks no more expensive than a list traversal:

instance (Parent a MenuItemBase, impl ~ ( T.Text -> Maybe Shortcut -> Maybe (Ref a-> IO ()) -> MenuItemFlags -> IO (Ref MenuItemBase))) => Op (AddAndGetMenuItem ()) MenuPrimBase orig (impl) where runOp _ _ menu_ name shortcut cb flags = do (AtIndex i) <- add menu_ name shortcut cb flags items <- getMenu menu_ let mi = items !! i case mi of Just mi' -> return mi' Nothing -> throwIO (userError ("FLTK claims the menu item " ++ (T.unpack name) ++ " was added successfully at index " ++ (show i) ++ " , but no MenuItem at that index could be retrieved."))

Perhaps it's forcing some conversion on each list item by iterating past them? Could it be lazier?

ericu avatar Jul 25 '20 00:07 ericu

Off the bat I see that getMenu is retrieving all the items in the menu and iterating through them to find the one you just added, so essentially it's the painter's algorithm.

Honestly I didn't see the menus being used this way so I went with a very naive approach. An incremental improvement might be to have getMenu return a Vector instead of a List.

deech avatar Jul 25 '20 00:07 deech

Could AddAndGetMenuItem just call into getMenuItemByIndex' more directly, as getMenu is?

ericu avatar Jul 25 '20 00:07 ericu

Yes that might work well. I'll try to get to it as soon as I can but you are able to I'm happy to merge a PR.

deech avatar Jul 25 '20 00:07 deech

Thanks! Exposing getMenuItemByIndex would also be great.

ericu avatar Jul 25 '20 00:07 ericu

Heh; and in this case, the flag I was looking for was MenuItemValue, so I'm just going to call add instead of addAndGetMenuItem :grin:. So no rush on my account, but it does look likely to be a quick fix when you get around to it.

ericu avatar Jul 25 '20 00:07 ericu

I'm also going to see about reducing my menu count by a factor of 80-100; there's a small change that would do it, and now that I know how many there are, it seems kind of ridiculous.

ericu avatar Jul 25 '20 01:07 ericu