code-coverage - profiler.out 内容代表什么?

标签 code-coverage profiler openedge progress-4gl

我一直在研究从 profiler.out 文件中检索测试代码覆盖率数据的脚本。现在生成这个文件不是什么大问题。但我似乎无法理解这个文件的内容与被触发的测试有何关系(对我来说,这些看起来就像随机数字和字符串)...

有人知道这些数字代表什么吗?

我生成了一个示例分析器文件(源语言是 Progress),如下所示:

Example Profiler Output

提前致谢!

雅各

最佳答案

OpenEdge Profiler 的文档“很少”。如果你搜索 Progress kbase,它会出现几个条目,最终导致: https://community.progress.com/community_groups/openedge_general/w/openedgegeneral/1980.profiler-control-tool

这是旧的不受支持的独立“分析器控制工具”(该工具不受支持,支持分析器启动选项和 session 句柄)。

在该页面链接到的 zip 文件中是唯一已知的探查器输出格式文档。

当前的 OpenEdge 11 IDE (PDSOE) 直接支持分析器分析工具。

下面的代码不是很漂亮,但它是一个独立的工具,可以读取分析器输出文件(我更喜欢将它们命名为“something.prf”而不是“profiler.out”)并生成报告最耗时的代码行:

/* zprof_topx.p
 *
 * process a .prf file and produce a report
 *
 * pro -p lib/zprof_topx.p -param tmp/f03e40c9-8043-0aba-e611-3cc5eac467bd.2016.12.18.11.12.14
 *
 * note: there is no ".prf" at the end of the file name!
 *
 */

define variable zprofData as character no-undo.
define variable topLines  as integer no-undo initial 20.

define temp-table tt_profile
  field id          as integer format ">>>>9"
  field pdate       as date format "99/99/99"
  field description as character format "x(30)"
  index profile-idx is unique primary
    id
  index profile-date
    pdate
.

define temp-table tt_source
  field id          as integer format ">>>>9"
  field pid         as integer format ">>>>>9"
  field pname       as character format "x(40)"
  field debug_name  as character format "x(40)"
  index source-idx is unique primary
    id pid
  index source-name
    pname
.

define temp-table tt_tree
  field id          as integer format ">>>>9"
  field caller      as integer format ">>>>>9"
  field src_line    as integer format ">>>>>9"
  field callee      as integer format ">>>>>9"
  field call_count  as integer format ">>>>>9"
  index tree-idx is primary
    id caller src_line callee
.

define temp-table tt_ptime
  field id          as integer format ">>>>9"
  field pid         as integer format ">>>>>9"
  field src_line    as integer format ">>>>>9"
  field exec_count  as integer format ">>>>>>>>>9"
  field exe_time    as decimal format ">>>>>9.999999"
  field tot_time    as decimal format ">>>>>9.999999"
  field avg_time    as decimal format ">>>>>9.999999"
  index ptime-idx is unique primary
    id pid src_line
  index avg-idx
    avg_time descending
  index line-idx
    src_line
  index ptime-pid-t1
    id pid exe_time
  index ptime-pid-t3
    id pid avg_time
  index ptime-t1
    id exe_time
  index ptime-t3
    id avg_time
.

define temp-table tt_code_line
  field pid         as integer   format ">>>>>9"        /* program id#              */
  field src_line    as integer   format ">>>>9"         /* source line#             */
  field pname       as character format "x(30)"         /* procedure or class name      */
  field ipname      as character format "x(40)"         /* internal procedure or method name    */
  field t1          as decimal   format ">>>>>9.999999"     /* execution time           */
  field t2          as integer   format ">>>>>>>>>9"        /* calls                */
  field t3          as integer   format ">>9"           /* sessions             */
  field t4          as decimal   format ">>>>>9.999999"     /* average time             */
  index bad-idx1 is unique primary
    pid pname src_line
  index bad-idx2
    t2 t3
  index bad-idx3
    t1
  index avg-idx
    t4
.


/*********************************************************/

define stream inStrm.

procedure zprofiler_load:

  define input parameter zprofData as character no-undo.

  define variable i   as integer   no-undo.
  define variable v   as integer   no-undo.
  define variable dt  as date      no-undo.
  define variable dsc as character no-undo.

  define variable profile_id as integer no-undo.

  empty temp-table tt_profile.
  empty temp-table tt_source.
  empty temp-table tt_tree.
  empty temp-table tt_ptime.

  file-info:file-name = zprofData + ".prf".

  if file-info:full-pathname = ? then
    do:
      message "Cannot find profiler .prf data file:" zprofData.
      pause.
      return.
    end.

  /* message "loading from:" file-info:full-pathname. /* session:date-format. */ pause. */

  input stream inStrm from value( file-info:full-pathname ).

  i = 1.

  repeat:               /* in theory there could be more than 1?  that would probably break a lot of stuff...   */

    import stream inStrm v /* dt */ ^ dsc no-error.     /* the profiler apparently ignores session:date-format...   */

    if v <> 1 then
      do:
        input stream inStrm close.
        message "Invalid version:" v.
        pause.
        return.
      end.

    /* message v dt dsc. pause. */              /* the profiler apparently ignores session:date-format...   */

    profile_id = i.

    create tt_profile.
    assign
      tt_profile.id          = profile_id
      tt_profile.pdate       = today /* dt */
      tt_profile.description = dsc
    .

    i = i + 1.

  end.

  /* message "profile id:" profile_id. pause. */

  i = 1.

  repeat:

      create tt_source.
      tt_source.id = profile_id.
      import stream inStrm tt_source.pid tt_source.pname tt_source.debug_name no-error.

      i = i + 1.

  end.

/*  message i "tt_source loaded". pause.
 *  message "creating tt_source session record". pause.
 */

  /* create tt_source. */       /* don't CREATE -- an extra will be left over from the REPEAT logic */
  assign
    tt_source.id = profile_id
    tt_source.pid = 0
    tt_source.pname = "Session"
    tt_source.debug_name = "Session"
  .

  /* message "tt_source session record created". pause. */

  i = 1.

  repeat:

    create tt_tree.
    tt_tree.id = profile_id.
    import stream inStrm tt_tree.caller tt_tree.src_line tt_tree.callee tt_tree.call_count no-error.

    i = i + 1.

  end.

  delete tt_tree.

  /* message i "tt_tree loaded". pause. */

  i = 1.

  repeat:


    create tt_ptime.
    tt_ptime.id = profile_id.
    import stream inStrm tt_ptime.pid tt_ptime.src_line tt_ptime.exec_count tt_ptime.exe_time tt_ptime.tot_time no-error.
    tt_ptime.avg_time = tt_ptime.exe_time / tt_ptime.exec_count.

    i = i + 1.

  end.

  delete tt_ptime.

  /* message i "tt_ptime loaded". pause. */

  input stream inStrm close.

  return.

end.


procedure zprofiler_proc:

  define variable c  as integer no-undo.
  define variable i  as integer no-undo.
  define variable t1 as decimal no-undo format ">>>>>9.999999".
  define variable t2 as integer no-undo format ">>>>>>>>>9".
  define variable t3 as integer no-undo format ">>9".

  define variable srcName    as character no-undo.
  define variable iprocName  as character no-undo.

  empty temp-table tt_code_line.

  for each tt_ptime no-lock by tt_ptime.avg_time descending:     

    /*  if exec_count < 1 /* or src_line = 0 */ then next. */

    find tt_source where
         tt_source.id =  tt_ptime.id and
         tt_source.pid = tt_ptime.pid no-error.

    if not available( tt_source ) then
      srcName = "session".
     else
      srcName = tt_source.pname.

    if srcName begins "lib/zprof" then next.            /* don't include the profiler */

    find tt_code_line where
         tt_code_line.pid      = tt_ptime.pid and
         tt_code_line.src_line = tt_ptime.src_line and
         tt_code_line.pname    = srcName /* tt_source.pname */ no-error.

    if not available tt_code_line then
      do:
        create tt_code_line.
        assign
          i = i + 1
          tt_code_line.pid      = tt_ptime.pid
          tt_code_line.src_line = tt_ptime.src_line
          tt_code_line.pname    = srcName
        .
      end.

  end.

  /* message i "entries processed". pause. */

  for each tt_code_line:

    assign
      tt_code_line.t1 = 0
      tt_code_line.t2 = 0
    .

    for
      each tt_source where
        tt_source.pname = tt_code_line.pname,
      each tt_ptime where
        tt_ptime.id       = tt_source.id  and
        tt_ptime.pid      = tt_source.pid and
        tt_ptime.src_line = tt_code_line.src_line:      

      assign
        tt_code_line.t1 = tt_code_line.t1 + tt_ptime.exe_time
        tt_code_line.t2 = tt_code_line.t2 + tt_ptime.exec_count
        tt_code_line.t3 = tt_code_line.t3 + 1
      .

      if tt_ptime.pid = 0 and tt_ptime.src_line = 0 then tt_code_line.t1 = tt_ptime.tot_time.

    end.

  end.

  for each tt_code_line:

    tt_code_line.t4 = ( tt_code_line.t1 / tt_code_line.t2 ).    /* calculate the average time... */

    if num-entries( tt_code_line.pname, " " ) > 1 then
      assign
        tt_code_line.ipname = entry( 1, tt_code_line.pname, " " )
        tt_code_line.pname  = entry( 2, tt_code_line.pname, " " )
      .

  end.

  return.

end.


procedure zprofiler_topx:

  define input parameter zprofData as character no-undo.
  define input parameter toTTY     as logical   no-undo.
  define input parameter topLines  as integer   no-undo.

  define variable c  as integer no-undo.
  define variable i  as integer no-undo.
  define variable t1 as decimal no-undo format ">>>>>9.999999".
  define variable t2 as integer no-undo format ">>>>>>>>>9".
  define variable t3 as integer no-undo format ">>9".

  define variable t9 as integer no-undo.

  find first tt_profile no-lock no-error.   /* assuming that they're all the same date... */

  for each tt_code_line no-lock where tt_code_line.pname <> "session":
    t9 = t9 + tt_code_line.t1.
  end.

  if toTTY = no then output to value( zprofData + ".rpt" ).

  display
    tt_profile.description  label "Description" format "x(70)" skip
    "Session Total Execution Time  " string( t9, "hh:mm:ss" )  skip
    "Line 0 = initialization, line -1 = cleanup"               skip
   with frame prof-hdr
     title " Profiler: Top Results "
     width 120
     centered
     overlay
     side-labels
     row 4
  .

  i = 0.

  for each tt_code_line no-lock by tt_code_line.t1 descending:

    if tt_code_line.pname = "session" then next.

    i = i + 1.

    display
      tt_code_line.pname    label "Program/Class"
      tt_code_line.src_line label "Line"
      tt_code_line.t1       label "Time"
      tt_code_line.t4       label "Avg Time"
      tt_code_line.t2       label "Calls"
      tt_code_line.ipname   label "Internal Procedure/Method"
     with frame prof-rpt
       title " Top Lines: Total Execution Time "
       width 120
       centered
       overlay
       down
       row 9
    .

    if i > topLines then leave.

  end.

  if toTTY = no then
    output close.
   else
    do:
      pause.
      hide frame prof-rpt.
      hide frame prof-hdr.
    end.

  return.

end.


/* main body
 *
 */

zprofData = entry( 1, session:parameter, "|" ).
if num-entries( session:parameter, "|" ) = 2 then topLines = integer( entry( 2, session:parameter, "|" )).

run zprofiler_load( zprofData ).            /* load profiler data into temp-tables to analyze       */
run zprofiler_proc.                 /* process the data                     */
run zprofiler_topx( zprofData, no,  topLines ).     /* report on the top X execution time lines -- to file      */

if session:batch = no then
  run zprofiler_topx( zprofData, yes, topLines ).   /* report on the top X execution time lines -- to TTY       */

quit.

关于code-coverage - profiler.out 内容代表什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53958452/

相关文章:

java - 确保对新的 Subversion 提交的覆盖率最小

intellij-idea - 在命令行中运行 IntelliJ IDEA 代码覆盖率

javascript - 无法在 WebStorm 中使用 Spy-js 分析 Babel 转译的 Node.js 应用程序

set - OpenEdge 10.2A - INPUT THROUGH 设置在 Windows 10 上的 Windows Update 1703 后不起作用

maven - 使用 Gradle 将 zip 文件发布到 Nexus (Maven)

go - 如何检测 GO 中分离文件夹的代码覆盖率?

python - 如何省略使用 python 覆盖库?

c# - Entity Framework 6 : Skip() & Take() do not generate SQL, 相反,结果集在加载到内存后被过滤。还是我做错了什么?

java - 分析 Linux 上的 Java 内存使用情况

ssl - 进度错误 54 - 无法获取本地颁发者证书