20000 个文件跑了 11500 秒:你压的是 YARN 调度器,不是 HDFS

20000 个文件跑了 11500 秒:你压的是 YARN 调度器,不是 HDFS

关键词:TestDFSIO、HDFS 基准测试、YARN 调度器、maximum-offswitch-assignments、心跳间隔、容器分配速率、Hadoop 性能测试、TeraSort、小文件、基准测试设计

目录

  • 一、先说结论
  • 二、测试现场
  • [三、结果:五轮写入,稳定得不像 I/O](#三、结果:五轮写入,稳定得不像 I/O "#%E4%B8%89%E7%BB%93%E6%9E%9C%E4%BA%94%E8%BD%AE%E5%86%99%E5%85%A5%E7%A8%B3%E5%AE%9A%E5%BE%97%E4%B8%8D%E5%83%8F-io")
  • 四、第一反应:是不是磁盘不行
  • [五、转折:有人问了一句"分配 container 要多久"](#五、转折:有人问了一句"分配 container 要多久" "#%E4%BA%94%E8%BD%AC%E6%8A%98%E6%9C%89%E4%BA%BA%E9%97%AE%E4%BA%86%E4%B8%80%E5%8F%A5%E5%88%86%E9%85%8D-container-%E8%A6%81%E5%A4%9A%E4%B9%85")
  • 六、算账:集群每秒能发多少个任务
  • 七、三个参数锁死了调度速率
  • [八、1333 秒只是下限](#八、1333 秒只是下限 "#%E5%85%AB1333-%E7%A7%92%E5%8F%AA%E6%98%AF%E4%B8%8B%E9%99%90")
  • [九、90% 的时间,磁盘在空转](#九、90% 的时间,磁盘在空转 "#%E4%B9%9D90-%E7%9A%84%E6%97%B6%E9%97%B4%E7%A3%81%E7%9B%98%E5%9C%A8%E7%A9%BA%E8%BD%AC")
  • [十、读取为什么快 2.1 倍](#十、读取为什么快 2.1 倍 "#%E5%8D%81%E8%AF%BB%E5%8F%96%E4%B8%BA%E4%BB%80%E4%B9%88%E5%BF%AB-21-%E5%80%8D")
  • [十一、同一批测试里的 TeraSort](#十一、同一批测试里的 TeraSort "#%E5%8D%81%E4%B8%80%E5%90%8C%E4%B8%80%E6%89%B9%E6%B5%8B%E8%AF%95%E9%87%8C%E7%9A%84-terasort")
  • 十二、怎么改:少任务,大文件
  • 十三、如果真的要压小文件
  • 十四、复盘

一、先说结论

5 节点的 HDFS 集群,TestDFSIO 写 20000 个 100MB 文件,五轮平均耗时 11572 秒 (约 3.2 小时),吞吐只有 177 MB/s。

第一反应一定是"磁盘不行"或者"网络不行"。

但算完一笔账之后,结论是另一个方向:

这批数据不能代表 HDFS 的性能。它测的是 YARN 控制平面的任务分发能力。

支撑这个结论的有四层证据:

  1. 调度速率被三个参数锁死:全集群每秒最多分发 15 个容器,20000 个 task 光"发号"就要 1333 秒
  2. 动态心跳是关闭的:节点没有任何加速汇报的可能,即使任务队列堆积如山
  3. 五轮耗时极差只有 4.2%,读取 4 轮只有 1% :这种一致性是确定性瓶颈的特征,不是 I/O 抖动
  4. 单任务粒度太小:每个 task 只写 100MB(约 1 秒的 I/O),却要走完整的容器申请与 JVM 启动流程

一句话:

你测到的不是"字节吞吐",是"任务吞吐"。


二、测试现场

2.1 命令

arduino 复制代码
hadoop jar hadoop-mapreduce-client-jobclient-3.3.3-tests.jar TestDFSIO -write -nrFiles 20000 -fileSize 100
项 值
文件数 20000
单文件大小 100 MB
总数据量 20000 × 100MB = 2 TB
集群规模 5 节点(2 NN + 3~5 DN/NM)
写入轮次 5
读取轮次 4

-nrFiles 20000 这个参数,直接决定了这个测试会创建 20000 个 map task。

而 20000 个 task,就是这个问题的起点。

2.2 基准脚本

bash 复制代码
#!/bin/bash
# hadoop_benchmark.sh
HADOOP_BIN="/opt/hadoop/bin/hadoop"
TEST_JAR="/opt/hadoop/share/hadoop/mapreduce/hadoop-mapreduce-client-jobclient-3.3.3-tests.jar"
EXAMPLE_JAR="/opt/hadoop/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.3.3.jar"
​
LOG_FILE="./benchmark_$(date +%Y%m%d-%H%M%S).log"
CSV_FILE="./benchmark_result_$(date +%Y%m%d-%H%M%S).csv"
​
RUN_TIMES=${1:-1}
MODE=${2:-"dfsio-write"}
​
echo "round,test_type,start_time,end_time,cost_seconds" > $CSV_FILE
​
clean_hdfs() {
    $HADOOP_BIN fs -rm -r -skipTrash /test/terasort-input   >/dev/null 2>&1
    $HADOOP_BIN fs -rm -r -skipTrash /test/terasort-output  >/dev/null 2>&1
    $HADOOP_BIN fs -rm -r -skipTrash /benchmarks/TestDFSIO* >/dev/null 2>&1
}
​
run_test() {
    local i=$1
    clean_hdfs
​
    START_TIME=$(date +%s);  START_HUMAN=$(date "+%Y-%m-%d %H:%M:%S")
​
    case $MODE in
        dfsio-write) $HADOOP_BIN jar $TEST_JAR TestDFSIO -write -nrFiles 20000 -fileSize 100 | tee -a $LOG_FILE ;;
        dfsio-read)  $HADOOP_BIN jar $TEST_JAR TestDFSIO -read  -nrFiles 20000 -fileSize 100 | tee -a $LOG_FILE ;;
        teragen)     $HADOOP_BIN jar $EXAMPLE_JAR teragen 10000000000 /test/terasort-input | tee -a $LOG_FILE ;;
        terasort)    $HADOOP_BIN jar $EXAMPLE_JAR terasort /test/terasort-input /test/terasort-output | tee -a $LOG_FILE ;;
        *) echo "[ERROR] Unknown mode: $MODE"; exit 1 ;;
    esac
​
    END_TIME=$(date +%s);  END_HUMAN=$(date "+%Y-%m-%d %H:%M:%S")
    COST=$((END_TIME - START_TIME))
    echo "$i,$MODE,$START_HUMAN,$END_HUMAN,$COST" >> $CSV_FILE
}
​
for ((i=1; i<=RUN_TIMES; i++)); do run_test $i; done

脚本本身没问题------清理、计时、落 CSV、多轮循环都有。

问题不在脚本,在参数。


三、结果:五轮写入,稳定得不像 I/O

3.1 写入 5 轮

轮次 耗时(秒)
1 11855
2 11538
3 11701
4 11399
5 11370
平均 11572

极差 485 秒,波动率 4.2%。

3.2 读取 4 轮

轮次 耗时(秒)
1 5324
2 5360
3 5304
4 5341
平均 5332

极差 56 秒,波动率 1.05%。

3.3 换算吞吐

bash 复制代码
写入:2 TB ÷ 11572 s ≈ 177 MB/s
读取:2 TB ÷ 5332 s ≈ 384 MB/s

3.4 这里有个细节值得盯一下

读取 4 轮的波动只有 1%。

真实的磁盘 I/O 很难这么稳------页缓存命中率、后台 compaction、GC、网络抖动,都会让结果上下浮动个几秒到几十秒。

1% 的波动率,说明瓶颈是确定性的、每次都会发生、且每次都消耗几乎相同的时间。

这不是"磁盘状态有波动"的特征,是"每个任务都要走一遍固定流程"的特征。


四、第一反应:是不是磁盘不行

看到 177 MB/s,第一反应是排查硬件:

检查项 结果
磁盘健康(SMART / iostat) 正常
网络带宽 正常
DataNode 存活 5 台都在
副本数 / 块大小 默认,正常
NameNode RPC 队列 不积压

硬件层面没有明显短板。

照这个方向继续查下去,会陷入"每块盘看起来都正常,但整体就是慢"的困境。


五、转折:有人问了一句"分配 container 要多久"

当时已经准备去测单盘 IOPS 了。

然后被问了一个很简单的问题:

"20000 个 map,光分配 container 要多久?跟 HDFS 性能有关系吗?"

这句话把方向整个掰了过来。

因为 TestDFSIO 的 20000 个文件 = 20000 个 map task,而每一个 task 都必须:

复制代码
排队 → 向 RM 申请容器 → 拿到容器 → 启动 JVM → 干活 → 回收

"干活"只是这条链上的一环。

如果这条链的入口 每秒只能放进 15 个,那 20000 个就要 1300 多秒------这跟磁盘快慢一点关系都没有。


六、算账:集群每秒能发多少个任务

YARN 是拉取式调度:ResourceManager 不会主动把任务推给节点,必须等 NodeManager 发心跳来领。

所以"每秒能派发多少任务"由三个东西决定:

复制代码
分配速率 = 计算节点数 × 心跳频率 × 单次心跳可分配容器数

代入实测参数:

ini 复制代码
计算节点数        : 3(5 节点集群中 2 台是 NN)
心跳频率          : 1 次/秒(1000ms)
单次可分配容器数   : 5
​
分配速率 = 3 × 1 × 5 = 15 容器/秒

6.1 20000 个任务需要多久才能"发完"

yaml 复制代码
20000 ÷ 15 ≈ 1333 秒   (约 22 分钟)

如果 5 个计算节点全在(而不是 3 个):

ini 复制代码
5 × 1 × 5 = 25 容器/秒
20000 ÷ 25 = 800 秒    (约 13 分钟)

光把任务派发下去,最少也要 13--22 分钟。

6.2 这段时间里集群在干什么

任务不是"一次性全发下去然后同时跑",而是:

ini 复制代码
t=0s    发出第 1--15 个,开始跑
t=1s    发出第 16--30 个
t=2s    ...
        ↓
前面发下去的任务早就跑完了(每个只写 100MB)
后面的任务还在排队等号
        ↓
集群的真实状态:跑一阵,等一阵

集群不是被数据压垮的,是被"发号"的速度限制住的。


七、三个参数锁死了调度速率

这三个数字都不是拍脑袋,全部来自配置和源码。

7.1 maximum-offswitch-assignments = 5

ini 复制代码
yarn.scheduler.capacity.per-node-heartbeat.maximum-offswitch-assignments = 5

这个参数的含义是:每个节点、每次心跳,最多分配多少个"非本地(off-switch)"容器。

默认值就是 5。

这是 Capacity Scheduler 的保护机制:防止一次心跳把大量容器塞给一个节点,造成节点过载和调度抖动。

它就是那个"每秒最多领 5 个号"的来源。

7.2 heartbeat-interval-ms = 1000

ini 复制代码
yarn.resourcemanager.nodemanagers.heartbeat-interval-ms = 1000

NodeManager 每秒向 RM 汇报一次。

源码里它是硬编码的默认值:

arduino 复制代码
// YarnConfiguration.java
public static final int DEFAULT_RM_NM_HEARTBEAT_INTERVAL_MS = 1000;

7.3 heartbeat-interval-scaling-enable = false(最关键的一个)

ini 复制代码
yarn.resourcemanager.nodemanagers.heartbeat-interval-scaling-enable = false

这一项才是让人绝望的地方。

YARN 其实提供了一个"动态心跳"机制:当队列堆积时,可以让节点加快汇报频率。

ini 复制代码
# 动态心跳的相关参数
yarn.resourcemanager.nodemanagers.heartbeat-interval-scaling-enable = false
yarn.resourcemanager.nodemanagers.heartbeat-interval-min-ms = 1000
yarn.resourcemanager.nodemanagers.heartbeat-interval-max-ms = 1000

但 scaling-enable 默认是 false。

也就是说:

系统完全忽略 min-ms / max-ms 的调整逻辑,强制使用固定的 1000ms。

NodeManager 没有任何加速汇报状态的可能------哪怕任务队列堆到两万个,它依然保持"每秒一次"的节奏。

7.4 三个参数合起来

ini 复制代码
scaling-enable = false        → 心跳频率锁死在 1 Hz,不能加速
heartbeat-interval-ms = 1000  → 每秒只有 1 次机会
maximum-offswitch-assignments = 5 → 每次机会最多领 5 个
        ↓
每个节点每秒最多 5 个容器
        ↓
整个集群每秒最多 15 个(3 个计算节点)

八、1333 秒只是下限

1333 秒是"任务全部就绪、资源充足、完美匹配"情况下的理论最小值。

实际还要叠加三块开销:

开销 量级 说明
AM ↔ RM 交互延迟 每次约 2 秒 ApplicationMaster 心跳与资源协商
JVM 启动/销毁 1--3 秒/任务 每个 map task 都要起一个 JVM
资源碎片等待 不确定 偶发性的等待,可能重试(speculative / retry)

所以真实的"任务级固定开销"远大于 1333 秒。

这也解释了为什么 11572 秒会出现在这么"整齐"的区间里------因为它不是被 I/O 决定的,是被这条流水线的节奏决定的。


九、90% 的时间,磁盘在空转

9.1 每个 task 到底干了多少活

bash 复制代码
单文件大小 : 100 MB
单个 task  : 写 100 MB
按单盘 100 MB/s 估算 : 约 1 秒

每个 task 实际搬数据的时间,只有 1 秒左右。

但每个 task 的完整生命周期是:

复制代码
ResourceManager 分配容器
    ↓
NodeManager 创建容器目录
    ↓
启动 JVM
    ↓
加载 Hadoop 配置
    ↓
建立 HDFS 连接(含 Kerberos 认证)
    ↓
写入 100MB   ← 干活的部分,约 1 秒
    ↓
关闭文件、汇报状态、回收容器

开销是干活的数倍。

9.2 那真实带宽是多少

按经验估算,这类"小文件 + 海量任务"的评测里,真正在写数据的时间通常只占总时长的 5%--10% 。

反推一下:

yaml 复制代码
总时长 11572 s
有效 I/O 时间  ≈ 1157 s(按 10% 估)
真实写入带宽   ≈ 2048000 MB ÷ 1157 s ≈ 1770 MB/s ≈ 1.7 GB/s

注意这是推算值,不是实测值。 但它指出了一个量级差:

如果把这个测试改对,量出来的结果可能是 1.7 GB/s 量级 ,而不是报告上的 177 MB/s。 差了将近十倍。

而那 90% 的时间里,磁盘在干什么?

在等。


十、读取为什么快 2.1 倍

读取 5332s,写入 11572s,比例 2.16 倍。

这个比例同时被三层因素影响:

层 写入 读取
调度开销(共同下限) 约 800--1333s 约 800--1333s
单任务开销 建文件、分配块、写 pipeline 只读,流程更短
实际 I/O 2TB 写入 2TB 读取

HDFS 本身"读快写慢"是正常的(写入要走 3 副本 pipeline,读取可以直接从最近副本读)。

但有个反直觉的点:

因为两边都垫着同一块固定的调度成本,"2.1 倍"这个比值是被稀释过的。

也就是说,真实的磁盘读写性能差距,很可能比 2.1 倍更大------把这个固定成本扣掉之后,差距才会显出来。


十一、同一批测试里的 TeraSort

同一批基准里还跑了 MapReduce 计算性能:

测试 参数 耗时
TeraGen 10,000,000,000 行 4714 秒(约 1.3 小时)
TeraSort 1 TB 741 秒(约 12.3 分钟)

这两组数据的价值,不在于和 TestDFSIO 做性能对比(测试对象不同),而在于:

集群在连续数小时的压力测试下,没有出现服务中断、节点掉线、任务大面积失败。

一次测错的基准,数据不能用来评估性能,但可以证明"能撑住" 。

这也是这次测试唯一可靠的产出。


十二、怎么改:少任务,大文件

核心原则只有一条:

css 复制代码
单任务 I/O 时间 >> 单任务启动开销

12.1 参数怎么改

调整项 原来 改成 理由
文件数 20000 100 任务数降两个数量级,调度几秒内完成
单文件大小 100 MB 10 GB 单任务 I/O 从 1s 提到 100s
总数据量 2 TB 1 TB 测试时长可控

12.2 新命令

perl 复制代码
# 写入
hadoop jar hadoop-mapreduce-client-jobclient-3.3.3-tests.jar \
  TestDFSIO -write -nrFiles 100 -fileSize 10000MB
​
# 读取
hadoop jar hadoop-mapreduce-client-jobclient-3.3.3-tests.jar \
  TestDFSIO -read -nrFiles 100 -fileSize 10000MB

12.3 为什么这样就对了

css 复制代码
原来:20000 × 100MB
  单任务 I/O ≈ 1s,启动开销 ≈ 2s
  → 开销占比 ≈ 66%,调度耗时 ≈ 1333s
​
改后:100 × 10GB
  单任务 I/O ≈ 100s,启动开销 ≈ 2s
  → 开销占比 ≈ 2%,调度耗时 ≈ 7s

同样的思路,从"测任务吞吐"变成"测字节吞吐"。

12.4 预期结果与判定标准

指标 预期
调度开销 < 10 秒
测试总时长 完全由磁盘写入速度决定
吞吐 大幅提升,接近硬件物理极限

判定方法:

  • 如果吞吐显著提升 → 之前的瓶颈确实是调度,结论成立
  • 如果吞吐几乎没变 → 这时候才轮到查磁盘、查网络、查副本策略

十三、如果真的要压小文件

有一种场景是合理的:你就是要评估"海量小文件"对集群的冲击。

这时候要测的不是 HDFS 带宽,而是 YARN 调度器 + NameNode 元数据的能力。

13.1 临时放开调度限制(测试后必须还原)

ini 复制代码
# 开启动态心跳
yarn.resourcemanager.nodemanagers.heartbeat-interval-scaling-enable = true
​
# 允许最快 100ms 一次心跳
yarn.resourcemanager.nodemanagers.heartbeat-interval-min-ms = 100
​
# 单次心跳放开到 100 个容器
yarn.scheduler.capacity.per-node-heartbeat.maximum-offswitch-assignments = 100

改完之后,分配速率从:

ini 复制代码
3 × 1 × 5 = 15 /s

变成:

ini 复制代码
3 × 10 × 100 = 3000 /s

理论上快了 200 倍。

13.2 三个必须提醒的地方

① 这组参数有风险

maximum-offswitch-assignments 调大,会让单节点在极短时间内被塞入大量容器,可能造成:

  • NodeManager 本地磁盘 IO 打满
  • 容器启动风暴,JVM 争抢 CPU
  • 调度器抖动,影响其他队列

② 必须还原

压测完立刻改回默认值。这类参数一旦遗留在生产环境,下一次流量高峰可能就是事故。

③ 不要用改参数来"美化" HDFS 带宽测试

你如果只是想测磁盘,改参数是错误的方向------那是在改被测系统,而不是改测试方法。


十四、复盘

14.1 六个判断

① 基准测试的第一步,是算清楚"这套测试最快能跑多快"

理论下限 1333 秒,实测 11572 秒 ------ 先算天花板,才知道大头在哪。

② "结果太稳定"本身就是一个信号

读取 4 轮波动 1%、写入 5 轮波动 4.2%。当一个本该有抖动的指标变得极其稳定时,说明瓶颈是确定性的,不是物理的。

③ 拉取式调度系统,天然有"发号上限"

YARN、K8s、Mesos 都是拉取式。

它们的能力上限不是"能跑多快",而是"每秒能派出去多少"。

④ 动态心跳默认关闭,是很多人不知道的一层

heartbeat-interval-scaling-enable=false 意味着堆积不会触发加速。

很多人以为"队列长了系统会自己加快",不会。

⑤ 任务粒度决定了你测的是"任务吞吐"还是"字节吞吐"

20000 × 100MB 和 100 × 10GB,前者测调度器,后者测磁盘。

任务数超过某个量级,被测对象就自动换了。

⑥ 测错的基准不是废数据

这次 11500 秒不能评估 HDFS 性能,但证明了集群在 3 小时连续压力下稳定运行。

很多测试的价值,不在它原本要测的方向上。

14.2 下次做基准测试前的检查清单

检查项 怎么判断
任务数是否合适 总任务数 ÷ 调度速率 应远小于预估总耗时
单任务 I/O 是否够大 单任务 I/O 时间应 ≥ 启动开销的 10 倍
是否已知调度速率 节点数 × 心跳频率 × 单次分配数
动态心跳是否开启 heartbeat-interval-scaling-enable
结果波动是否合理 波动过小 → 怀疑确定性瓶颈
读/写是否分开 分开跑,不要混在一轮里
是否动了生产参数 不应该动

附:改进版脚本

bash 复制代码
#!/bin/bash
# hadoop_benchmark.sh ------ 两段式:大文件测 I/O,小文件测调度
HADOOP_BIN="/opt/hadoop/bin/hadoop"
TEST_JAR="/opt/hadoop/share/hadoop/mapreduce/hadoop-mapreduce-client-jobclient-3.3.3-tests.jar"
EXAMPLE_JAR="/opt/hadoop/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.3.3.jar"
​
STAMP=$(date +%Y%m%d-%H%M%S)
LOG_FILE="./benchmark_${STAMP}.log"
CSV_FILE="./benchmark_result_${STAMP}.csv"
RUN_TIMES=${1:-1}
MODE=${2:-"dfsio-write-big"}
​
echo "round,test_type,start_time,end_time,cost_seconds" > "$CSV_FILE"
​
clean_hdfs() {
    echo "[INFO] cleaning HDFS..." | tee -a "$LOG_FILE"
    $HADOOP_BIN fs -rm -r -skipTrash /test/terasort-input   >/dev/null 2>&1
    $HADOOP_BIN fs -rm -r -skipTrash /test/terasort-output  >/dev/null 2>&1
    $HADOOP_BIN fs -rm -r -skipTrash /benchmarks/TestDFSIO* >/dev/null 2>&1
}
​
run_test() {
    local i=$1
    echo "" | tee -a "$LOG_FILE"
    echo "---------- Round $i ($MODE) ----------" | tee -a "$LOG_FILE"
    clean_hdfs
​
    local START_TIME START_HUMAN END_TIME END_HUMAN COST
    START_TIME=$(date +%s)
    START_HUMAN=$(date "+%Y-%m-%d %H:%M:%S")
​
    case $MODE in
        # 大文件:测真实 I/O 带宽(推荐)
        dfsio-write-big) $HADOOP_BIN jar $TEST_JAR TestDFSIO -write -nrFiles 100 -fileSize 10000MB | tee -a "$LOG_FILE" ;;
        dfsio-read-big)  $HADOOP_BIN jar $TEST_JAR TestDFSIO -read  -nrFiles 100 -fileSize 10000MB | tee -a "$LOG_FILE" ;;
        # 小文件:测调度与元数据压力(对比用)
        dfsio-write-small) $HADOOP_BIN jar $TEST_JAR TestDFSIO -write -nrFiles 20000 -fileSize 100 | tee -a "$LOG_FILE" ;;
        dfsio-read-small)  $HADOOP_BIN jar $TEST_JAR TestDFSIO -read  -nrFiles 20000 -fileSize 100 | tee -a "$LOG_FILE" ;;
        # 计算性能
        teragen)  $HADOOP_BIN jar $EXAMPLE_JAR teragen 10000000000 /test/terasort-input | tee -a "$LOG_FILE" ;;
        terasort) $HADOOP_BIN jar $EXAMPLE_JAR terasort /test/terasort-input /test/terasort-output | tee -a "$LOG_FILE" ;;
        *) echo "[ERROR] Unknown mode: $MODE" | tee -a "$LOG_FILE"; exit 1 ;;
    esac
​
    END_TIME=$(date +%s)
    END_HUMAN=$(date "+%Y-%m-%d %H:%M:%S")
    COST=$((END_TIME - START_TIME))
​
    echo "[RESULT] Round $i cost: ${COST}s" | tee -a "$LOG_FILE"
    echo "$i,$MODE,$START_HUMAN,$END_HUMAN,$COST" >> "$CSV_FILE"
}
​
for ((i=1; i<=RUN_TIMES; i++)); do
    run_test "$i"
done
​
echo "" | tee -a "$LOG_FILE"
echo "=========== Completed. CSV: $CSV_FILE ===========" | tee -a "$LOG_FILE"

用法:

bash 复制代码
# 大文件写入(测 I/O 带宽)
./hadoop_benchmark.sh 1 dfsio-write-big
​
# 小文件写入(对照:看调度影响)
./hadoop_benchmark.sh 1 dfsio-write-small
​
# TeraGen + TeraSort
./hadoop_benchmark.sh 1 teragen && ./hadoop_benchmark.sh 1 terasort

最后一句

这次测试最有价值的产出,不是那 177 MB/s,而是想明白了一件事:

当你测一个系统时,如果测试本身的开销超过了被测对象的开销, 你测到的就是测试框架,不是那个系统。

下次跑基准之前,先花五分钟算一下"这套测试最快能跑多快"。

五分钟的算术,能省下三小时的白跑。

相关推荐
wtblszn8 小时前
农村供水站远程监控智能管理方案
大数据
aixingkong9219 小时前
华为灵衢超节点参考架构白皮书深度解读
大数据·人工智能·华为
大大大大晴天10 小时前
每天认识一个组件:Apache Iceberg
大数据
xiaoyunxuexibiji11 小时前
采购协同管理:从备货计划、进度确认到到货签收
大数据·运维·人工智能
2601_9578752012 小时前
华立科技荣获环球品牌与合作(大中华区)年度“最佳街机游戏合作伙伴”
大数据·科技·游戏
BJ_Bonree13 小时前
聊点技术 | Bonree ONE 业务链路观测实战 支付成功率下降,问题究竟出在哪一环?
大数据·人工智能
IT研究室13 小时前
最新大数据毕业设计选题推荐-基于大数据的Kaggle竞赛团队协作模式与效能可视化分析-大数据-Spark-Hadoop-Bigdata
大数据·spark·课程设计
骑着蜗牛撵大象32713 小时前
闲鱼捡漏自动化:关键词加价格上限先粗筛,AI 大模型再做第一轮判定
大数据·人工智能·ai·自动化·二手交易·闲鱼·关键词监控