【问题标题】:How to time the execution of a gnu make rule?如何定时执行 gnu make 规则?
【发布时间】:2016-01-21 22:26:43
【问题描述】:

我想为 make 规则的执行计时,但在获取有效的开始和停止时间以及让简单的算术(减法)工作时遇到了麻烦。

$ make money
sleep 2
echo "money: 1453412887" > logfile
echo "money: 1453412887" >> logfile
echo "money: 1453412887" >> logfile

Makefile:

money:
        $(eval start := $(shell date +%s))
        sleep 2
        $(eval end := $(shell date +%s))
        echo "$@: ${start}" > logfile
        echo "$@: ${end}" >> logfile
        echo "$@: $(shell date +%s)" >> logfile

【问题讨论】:

    标签: makefile profiling timing


    【解决方案1】:

    请尝试以下示例,

    test:
            @start=$$(date +%s); \
            echo $@: $$start > test.log
            @sleep 2
            @end=$$(date +%s); \
            echo $@: $$end >> test.log
    

    ,一个关键的项目是,shell变量赋值应该和echo命令在同一行。

    【讨论】:

      【解决方案2】:

      如果您只想跟踪一个目标的时间,Eric 的答案是一个不错的答案。虽然,没有理由设置一个单独的变量;只回显命令的输出更简单。此外,如果您对 shell 命令使用老式反引号而不是较新的 $(...) 格式,则在 makefile 配方中可能更容易阅读:

      test:
              echo $@: `date +%s` > test.log
              @sleep 2
              echo $@: `date +%s` >> test.log
      

      您的尝试不起作用的原因是 make 将在开始第一行之前评估配方的所有行。因此,整个配方中的所有 make 变量和函数(如 evalshell 等)都在配方的任何部分开始之前预先扩展。所以多次运行date 命令的结果总是相同的。

      如果您尝试为所有命令计时并且不想更改所有配方以保留日志,则另一种选择是编写一个特殊的脚本或程序,它将命令行作为参数,然后定时在 shell 中运行该命令。然后设置 make SHELL 变量以使用该脚本/程序而不是真正的 shell。如果你有复杂的配方(你必须保留所有的引用等),让它正常工作会有点棘手。实际上编写一个小 C 程序并使用 fork/exec 是最简单的:那里没有引用问题。但是,这是最可靠且侵入性最小的方法。

      【讨论】:

        【解决方案3】:

        这是我用来计时执行 makefile 构建项(配方及其各自的项,甚至是项的输出)的解决方案。

        make 命令的输出的原理是通过管道传送到这个

        while read line; do date +'%s%N'; echo "$line"; done`
        

        它在所有从 make 调用发出的输出行前面加上一个时间戳行,允许查看用于各个配方及其元素/项目的时间。

        一个例子说明了这一点。假设这个简单的 Makefile

        如果这是我们的 Makefile

        all: part1 part2
            cat part1 part2 > all
        
        part1: 
            sleep 1
            echo "part1 content" > part1
        
        part2: 
            sleep 2
            echo "part2 content" > part2
        

        然后运行它会导致这个输出:

        $> make | while read line; do date +'%s%N'; echo "$line"; done
        1561566560276946890
        sleep 1
        1561566561280995480
        echo "part1 content" > part1
        1561566561290389273
        sleep 2
        1561566563292382045
        echo "part2 content" > part2
        1561566563298681800
        cat part1 part2 > all
        

        不出所料表明 part1 配方步骤 sleep 1 的规则采用了 1561566561280995480 - 1561566560276946890 = 1 004 048 640 纳秒,相当于 到预期的 1 秒持续时间。

        生成的 unix epoc 纳秒时间戳,如this answer中所建议 提供一种简单的方法来快速检查输出的持续时间和 从而获得好评。

        警告。通过-j命令行参数使用多个make作业时,时间戳只能反映-Onone的时间,即不使用输出同步。

        【讨论】:

          【解决方案4】:

          这里是如何做到这一点,而无需在 makefile 上乱涂乱画。 基本上, 您将 make 通常用于执行命令 (/bin/sh) 的 shell 替换为您自己设计的 shellscript。 单线就可以了。比如:

          $ cat ~/TIMING
          #!/bin/bash
          command time -ao ~/LOG -f "%E [$*]" bash "$@"
          
          • command 因为我们想使用 /bin/time (YMMV) 而不是 bash 内置 time
          • -ao 将消息附加到日志文件中。我们使用绝对路径,以便子使更改文件夹继续记录到文件。
          • -f 指定时间格式:我选择经过时间,后跟 make 提供给 shell 的参数。
          • "$@" 扩展为 make 传递给 shell 的参数。 make 使用的第一个参数应该是-c,这会导致 bash 将以下参数作为命令执行。
          • 退出代码是 make 要求执行的命令的退出代码。

          测试

          $ cat Makefile
          .PHONY: atest
          atest:
              sleep 1.5
              echo testing non-zero exit code
              exit 22
              echo done
          

          然后正常运行:

          $ make
          sleep 1.5
          echo testing non-zero exit code
          testing non-zero exit code
          exit 22
          make: *** [atest] Error 22
          

          然后是定时运行。看起来都一样:

          $ rm -f ~/LOG
          $ chmod a+x ~/TIMING
          $ make SHELL=~/TIMING
          sleep 1.5
          echo testing non-zero exit code
          testing non-zero exit code
          exit 22
          make: *** [atest] Error 22
          

          但是这次我们有一个不错的日志文件:

          $ cat ~/LOG
          0:01.50 [-c sleep 1.5]
          0:00.00 [-c echo testing non-zero exit code]
          0:00.00 [-c exit 22]
          

          很好。并行安全也。你的 makefile 是并行安全的,对吧?

          【讨论】:

            猜你喜欢
            • 2014-02-02
            • 2022-12-02
            • 2010-12-26
            • 2017-09-26
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2023-04-02
            • 2015-08-28
            相关资源
            最近更新 更多