以下 Haskell 函数:
{-# LANGUAGE ForeignFunctionInterface #-}
module Main where
import Data.Word (Word32)
sum' :: Word32 -> Word32
sum' 0 = 0
sum' n = n + sum' (n-1)
foreign export javascript "sum" sum' :: Word32 -> Word32
main :: IO ()
main = print (sum' 10000000)
编译为 WASM 时,在
n
上呈二次方,而不是如预期的线性。因此,它比原生版本慢数百万倍,这对于 WASM 来说是不期望的。这是编译器错误,还是我做错了什么?
我正在使用 GHC 9.11.20240817,使用以下命令:
wasm32-wasi-ghc main.hs -O2 -no-hs-main -optl-mexec-model=reactor
接下来是后链接步骤:
$(wasm32-wasi-ghc --print-libdir)/post-link.mjs -i main.wasm -o main.js
然后我从 JS 导入
sum
并在不同的 n 上调用它。
您是否有可能将二次性能误认为是“无性能”? 在我对版本 9.11.20240818 的测试中,我看到线性性能高达
sum' 258690872
,然后当编译为命令模块并在 sum' 258690873
下运行时,从 wasmtime
开始不会终止。 具体来说,如果我编译:
module Main where
import Data.Word (Word32)
sum' :: Word32 -> Word32
sum' 0 = 0
sum' n = n + sum' (n-1)
main :: IO ()
main = print $ sum' 258690872
与
wasm32-wasi-ghc -O2 Sum.hs
并使用 wasmtime
运行时运行它,运行时间约为 7 秒。 如果我将 258690872
增加到 258690873
,它不会终止。
它看起来与错误的堆栈溢出处理有关,因为使用 RTS
-K
选项,我可以让 sum' 258690872
以堆栈溢出错误终止,无限期挂起,或在大约 7 秒内完成,因为堆栈大小增加了。
我已提交问题#25213。