summaryrefslogtreecommitdiffhomepage
path: root/src/Xmobar/Plugins/Date.hs
diff options
context:
space:
mode:
authorTomas Janousek <tomi@nomi.cz>2020-11-12 10:02:44 +0000
committerjao <jao@gnu.org>2020-11-13 02:10:31 +0000
commit17b0dac481c01425651326e8814b45058cd40f06 (patch)
treecabb9394e29880b7460ae3cfbc449c53bd416722 /src/Xmobar/Plugins/Date.hs
parente47cb0222eb5b152f69a18f4685726a5460f4b90 (diff)
downloadxmobar-17b0dac481c01425651326e8814b45058cd40f06.tar.gz
xmobar-17b0dac481c01425651326e8814b45058cd40f06.tar.bz2
Optimize Date plugin again (refresh timezone only once a minute)
This makes the Date plugin approximately twice as fast, and makes xmobar up to about 5–10 % faster if Date is the only active plugin. (If more expensive plugins like Network or MultiCpu are used, it doesn't make any measurable difference.) Micro-benchmark results on my HW: Date Benchmarks/Date mean 2.833 μs ( +- 16.08 ns ) Date Benchmarks/DateZonedTime mean 5.020 μs ( +- 32.91 ns ) Date Benchmarks/DateWithTimeZone mean 2.827 μs ( +- 20.52 ns ) (DateZonedTime is the original implementation and DateWithTimeZone is the implementation we had since 0.34 which never refreshes timezone.) Real-life measurements (done overnight on an idle laptop, with all measured xmobars running in parallel to ensure comparable conditions; xmobars configured to only display date and with rate 10 — once per second): $ time timeout 6h xmobar .xmobarrc-DateZonedTime real 360m0,010s user 0m9,867s sys 0m4,644s (9.867 + 4.644) / (360 * 60) = 0.000672 $ time timeout 6h xmobar .xmobarrc-Date real 360m0,008s user 0m9,535s sys 0m4,327s (9.535 + 4.327) / (360 * 60) = 0.000642 $ time timeout 6h xmobar .xmobarrc-Date-10m real 360m0,010s user 0m9,780s sys 0m4,215s (9.780 + 4.215) / (360 * 60) = 0.000648 $ time timeout 6h xmobar .xmobarrc-DateWithTimeZone real 360m0,006s user 0m9,658s sys 0m4,166s (9.658 + 4.166) / (360 * 60) = 0.000640 (.xmobarrc-Date-10m is the proposed implementation, but with timezone refresh every 10 minutes instead of every 1 minute) Interpretation of these results: * refreshing xmobar with just date takes around 650 μs * that is xmobar with just date uses around 0.065 % of CPU time * refreshing timezone takes additional cca 30 μs When we only refresh timezone once a minute, these 30 μs become 0.5 μs amortized, and that should be acceptable to even the most dedicated perfectionist :-) Fixes: a58e32f7c8af ("Revert "Optimize date plugin"") Fixes: 878db3908060 ("Optimize date plugin") Co-authored-by: Sibi Prabakaran <sibi@psibi.in>
Diffstat (limited to 'src/Xmobar/Plugins/Date.hs')
-rw-r--r--src/Xmobar/Plugins/Date.hs21
1 files changed, 17 insertions, 4 deletions
diff --git a/src/Xmobar/Plugins/Date.hs b/src/Xmobar/Plugins/Date.hs
index 1cb0596..d7de2e9 100644
--- a/src/Xmobar/Plugins/Date.hs
+++ b/src/Xmobar/Plugins/Date.hs
@@ -17,22 +17,35 @@
--
-----------------------------------------------------------------------------
-module Xmobar.Plugins.Date (Date(..)) where
+module Xmobar.Plugins.Date (Date(..), date) where
import Xmobar.Run.Exec
#if ! MIN_VERSION_time(1,5,0)
import System.Locale
#endif
+import Data.IORef
import Data.Time
+import Control.Concurrent.Async (concurrently_)
data Date = Date String String Int
deriving (Read, Show)
instance Exec Date where
alias (Date _ a _) = a
- run (Date f _ _) = date f
rate (Date _ _ r) = r
+ start (Date f _ r) cb =
+ -- refresh time zone once a minute to avoid wasting CPU cycles
+ withRefreshingZone 600 $ \zone ->
+ doEveryTenthSeconds r $ date zone f >>= cb
-date :: String -> IO String
-date format = fmap (formatTime defaultTimeLocale format) getZonedTime
+date :: IORef TimeZone -> String -> IO String
+date zoneRef format = do
+ zone <- readIORef zoneRef
+ fmap (formatTime defaultTimeLocale format . utcToZonedTime zone) getCurrentTime
+
+withRefreshingZone :: Int -> (IORef TimeZone -> IO ()) -> IO ()
+withRefreshingZone r action = do
+ zone <- newIORef =<< getCurrentTimeZone
+ let refresh = atomicWriteIORef zone =<< getCurrentTimeZone
+ concurrently_ (doEveryTenthSeconds r refresh) (action zone)