[Fencommits] fenserve: cache compiled code. nice, this makes it quite fast after the code is compiled :)
Benja Fallenstein
benja.fallenstein at gmail.com
Sun Mar 25 22:58:21 EEST 2007
Sun Mar 25 22:58:08 EEST 2007 Benja Fallenstein <benja.fallenstein at gmail.com>
* cache compiled code. nice, this makes it quite fast after the code is compiled :)
diff -rN -u old-fenserve/FenServe.hs new-fenserve/FenServe.hs
--- old-fenserve/FenServe.hs 2007-03-25 22:58:21.000000000 +0300
+++ new-fenserve/FenServe.hs 2007-03-25 22:58:21.000000000 +0300
@@ -27,19 +27,21 @@
import HAppS hiding (query, Handler)
import Control.Monad (liftM)
+import Control.Monad.Error (throwError, runErrorT)
import Control.Monad.State (State, StateT, runStateT,
get, gets, put, modify, execState)
-import Control.Monad.Trans (lift)
+import Control.Monad.Trans (lift, liftIO)
import qualified Data.ByteString as ByteString
import Data.ByteString (ByteString)
import Data.Generics
+import Data.IORef
import qualified Data.List as List
import qualified Data.Map as Map
import Data.Map (Map)
import qualified Data.Set as Set
import Data.Set (Set)
-import Data.Maybe (fromMaybe, fromJust)
+import Data.Maybe (fromMaybe, fromJust, isJust)
import Data.Typeable
import Language.Haskell.Hsx as Hsx
@@ -270,12 +272,20 @@
"qualified Data.ByteString as ByteString",
"qualified Data.List as List",
"qualified Data.Map as Map"]
+
+codeCache :: IORef (Map BlockId Handler)
+codeCache = unsafePerformIO $ newIORef Map.empty
execute :: Node -> Request -> FenServe Result
-execute code req = do
- s <- getBlock (bID code)
- let errH stage msg = return $ (,) Nothing $ \req -> return $
- mkResult 500 "text/plain" $ toUTF $ stage ++ " failed:\n" ++ msg
+execute code req = getBlock (bID code) >>= \s ->
+ let f (Left msg) = return $ mkResult 500 "text/plain" $ toUTF $ msg
+ f (Right h) = h req
+ in f $ unsafePerformIO $ runErrorT $ do
+
+ cached <- liftM (Map.lookup $ bID code) $ liftIO $ readIORef codeCache
+ if isJust cached then return (fromJust cached) else do
+
+ let err stage msg = throwError (stage ++ " failed:\n" ++ msg)
mname = "Page_" ++ (blockId $ bID code)
s2 = "module " ++ mname ++ " where\n" ++
concatMap (\i -> "import "++i++"\n") imports ++
@@ -283,36 +293,31 @@
-- the 'dummyAssignment' is to make sure that
-- pages can't import anything -- imports are
-- syntactically disallowed except at the beginning
- (m,h) <- case Hsx.parseModuleWithMode (Hsx.ParseMode "Page.hs") $ s2 of
- ParseFailed (SrcLoc file line col) err -> errH "HSP preprocessing" $
- "At "++show line++":"++show col++" in "++file++": "++err
- ParseOk parsed -> return $ unsafePerformIO $ do
- let s' = Hsx.prettyPrintWithMode (Hsx.defaultMode
- {Hsx.linePragmas=True}) $ Hsx.transform parsed
-
- putStrLn (unlines $ take 10 $ lines s')
-
- let fp = "/tmp/"++mname++".hs"
- hdl <- openFile fp WriteMode
- hPutStr hdl s'
- hClose hdl
- let dir = "dist/build"
- homedir <- getEnv "HOME"
- makeResult <- Plugins.make fp ["-fglasgow-exts", "-fallow-overlapping-instances"]
- h' <- case makeResult of
- Plugins.MakeFailure err ->
- errH "Make" $ concat (List.intersperse "\n" err)
- Plugins.MakeSuccess _ o -> do
- loadResult <- Plugins.load o [] [homedir ++ "/.ghc/i386-linux-6.6/package.conf"] "handler"
- case loadResult of
- Plugins.LoadSuccess m v -> return (Just m,v)
- Plugins.LoadFailure err ->
- errH "Load" $ concat (List.intersperse "\n" err)
- Plugins.makeCleaner fp; return h'
- result <- h req -- run the loaded handler
- case m of Just m' -> unsafePerformIO $ do --Plugins.unload m'
- return (return result)
- Nothing -> return result
+
+ parsed <- case Hsx.parseModuleWithMode (Hsx.ParseMode "Page.hs") $ s2 of
+ ParseFailed (SrcLoc file line col) e -> err "HSP preprocessing" $
+ "At "++show line++":"++show col++" in "++file++": "++e
+ ParseOk parsed -> return parsed
+
+ let s' = Hsx.prettyPrintWithMode (Hsx.defaultMode {Hsx.linePragmas=True}) $
+ Hsx.transform parsed
+ fp = "/tmp/"++mname++".hs"
+
+ hdl <- liftIO $ openFile fp WriteMode
+ liftIO $ hPutStr hdl s'
+ liftIO $ hClose hdl
+ homedir <- liftIO $ getEnv "HOME"
+ makeResult <- liftIO $ Plugins.make fp ["-fglasgow-exts", "-fallow-overlapping-instances"]
+ o <- case makeResult of
+ Plugins.MakeFailure e -> err "Make" $ concat (List.intersperse "\n" e)
+ Plugins.MakeSuccess _ o -> return o
+ loadStatus <- liftIO $ Plugins.load o [] [homedir ++ "/.ghc/i386-linux-6.6/package.conf"] "handler"
+ h <- case loadStatus of
+ Plugins.LoadFailure e -> err "Load" $ concat (List.intersperse "\n" e)
+ Plugins.LoadSuccess _ h -> return h
+ liftIO $ Plugins.makeCleaner fp
+ liftIO $ modifyIORef codeCache (Map.insert (bID code) h)
+ return h
-------------------------------------------------------------------------
More information about the Fencommits
mailing list