Nor*_*sey 18 scripting performance interpreter haskell
有没有人知道一个快速启动的Haskell解释器适合用于编写shell脚本?使用Hugs运行'hello world'在我的旧笔记本电脑上运行了400ms,在我当前的Thinkpad X300上运行了300ms.这对于瞬时响应来说太慢了.与GHCi的时代相似.
功能语言不一定要慢:Objective Caml和Moscow ML在1ms或更短的时间内运行hello world.
澄清:我是GHC的重度用户,我知道如何使用GHCi.我知道所有关于编译以使事情变得快速的事情.解析成本应该完全无关:如果ML和OCaml的启动速度比GHCi快300倍,那么还有改进的余地.
我在寻找
性能可与其他解释器相媲美,包括快速启动和执行简单程序等
module Main where
main = print 33
Run Code Online (Sandbox Code Playgroud)我不是在寻找更严肃程序的编译性能.重点是看看Haskell是否对脚本有用.
srp*_*ish 31
为什么不创建一个脚本前端来编译脚本(如果它以前没有,或者编译后的版本已经过时).
这是基本的想法,这个代码可以进行很多改进 - 搜索路径而不是假设所有内容都在同一个目录中,更好地处理其他文件扩展名等.另外,我在haskell编码时非常环保(ghc-compiled-script. HS):
import Control.Monad
import System
import System.Directory
import System.IO
import System.Posix.Files
import System.Posix.Process
import System.Process
getMTime f = getFileStatus f >>= return . modificationTime
main = do
scr : args <- getArgs
let cscr = takeWhile (/= '.') scr
scrExists <- doesFileExist scr
cscrExists <- doesFileExist cscr
compile <- if scrExists && cscrExists
then do
scrMTime <- getMTime scr
cscrMTime <- getMTime cscr
return $ cscrMTime <= scrMTime
else
return True
when compile $ do
r <- system $ "ghc --make " ++ scr
case r of
ExitFailure i -> do
hPutStrLn stderr $
"'ghc --make " ++ scr ++ "' failed: " ++ show i
exitFailure
ExitSuccess -> return ()
executeFile cscr False args Nothing
Run Code Online (Sandbox Code Playgroud)
现在我们可以创建这样的脚本(hs-echo.hs):
#! ghc-compiled-script
import Data.List
import System
import System.Environment
main = do
args <- getArgs
putStrLn $ foldl (++) "" $ intersperse " " args
Run Code Online (Sandbox Code Playgroud)
现在运行它:
$ time hs-echo.hs "Hello, world\!"
[1 of 1] Compiling Main ( hs-echo.hs, hs-echo.o )
Linking hs-echo ...
Hello, world!
hs-echo.hs "Hello, world!" 0.83s user 0.21s system 97% cpu 1.062 total
$ time hs-echo.hs "Hello, world, again\!"
Hello, world, again!
hs-echo.hs "Hello, world, again!" 0.01s user 0.00s system 60% cpu 0.022 total
Run Code Online (Sandbox Code Playgroud)
使用ghc -e几乎等同于调用ghci.我相信GHC会runhaskell在运行之前将代码编译为临时可执行文件,而不是将其解释为ghc -e/ ghci,但我不是100%肯定的.
$ time echo 'Hello, world!'
Hello, world!
real 0m0.021s
user 0m0.000s
sys 0m0.000s
$ time ghc -e 'putStrLn "Hello, world!"'
Hello, world!
real 0m0.401s
user 0m0.031s
sys 0m0.015s
$ echo 'main = putStrLn "Hello, world!"' > hw.hs
$ time runhaskell hw.hs
Hello, world!
real 0m0.335s
user 0m0.015s
sys 0m0.015s
$ time ghc --make hw
[1 of 1] Compiling Main ( hw.hs, hw.o )
Linking hw ...
real 0m0.855s
user 0m0.015s
sys 0m0.015s
$ time ./hw
Hello, world!
real 0m0.037s
user 0m0.015s
sys 0m0.000s
Run Code Online (Sandbox Code Playgroud)
在运行它们之前简单地编译所有"脚本"有多难?
啊,为多种架构提供二进制文件确实很痛苦.我之前走过这条路,这并不是很有趣......
遗憾的是,我认为不可能更好地使任何Haskell编译器的启动开销.语言的声明性意味着有必要首先阅读整个程序,甚至在尝试进行类型检查之前,从不执行任何操作,然后您要么承担严格性分析或不必要的懒惰和thunking的成本.
流行的"脚本"语言(shell,Perl,Python等)和基于ML的语言只需要一次通过......好吧,ML需要静态类型检查传递,Perl有这种有趣的5遍方案(带有其中两个反向运行); 无论哪种方式,程序化意味着编译器/解释器更容易将程序的各个部分组合在一起.
简而言之,我认为不可能比这更好.我还没有测试看看Hugs或GHCi是否有更快的启动,但任何差异仍然远离非Haskell语言.
| 归档时间: |
|
| 查看次数: |
5076 次 |
| 最近记录: |