1
0
forked from GitHub/gf-core
Files
gf-core/src/server/Cache.hs
T
hallgren 4008a2b111 PGF web service: disable caching of parse results
Caching parse results uses a lot of memory, even if they expire after
2 minutes, so it won't scale up to many simultaneous users.

But some excessive memory use seems to be caused by space leaks in
(the Haskell binding to) the C run-time system, and these should be fixed.
For example, flushing the PGF cache does not release the memory allocated
by the C run-time system when loading a PGF file.
2014-04-10 15:55:33 +00:00

44 lines
1.6 KiB
Haskell

module Cache (Cache,newCache,flushCache,readCache,readCache') where
import Control.Concurrent.MVar
import Data.Map (Map)
import qualified Data.Map as Map
import System.Directory (getModificationTime)
import System.Mem(performGC)
import Data.Time (UTCTime)
import Data.Time.Compat (toUTCTime)
data Cache a = Cache {
cacheLoad :: FilePath -> IO a,
cacheObjects :: MVar (Map FilePath (MVar (Maybe (UTCTime, a))))
}
newCache :: (FilePath -> IO a) -> IO (Cache a)
newCache load =
do objs <- newMVar Map.empty
return $ Cache { cacheLoad = load, cacheObjects = objs }
flushCache :: Cache a -> IO ()
flushCache c = do modifyMVar_ (cacheObjects c) (const (return Map.empty))
performGC
readCache :: Cache a -> FilePath -> IO a
readCache c file = snd `fmap` readCache' c file
readCache' :: Cache a -> FilePath -> IO (UTCTime,a)
readCache' c file =
do v <- modifyMVar (cacheObjects c) findEntry
modifyMVar v readObject
where
-- Find the cache entry, inserting a new one if neccessary.
findEntry objs = case Map.lookup file objs of
Just v -> return (objs,v)
Nothing -> do v <- newMVar Nothing
return (Map.insert file v objs, v)
-- Check time stamp, and reload if different than the cache entry
readObject m = do t' <- toUTCTime `fmap` getModificationTime file
x' <- case m of
Just (t,x) | t' == t -> return x
_ -> cacheLoad c file
return (Just (t',x'), (t',x'))