4. 測定ツール
著者:梅谷 武
プログラムの実装実験に用いる測定ツールについて記す。
作成:2024-03-08
更新:2024-08-24
 Ubuntu上で複数言語で同じプログラムを実装して比較するために簡易的な測定ツールを作成しておく。これは測定対象のプログラムにコマンドライン引数で測定パラメータを渡して子プロセスとして実行し、getrusage()によりプロセス統計を取得し表示する。実行時間やメモリ消費量は実行時の状況により変動するのであくまでも傾向を把握するものである。
 measure.cpp:
#include <print>
#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>
 
off_t get_file_size(const char *filename) {
  struct stat st;
  if (stat(filename, &st) == 0)
    return st.st_size;
  else
    return -1;
}
 
int main(int argc, char *argv[]) {
  if (argc < 2) {
    std::println(stderr, "Usage: measure target [args...]");
    return 1;
  }
  pid_t pid = fork();
  if (pid < 0) {
    std::println(stderr, "--->fork() failed.");
    return 1;
  } else if (pid == 0) {
    if (execvp(argv[1], &argv[1]) == -1) {
      std::println(stderr, "--->execvp() failed.");
      _exit(EXIT_FAILURE);
    }
  } else {
    int status;
    struct rusage usage;
    if (wait4(pid, &status, 0, &usage) == -1) {
      std::println(stderr, "--->wait4() failed.");
      return 1;
    }
    std::println(stdout, "======================================");
    if (WIFEXITED(status))
      std::println(stdout,
                   "Process exited with status: {}",
                   WEXITSTATUS(status));
    else if (WIFSIGNALED(status))
      std::println(stdout,
                   "Process terminated by signal: {}",
                   WTERMSIG(status));
    else
      std::println(stdout,
                   "Process did not exit normally.");
    double user_time = usage.ru_utime.tv_sec + usage.ru_utime.tv_usec / 1e6;
    double sys_time = usage.ru_stime.tv_sec + usage.ru_stime.tv_usec / 1e6;
    double total_time = user_time + sys_time;
    std::println(stdout, "total time: {:9.6f} [sec]", total_time);
    std::println(stdout, "mem  size:  {:>9} [KB]", usage.ru_maxrss);
    std::println(stdout, "code size:  {:>9} [KB]", get_file_size(argv[1]) / 1000l);
  }
  return 0;
}


 makefile:
CPP = g++
CPPFLAGS = -std=c++23
SRC = measure.cpp
EXES = measure
 
all: $(EXES)
 
measure: $(SRC)
	$(CPP) $(CPPFLAGS) -o $@ $(SRC)
 
clean:
	rm -f $(EXES)


 この実行ファイルをPATHが通ったディレクトリにコピーしておく。
$ sudo cp measure /usr/local/bin
This document is licensed under the MIT License.
Copyright (C) 2024 Takeshi Umetani