说明:本系列文章为个人笔记,如有不正确之处,请参考官方相关文档,如果错误发现,我会尽量更新修改。另外,以下内容不保证对于所有版本的编译器都正确,编译器的实现也可能有一些变化之处,具体参考官方文档。
更多说明请参考http://blog.youkuaiyun.com/gengshenghong/article/details/7034748中补充说明部分。
Summary:这里的工具是tselect,test prioritization Tool,从字面上,测试优先级工具,应该也是和测试相关的,所以测试人员可能比较容易理解,下面只是大概理解一下tselect的内容和如何使用,对于测试理论,我也不太懂。
关于测试优先级可参考:
http://blog.youkuaiyun.com/lengyue_112/article/details/375342
http://edu.21cn.com/ruankao/g_185_695002-1.htm等
(1) 测试优先级的作用
参考相关内容理解。
(2) PGO测试优先级工具tselect的使用介绍
1. 需要的文件
类似于codecov工具,tselect涉及的文件有:使用/Qprof-gen:srcpos选项编译得到的spi文件,由dyn文件合并的dpi文件。
2. tselect使用
使用:tselect -dpi_list file
其中-dpi_list是一个必须的选项,还有一些其它可选选项。
下面是tselect工具使用的典型模型:
简单的理解,第一步,使用/Qprof-gen:srcpos得到spi文件和辅助可执行文件,多次使用不同的测试数据运行辅助可执行文件,分别得到其dpi文件,将dpi文件以列表的形式放入一个文本文件中,使用tselect工具即可。
(3)实例:
以http://blog.youkuaiyun.com/gengshenghong/article/details/7053847中的差异覆盖的代码为例子(代码如下):
// File: tselect.cpp
#include <stdio.h>
void foo()
{
printf("This is foo\n");
}
void bar()
{
printf("This is bar\n");
}
void foobar()
{
printf("This is foobar\n");
}
int main(int argc, char* argv[])
{
int count = argc;
switch(count)
{
case 0:
printf("Case0\n");
break;
case 1:
printf("Case1\n");
foo();
break;
case 2:
printf("Case2\n");
bar();
break;
case 3:
printf("Case3\n");
foo();
bar();
break;
case 4:
printf("Case4\n");
foobar();
break;
}
}
@echo OFF
rem #File: build.bat
set exeargs=arg1 arg2 arg3
rem #can set env vars in command line or in this file before run this bat file.
if exist *.obj del *.obj
if exist *.exe del *.exe
if exist *.dyn del *.dyn
if exist *.lock del *.lock
if exist *.dpi del *.dpi
if exist *.spi del *.spi
if exist *.spl del *.spl
icl tselect.cpp -o tselect.exe /Od /Qprof-gen:srcpos /nologo
tselect.exe %exeargs%
profmerge
分别得到执行case1234情况下对应的dpi和spi,如下:
PGOPTI.SPI
pgopti1.dpi
pgopti2.dpi
pgopti3.dpi
pgopti4.dpi
创建文件list.txt如下:
pgopti4.dpi
pgopti3.dpi
pgopti2.dpi
pgopti1.dpi
然后运行:
tselect -dpi_list list.txt
输出如下:
Intel(R) C++/Fortran Compiler test prioritizer for applications running on Intel
(R) 64, Version 12.1 Build 20111128
Copyright (C) 1985-2011 Intel Corporation. All rights reserved.
WARNING: no SPI file name was specified, assumed .\pgopti.spi.
Total number of tests = 4
Total block coverage ~ 91.67
Total function coverage ~ 100.00
num %RatCvrg %BlkCvrg %FncCvrg Test Name @ Options
--- -------- -------- -------- -------------------
1 50.00 45.83 75.00 pgopti3.dpi
2 72.73 66.67 100.00 pgopti4.dpi
3 86.36 79.17 100.00 pgopti2.dpi
4 100.00 91.67 100.00 pgopti1.dpi
说明:运行tselect需要一个列表文件和对应的多个dpi文件,以及一个spi文件(默认是pgopti.spi),不需要源代码(这是和codecov不同的,codecov需要源代码,否则结果错误)。
1. 相关基本参数含义
上面的tselect的输出相关参数的含义如下:
(total number of tests)测试的总数为4,由list.txt决定,list.txt列举了多少个dpi文件,就是多少。
(total block coverage)总的块覆盖率为91.67%。
(total function coverage)总的函数覆盖率为100%。
下面的表格分别对应于列表中每一个测试的情况。
从上面的结果可以知道如下信息,运行pgopti3.dpi对应的测试覆盖了程序45.83%的基本块,占到了所有四次测试可以获得的总的块覆盖率的50%(即45.83%/91.67%=50%),另外,它对应的测试覆盖了75%的函数覆盖率(一共有foo、bar、foobar和main四个函数,case3的时候覆盖了其中的foo、bar和main三个函数,所以是75%);运行pgopti4.dpi对应的测试后,累积覆盖了程序66.67%的基本块,占到了总的四次测试可以获得的块覆盖率的72.73%(即66.67%/91.67%=72.73%),另外,它对应的测试累积覆盖了100%的函数覆盖率(case4会覆盖foobar函数,所以所有函数都被覆盖到了);其它的类似。
说明:
A、这里是有一个顺序问题,后面的测试是前面的累积的结果。另外,不太清楚这个pgopti3、4、2、1的顺序是如何确定的,跟list.txt的列举顺序没关系,无论怎么样的顺序列举,得到的tselect结果的顺序都是pgopti3、4、2、1!Why?(更新:参考下面的内容得到答案)
B、由于显示的是累积的结果,如果某一次测试对前面的测试结果的覆盖率等数据不产生变化,那么就不会显示在下面的表格中。比如list.txt如下:
pgopti4.dpi
pgopti3.dpi
pgopti2.dpi
pgopti1.dpi
pgopti4.dpi
pgopti3.dpi
pgopti2.dpi
pgopti1.dpi
对应的结果如下:
Total number of tests = 8
Total block coverage ~ 91.67
Total function coverage ~ 100.00
num %RatCvrg %BlkCvrg %FncCvrg Test Name @ Options
--- -------- -------- -------- -------------------
1 50.00 45.83 75.00 pgopti3.dpi
2 72.73 66.67 100.00 pgopti4.dpi
3 86.36 79.17 100.00 pgopti2.dpi
4 100.00 91.67 100.00 pgopti1.dpi
测试总数为8,但是表格只有4行。
3. 估算最少执行时间
有了上面的理解,下面的内容就简单了。可以在list.txt的每一行测试后面加一个表示时间的数据,然后,使用-mintime选项来估算完成所有测试的最小执行时间的顺序(如果不使用-mintime选项,也可以在每行测试后写一个时间,这不是必须的,写了也没有什么影响,如果使用了-mintime选项,那么每行必须有一个时间,这个时间要符合一定的格式)。如下是list.txt的例子:
pgopti4.dpi 00:00:40:04
pgopti3.dpi 00:00:30:03
pgopti2.dpi 00:00:20:02
pgopti1.dpi 00:00:10:01
pgopti1.dpi 00:00:10:01
注意:其中dpi文件名和后面的时间之间可以有任意多个空格,但是,不能有tab(这点有点不友好)。
tselect -dpi_list list.txt -mintime
得到:
Total number of tests = 5
Total block coverage ~ 91.67
Total function coverage ~ 100.00
Total execution time = 1:50:11
num elapsedTime %RatCvrg %BlkCvrg %FncCvrg Test Name @ Options
--- ----------- -------- -------- -------- -------------------
1 10:01 36.36 33.33 50.00 pgopti1.dpi
2 30:03 59.09 54.17 75.00 pgopti2.dpi
3 1:00:06 77.27 70.83 75.00 pgopti3.dpi
4 1:40:10 100.00 91.67 100.00 pgopti4.dpi
所以,一共五次测试,其中总的执行时间只需要1:50:11就能达到最大的覆盖率,顺序就是按照时间顺序从少到多的,其中list.txt中的最后一个pgopti1.dpi(第五次测试)是不需要进行的,因为它的执行对覆盖率没有任何影响。(当然,这里故意用同一个dpi数据,所以肯定不会改变覆盖率,但是不同的dpi也可以不改变覆盖率的)。
4. 其他选项
到这里,就基本理解了tselect的作用和用法了,接下来就看看其它的选项。
-help: 显示帮助。
-dpi_list file: 唯一一个必须有的选项,指定列表文件。
-spi file: 指定spi文件。
-o file: 指定tselect输出的报告的文件,默认情况下是输出到控制台的,指定-o后,直接输出到文件,控制台不输出。
-mintime: 估算最小执行时间。
-nototal: 报告中不包含total的那些信息。
-verbose: 工具会显示运行时的更多日志信息,且报告中会显示更详细的信息。
-cutoff value: 其参数是一个值,指定tselect工具在累积块覆盖率达到预计的总的块覆盖率的value%的值的时候就终止。比如:tselect -dpi_list list.txt -cutoff 10.00,表示只要块覆盖率达到10%就终止。下面是一个列子:
tselect -dpi_list list.txt -cutoff 49
得到:
Total number of tests = 5
Total block coverage ~ 91.67
Total function coverage ~ 100.00
num %RatCvrg %BlkCvrg %FncCvrg Test Name @ Options
--- -------- -------- -------- -------------------
1 50.00 45.83 75.00 pgopti3.dpi
同样的例子,使用:tselect -dpi_list list.txt -cutoff 51,得到:
Total number of tests = 5
Total block coverage ~ 91.67
Total function coverage ~ 100.00
num %RatCvrg %BlkCvrg %FncCvrg Test Name @ Options
--- -------- -------- -------- -------------------
1 50.00 45.83 75.00 pgopti3.dpi
2 72.73 66.67 100.00 pgopti4.dpi
-srcbasedir dir:
-comp: