← Implementing the SPEC test executor on HarmonyOS

This article has no English version yet; the original Chinese text follows. Chart labels are in Chinese as well.

示例代码

  • timing.cpp:C++17 的计时边界算术,返回秒。进程回收、退出状态和共享记录检查由执行器完成,示例只做算术。
  • measurement.mjs:独立 JavaScript 示例,演示一至三轮的时间选取、已验证结果比率、主命令耗时汇总。两轮采用排序后的较大值。它只做结果算术,不运行 SPEC,也不做输出比较。

以文章提供的脱敏结果调用:

import { sumMainCommandSeconds, validatedRatio } from './measurement.mjs';

const response = await fetch('../data/chart-data.json');
if (!response.ok) throw new Error(`HTTP ${response.status}`);
const data = await response.json();
const seconds = sumMainCommandSeconds(data.commands);
const ratio = validatedRatio(data.referenceSeconds, [seconds], 1, data.validated);
console.log({ seconds, ratio });

通过 HTTP 提供静态文件时使用上述 fetch 方式。Node.js 可用 readFile 读取 JSON 后调用相同函数。

没有附带 SPEC 源码、二进制负载、输入数据和参考输出。这里的结果比率是单项运行的示例。

Files

measurement.mjs 30 lines Download ↓
// Independent explanatory helper. It neither runs SPEC nor validates its output.
export function selectMeasuredTime(times, expectedCount) {
  if (!Number.isInteger(expectedCount) || expectedCount < 1 || expectedCount > 3 ||
      times.length !== expectedCount ||
      times.some(value => !Number.isFinite(value) || value <= 0)) {
    throw new Error('Incomplete or invalid measurements');
  }
  return [...times].sort((a, b) => a - b)[Math.floor(times.length / 2)];
}

export function validatedRatio(referenceSeconds, iterationSeconds, expectedCount, validated) {
  if (validated !== true || !Number.isFinite(referenceSeconds) || referenceSeconds <= 0) {
    throw new Error('Output validation and positive reference time are required');
  }
  return referenceSeconds / selectMeasuredTime(iterationSeconds, expectedCount);
}

export function sumMainCommandSeconds(commands) {
  if (!Array.isArray(commands) || commands.length === 0) throw new Error('No main commands');
  let total = 0;
  for (const command of commands) {
    if (command.role !== 'main' || command.exitCode !== 0 || command.cancelled !== false ||
        !Number.isFinite(command.seconds) || command.seconds <= 0) {
      throw new Error('Invalid main command');
    }
    total += command.seconds;
  }
  return total;
}
timing.cpp 17 lines Download ↓
#include <cstdint>
#include <optional>

// Standalone arithmetic example. Process/exit validation belongs to the runner.
std::optional<double> ScoredSeconds(
    uint64_t processStart, uint64_t processEnd,
    uint64_t loadStart, uint64_t loadEnd, bool loadCompleted)
{
    if (!loadCompleted || processStart == 0 ||
        processEnd < processStart || loadStart < processStart ||
        loadEnd < loadStart || loadEnd > processEnd) return std::nullopt;
    const uint64_t raw = processEnd - processStart;
    const uint64_t load = loadEnd - loadStart;
    if (raw <= load) return std::nullopt;
    return static_cast<double>(raw - load) / 1e9;
}