diff options
| author | Anton Vorontsov <anton@enomsg.org> | 2014-09-16 15:48:49 -0700 | 
|---|---|---|
| committer | Anton Vorontsov <anton@enomsg.org> | 2014-09-16 20:20:10 -0700 | 
| commit | 73053ddf3386604f19b494afd9c234ac50427d6c (patch) | |
| tree | 9b11fc330277073806b73be3c075659784e239ea /src/Plugins | |
| parent | a6933f49ae9bdc8cbd5bee42920e5b9a01c21e7f (diff) | |
| download | xmobar-73053ddf3386604f19b494afd9c234ac50427d6c.tar.gz xmobar-73053ddf3386604f19b494afd9c234ac50427d6c.tar.bz2 | |
Locks: Rework to avoid unnecessary display reopening
The extremely useful "Locks" plugin eats quite a lot of CPU (>2% here on a
old-ish laptop), unfortunately. The plug-in unnecessary reopens the
display, which is quite expensive operation. It results into 16 syscalls:
     socket(PF_LOCAL)      -> connect(sun_path=@"/tmp/.X11-unix/X0"})
  -> getpeername()         -> uname()
  -> access(".Xauthority") -> open(".Xauthority")
  -> fstat()               -> mmap()
  -> read()                -> close()
  -> munmap()              -> getsockname()
  -> fcntl(F_SETFD)        -> fcntl(F_SETFL)
  -> shutdown()            -> close()
This is almost half of all the syscalls that we ought to execute for the
plug-in to work. Now, considering the useful work and that "Locks" runs
every 200 milliseconds, it gives us >300 syscalls (and a lot more
wake-ups) per second.
This commit fixes the reopening issue, effectively halving the CPU
consumption (down to ~1%). The patch also makes it easier to implement
event-driven indicators that will reduce the idle CPU consumption to 0.
Diffstat (limited to 'src/Plugins')
| -rw-r--r-- | src/Plugins/Locks.hs | 30 | 
1 files changed, 19 insertions, 11 deletions
| diff --git a/src/Plugins/Locks.hs b/src/Plugins/Locks.hs index 3c1e0a9..b30eb1b 100644 --- a/src/Plugins/Locks.hs +++ b/src/Plugins/Locks.hs @@ -30,22 +30,30 @@ locks = [ ( xK_Caps_Lock,   "CAPS"   )          , ( xK_Scroll_Lock, "SCROLL" )          ] +run' :: Display -> Window -> IO String +run' d root = do +    modMap <- getModifierMapping d +    ( _, _, _, _, _, _, _, m ) <- queryPointer d root + +    ls <- filterM ( \( ks, _ ) -> do +        kc <- keysymToKeycode d ks +        return $ case find (elem kc . snd) modMap of +            Nothing       -> False +            Just ( i, _ ) -> testBit m (fromIntegral i) +        ) locks + +    return $ unwords $ map snd ls +  instance Exec Locks where      alias Locks = "locks"      rate Locks = 2 -    run Locks = do +    start Locks cb = do          d <- openDisplay ""          root <- rootWindow d (defaultScreen d) -        modMap <- getModifierMapping d -        ( _, _, _, _, _, _, _, m ) <- queryPointer d root +        forever $ do +            cb =<< run' d root +            tenthSeconds $ rate Locks -        ls <- filterM ( \( ks, _ ) -> do -            kc <- keysymToKeycode d ks -            return $ case find (elem kc . snd) modMap of -                Nothing       -> False -                Just ( i, _ ) -> testBit m (fromIntegral i) -            ) locks          closeDisplay d - -        return $ unwords $ map snd ls +        return () | 
