You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何正确测量flex/bison解析器的纯解析平均耗时?

问题原因
  • 第一次yyparse()执行完成后,文件指针yyin已经移动到文件末尾,后续调用解析时读取到的是EOF,会直接触发语法错误
  • flex词法分析器内置了缓冲区、当前解析位置、状态标记等内部状态,第一次解析完成后这些状态不会自动重置,会影响后续解析流程
  • bison语法解析器自身也维护了语法栈、错误标记等内部状态,未重置的情况下二次执行会残留上一次的运行数据
  • 原有实现中start规则的printf输出属于IO操作,会被计入耗时统计,不符合你只统计解析阶段耗时的需求
正确实现步骤
  • 每次调用yyparse()前,先将文件指针重置到文件起始位置
  • 调用flex提供的yyrestart(yyin)接口重置词法分析器的所有内部状态
  • 调用bison的yyreset()接口重置语法解析器的内部状态(需要bison 3.0及以上版本,可在.y文件开头添加%define parse.reset 1开启该接口)
  • 临时注释掉.y文件start规则里的所有printf输出逻辑,或者将标准输出重定向到空设备,避免IO操作干扰耗时统计结果
修改后的示例代码
int main(int argc, char *argv[])
{
    struct timeval begin, end;
    
    yyin = fopen(argv[1], "r");
    if (!yyin) {
        perror("文件打开失败");
        return 1;
    }
    
    // 可选:将标准输出重定向到空设备,避免解析结果输出的IO耗时干扰统计
    // freopen("/dev/null", "w", stdout);

    // 开始计时
    gettimeofday(&begin, 0);
    int i;
    for (i=0; i<100; i++) {
        // 重置文件指针到文件开头
        fseek(yyin, 0, SEEK_SET);
        // 重置flex词法分析器状态
        yyrestart(yyin);
        // 重置bison语法解析器状态
        yyreset();
        yyparse();
    }
    
    // 结束计时并计算耗时
    gettimeofday(&end, 0);
    long seconds = end.tv_sec - begin.tv_sec;
    long microseconds = end.tv_usec - begin.tv_usec;
    double elapsed = seconds + microseconds*1e-6;
    printf("100次解析总耗时: %.6f 秒\n", elapsed);
    printf("单次解析平均耗时: %.6f 秒\n", elapsed/100);
    
    fclose(yyin);
    
    return 0;
}

特殊场景说明

如果你使用的是可重入版本的flex/bison(编译时添加了--reentrant参数),需要自行维护解析上下文句柄,每次传入新的上下文或者手动清空上下文内容即可。

内容的提问来源于stack exchange,提问作者Roger Costello

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 15:45:01