为什么 shake 对这个简单构建系统的进度估计非常错误?

Why is shake's progress estimation for this simple build system very wrong?

我有以下构建系统

module Main where

import Development.Shake

main :: IO ()
main = shakeArgs shakeOptions $ do

  "a" %> \out -> do
    need ["a.in"]
    cmd_ "sleep" "10"
    cmd "touch" [out]

我用 stack build 和 运行 用 stack exec myShake -- --progress a 构建。

如果我做了一个干净的构建,而不是 touch a.in 和 运行,shake 显示我非常错误的进度预测。有时它会预测 1000 分钟或更长时间。

(因为我每 5 秒在终端的标题栏中得到一个进度预测,如果我理解正确的话,我在这里只谈论第一个进度预测,因为这是我在这个版本中唯一得到的系统示例。)

我将 lts-9.6 与 stack and shake 0.16 版一起使用(通过 git + stack.yaml 中的包中的条目)。

看来第一个进度预估消息一般没什么用。对于重要的构建系统,这应该不是问题,因为它们花费的时间超过五秒。

使用这个构建系统和 --progress=1 可以看到,第一个估计是正确的,但其他的会变得更好:

module Main where

import Development.Shake

main :: IO ()
main = shakeArgs shakeOptions $ do
  mapM_ (\i ->
    ("a." ++ show i) %> \out ->
      do
        need [out ++ ".in", "a." ++ show (i-1)]
        cmd_ "sleep" "1"
        cmd "touch" [out])
    [1 .. 10]

  "a.0" %> \out -> do
    need ["a.0.in"]
    cmd_ "sleep" "1"
    cmd "touch" [out]

要尝试这个,您需要做

for i in $(seq 0 10); do touch a.$i.in; done

在您用于此示例构建系统的工作目录中。

可以在 progressDisplay:

找到有关进度如何工作的文档

The current implementation is to predict the time remaining (based on timeTodo) and the work already done (timeBuilt). The percentage is then calculated as remaining / (done + remaining), while time left is calculated by scaling remaining by the observed work rate in this build, roughly done / time_elapsed.

在只做一件事情的非常短的构建系统的情况下,工作率通常是垃圾 - 所以你最终用随机数(大概是大数字,获得 1000m)。

改变工作率的想法是,有时你在笔记本电脑上使用电池电源与主电源,有时你传递不同的并行标志。 Shake 很有可能应该使用一个或多个线程作为工作率的近似值,至少在开始时是这样。