`
mryufeng
  • 浏览: 982290 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

cover的原理及其启示

阅读更多
我们先看下cover模块的功能:

The module cover provides a set of functions for coverage analysis of Erlang programs, counting how many times each executable line of code is executed when a program is run.

那它是如何做到的呢?

它是这样实现的: cover一个模块的时候要先编译, 这个过程中, 根据模块的abstract code 里面的行号,在每个有效的语句前面插入一个 ets:update_couter() 语句, 这样编译出来的模块运行的时候,我们就可以收集到每个有效行的运行信息。

我hack了下cover.erl:

yu-fengdemacbook-2:src yufeng$ diff cover.erl cover_orig.erl 
1242,1243c1242
<     {ok, Module, Binary} = compile:forms(Forms, [debug_info]),
<     io:format("abstract code: ~n~p~n", [get_abstract_code(Module, Binary)]),
---
>     {ok, Module, Binary} = compile:forms(Forms, []),

yu-fengdemacbook-2:~ yufeng$ cat float.erl
-module(float).

-export([new/1,update/3]).

new(N) ->
       hipe_bifs:bytearray(N*8,0).

update(Arr,N,Float) ->
       <<A1,A2,A3,A4,A5,A6,A7,A8>> = <<Float/float>>,
       Start=N*8,
       hipe_bifs:bytearray_update(Arr,Start,A1),
       hipe_bifs:bytearray_update(Arr,Start+1,A2),
       hipe_bifs:bytearray_update(Arr,Start+2,A3),
       hipe_bifs:bytearray_update(Arr,Start+3,A4),
       hipe_bifs:bytearray_update(Arr,Start+4,A5),
       hipe_bifs:bytearray_update(Arr,Start+5,A6),
       hipe_bifs:bytearray_update(Arr,Start+6,A7),
       hipe_bifs:bytearray_update(Arr,Start+7,A8).

yu-fengdemacbook-2:~ yufeng$ otp_src_R13B02-1/bin/erl
Erlang R13B02 (erts-5.7.3) [source] [smp:2:2] [rq:2] [async-threads:0] [kernel-poll:false]

Eshell V5.7.3  (abort with ^G)
1> cover:start().
{ok,<0.33.0>}
2> cover:compile(float).
abstract code:
{raw_abstract_v1,
    [{attribute,1,file,{"/Users/yufeng/float.erl",1}},
     {attribute,1,module,float},
     {attribute,3,export,[{new,1},{update,3}]},
     {function,5,new,1,
         [{clause,5,
              [{var,5,'N'}],
              [],
              [{call,0,
                   {remote,0,{atom,0,ets},{atom,0,update_counter}},
                   [{atom,0,cover_internal_data_table},
                    {tuple,0,
                        [{atom,0,bump},
                         {atom,0,float},
                         {atom,0,new},
                         {integer,0,1},
                         {integer,0,1},
                         {integer,0,6}]},
                    {integer,0,1}]},

%% 我们清楚的看到 ets:update_counter()的调用

              {call,6,
                   {remote,6,{atom,6,hipe_bifs},{atom,6,bytearray}},
                   [{op,6,'*',{var,6,'N'},{integer,6,8}},{integer,6,0}]}]}]},
     {function,8,update,3,
         [{clause,8,
              [{var,8,'Arr'},{var,8,'N'},{var,8,'Float'}],
              [],
              [{call,0,
                   {remote,0,{atom,0,ets},{atom,0,update_counter}},
                   [{atom,0,cover_internal_data_table},
                    {tuple,0,
                        [{atom,0,bump},
                         {atom,0,float},
                         {atom,0,update},
                         {integer,0,3},
                         {integer,0,1},
                         {integer,0,9}]},
                    {integer,0,1}]},
               {match,9,
                   {bin,9,
                       [{bin_element,9,{var,9,'A1'},default,default},
                        {bin_element,9,{var,9,'A2'},default,default},
                        {bin_element,9,{var,9,'A3'},default,default},
                        {bin_element,9,{var,9,'A4'},default,default},
                        {bin_element,9,{var,9,'A5'},default,default},
                        {bin_element,9,{var,9,'A6'},default,default},
                        {bin_element,9,{var,9,'A7'},default,default},
                        {bin_element,9,{var,9,'A8'},default,default}]},
                   {bin,9,[{bin_element,9,{var,9,'Float'},default,[float]}]}},
               {call,0,
                   {remote,0,{atom,0,ets},{atom,0,update_counter}},
                   [{atom,0,cover_internal_data_table},
                    {tuple,0,
                        [{atom,0,bump},
                         {atom,0,float},
                         {atom,0,update},
                         {integer,0,3},
                         {integer,0,1},
                         {integer,0,10}]},
                    {integer,0,1}]},
               {match,10,
                   {var,10,'Start'},
                   {op,10,'*',{var,10,'N'},{integer,10,8}}},
               {call,0,
                   {remote,0,{atom,0,ets},{atom,0,update_counter}},
                   [{atom,0,cover_internal_data_table},
                    {tuple,0,
                        [{atom,0,bump},
                         {atom,0,float},
                         {atom,0,update},
                         {integer,0,3},
                         {integer,0,1},
                         {integer,0,11}]},
                    {integer,0,1}]},
               {call,11,
                   {remote,11,{atom,11,hipe_bifs},{atom,11,bytearray_update}},
                   [{var,11,'Arr'},{var,11,'Start'},{var,11,'A1'}]},
               {call,0,
                   {remote,0,{atom,0,ets},{atom,0,update_counter}},
                   [{atom,0,cover_internal_data_table},
                    {tuple,0,
                        [{atom,0,bump},
                         {atom,0,float},
                         {atom,0,update},
                         {integer,0,3},
                         {integer,0,1},
                         {integer,0,12}]},
                    {integer,0,1}]},
               {call,12,
                   {remote,12,{atom,12,hipe_bifs},{atom,12,bytearray_update}},
                   [{var,12,'Arr'},
                    {op,12,'+',{var,12,'Start'},{integer,12,1}},
                    {var,12,'A2'}]},
               {call,0,
                   {remote,0,{atom,0,ets},{atom,0,update_counter}},
                   [{atom,0,cover_internal_data_table},
                    {tuple,0,
                        [{atom,0,bump},
                         {atom,0,float},
                         {atom,0,update},
                         {integer,0,3},
                         {integer,0,1},
                         {integer,0,13}]},
                    {integer,0,1}]},
               {call,13,
                   {remote,13,{atom,13,hipe_bifs},{atom,13,bytearray_update}},
                   [{var,13,'Arr'},
                    {op,13,'+',{var,13,'Start'},{integer,13,2}},
                    {var,13,'A3'}]},
               {call,0,
                   {remote,0,{atom,0,ets},{atom,0,update_counter}},
                   [{atom,0,cover_internal_data_table},
                    {tuple,0,
                        [{atom,0,bump},
                         {atom,0,float},
                         {atom,0,update},
                         {integer,0,3},
                         {integer,0,1},
                         {integer,0,14}]},
                    {integer,0,1}]},
               {call,14,
                   {remote,14,{atom,14,hipe_bifs},{atom,14,bytearray_update}},
                   [{var,14,'Arr'},
                    {op,14,'+',{var,14,'Start'},{integer,14,3}},
                    {var,14,'A4'}]},
               {call,0,
                   {remote,0,{atom,0,ets},{atom,0,update_counter}},
                   [{atom,0,cover_internal_data_table},
                    {tuple,0,
                        [{atom,0,bump},
                         {atom,0,float},
                         {atom,0,update},
                         {integer,0,3},
                         {integer,0,1},
                         {integer,0,15}]},
                    {integer,0,1}]},
               {call,15,
                   {remote,15,{atom,15,hipe_bifs},{atom,15,bytearray_update}},
                   [{var,15,'Arr'},
                    {op,15,'+',{var,15,'Start'},{integer,15,4}},
                    {var,15,'A5'}]},
               {call,0,
                   {remote,0,{atom,0,ets},{atom,0,update_counter}},
                   [{atom,0,cover_internal_data_table},
                    {tuple,0,
                        [{atom,0,bump},
                         {atom,0,float},
                         {atom,0,update},
                         {integer,0,3},
                         {integer,0,1},
                         {integer,0,16}]},
                    {integer,0,1}]},
               {call,16,
                   {remote,16,{atom,16,hipe_bifs},{atom,16,bytearray_update}},
                   [{var,16,'Arr'},
                    {op,16,'+',{var,16,'Start'},{integer,16,5}},
                    {var,16,'A6'}]},
               {call,0,
                   {remote,0,{atom,0,ets},{atom,0,update_counter}},
                   [{atom,0,cover_internal_data_table},
                    {tuple,0,
                        [{atom,0,bump},
                         {atom,0,float},
                         {atom,0,update},
                         {integer,0,3},
                         {integer,0,1},
                         {integer,0,17}]},
                    {integer,0,1}]},
               {call,17,
                   {remote,17,{atom,17,hipe_bifs},{atom,17,bytearray_update}},
                   [{var,17,'Arr'},
                    {op,17,'+',{var,17,'Start'},{integer,17,6}},
                    {var,17,'A7'}]},
               {call,0,
                   {remote,0,{atom,0,ets},{atom,0,update_counter}},
                   [{atom,0,cover_internal_data_table},
                    {tuple,0,
                        [{atom,0,bump},
                         {atom,0,float},
                         {atom,0,update},
                         {integer,0,3},
                         {integer,0,1},
                         {integer,0,18}]},
                    {integer,0,1}]},
               {call,18,
                   {remote,18,{atom,18,hipe_bifs},{atom,18,bytearray_update}},
                   [{var,18,'Arr'},
                    {op,18,'+',{var,18,'Start'},{integer,18,7}},
                    {var,18,'A8'}]}]}]},
     {eof,19}]}
{ok,float}


这个故事告诉我们对 erlang系统的跟踪除了trace机制以为, 我们还可以用parse transform在编译的时候加入我们想要的代码,达到跟踪, 了解系统的目的。具体的可以参考 compiler模块 parse_transform的文档。


分享到:
评论
2 楼 mryufeng 2009-10-10  
parse_transform 在实现 系统级别的软件很有用。
1 楼 litaocheng 2009-10-10  
恩,高~~
eunit就是通过定义 parse_transform 为每个include eunit.hrl 的module 自动加入了一个 test/0 函数,同时处理各种test function.

相关推荐

    diffblue cover插件

    下面将详细介绍Diffblue Cover的功能、工作原理以及如何在IntelliJ IDEA中使用。 ** Diffblue Cover 插件功能 ** 1. **自动测试代码生成**:Diffblue Cover能够自动生成针对Java源代码的单元测试,大大减少了手动...

    iPhone开发秘籍 Coverflow

    首先,我们要理解Coverflow的基本原理。Coverflow效果是通过UIKit框架中的UIView和UIScrollView组件来实现的。开发者需要对Core Animation有深入的理解,以便创建流畅的动画效果。Core Animation是苹果提供的低级别...

    Python库 | diff_cover-1.0.3.tar.gz

    本文将深入探讨`diff_cover`的原理、安装、使用方法以及其在实际开发中的应用。 `diff_cover`库的出现源于一个普遍的需求:当开发者对代码进行修改后,如何确保新增或修改的代码得到了充分的测试覆盖。传统的代码...

    Cover 信息论基础

    这本书深入浅出地介绍了信息论的基本概念、原理及其应用,旨在将信息论与多学科相结合,比如统计物理学、统计学以及投资组合管理等领域。下面,我们将详细探讨该书中的关键知识点。 首先,信息论的基础是熵...

    iphone coverflow效果演示代码

    - 示例说明文档:可能是一个README文件,解释了如何运行示例代码,以及代码的工作原理。 通过研究和理解这个示例代码,你可以学习到如何在自己的应用中实现类似的Cover Flow效果,提升用户体验。同时,这也是深入...

    Diffblue Cover Community Edition 免费的单测自动生成神奇

    Diffblue Cover Community Edition 是一款备受瞩目的自动化单元测试生成工具,专为开发人员设计,尤其在Java编程领域中被广泛使用。它通过智能算法分析代码结构,自动生成精确且全面的单元测试用例,极大地提高了...

    Diffblue Cover Community Edition 免费的单测自动生成神器

    Diffblue Cover Community Edition 是一款专为开发者设计的免费单元测试自动生成工具,它极大地简化了编写测试用例的过程,尤其适合Java开发环境。这款插件是Diffblue公司提供的社区版本,能够在IntelliJ IDEA(简称...

    CoverFlow.rar

    【标题】"CoverFlow.rar" 是一个压缩包文件,它包含了一个实现iOS风格Coverflow效果的资源或代码库。Coverflow是一种视觉展示技术,让用户能够以3D翻页的效果浏览一系列元素,如图片、视频或者商品,常用于增强用户...

    CoverFlow 例子

    下面将详细介绍CoverFlow的概念、实现原理以及如何利用提供的代码进行集成。 CoverFlow的灵感来源于苹果公司的iTunes软件,它以3D视角展示一系列图像,通常用于展示图片、专辑封面或应用图标。用户可以平滑地滚动...

    flex 超炫组件 coverflow 组件源码

    Coverflow组件的源码是用AS编写的,这意味着我们可以深入了解其内部工作原理,进行自定义修改,以满足特定项目需求。 2. **bin目录**:这个目录通常包含编译后的SWF文件,即最终运行的Flex应用程序或库。在cover...

    android-coverflow

    在Android平台上,"android-coverflow" 是一个实现类似iPhone中Coverflow效果的库。Coverflow是一种视觉效果,它展示了一组元素(通常是图像)以旋转木马或翻页书的形式,用户可以滚动浏览,看起来就像元素在围绕一...

    flex coverflow 效果示例

    Flex Coverflow效果是一种在Web开发中常用于展示图像或内容的动态视觉效果,它模仿了类似于苹果iTunes Cover Flow的界面样式。Coverflow允许用户以3D视角浏览一系列元素,通常是一些图片或者卡片,而这些元素在用户...

    Cover Index

    Cover Index 是 SQL Server 中一种优化查询性能的策略,它的核心思想是通过包含查询所需的所有列,使得数据库系统在处理查询时可以直接从索引中获取所有信息,而无需回表(即不访问主键对应的行数据),从而减少了...

    Android版仿iOS的CoverFlow效果

    在Android开发中,有时我们希望实现一种类似于iOS的CoverFlow效果,这能为用户界面增添独特的视觉体验。CoverFlow是一种动态展示元素的方式,通常用于显示一系列图像或卡片,用户可以平滑地滚动浏览,就像翻阅一本...

    authorware中的cover函数

    在这个标题为"authorware中的cover函数"的讨论中,我们将深入探讨Cover函数在Authorware中的作用以及如何使用。 Cover函数是Authorware中一个非常实用的内置函数,主要用于处理对象的显示和隐藏。在Authorware的...

    IEEE Cover letter

    例如,如果研究揭示了一种新的算法或技术,应强调其创新点及潜在的应用价值。这一步骤旨在吸引编辑的兴趣,提高论文的吸引力。 #### 4. 作者贡献声明 详细说明所有作者在研究中的具体贡献,包括规划、执行实验、...

    wp7上coverflow控件

    在Windows Phone 7 (简称WP7)平台上,Coverflow控件是一种常见的用户界面元素,它模仿了唱片封面或卡片在平面上流动的效果,通常用于展示一系列图像或项目,让用户能够以美观的方式浏览和选择。在WP7应用开发中,...

    52COVER相册系统 v1.2.rar

    多说评论系统关联(独立评论管理)标题(Title)关键词(KeyWords)描述(Description)同时数据库自动调用关联相册分类及照片信息,助于seo 52COVER相册系统前台页面 52COVER相册系统后台管理 后台路径:域名/...

    Insofta Cover Commander 破解版

    软件名称:Insofta Cover Commander 软件版本:v3.1 适用平台:Windows 2000/2003/XP/Vista/Windows7 官方网站:http://www.insofta.com 功能简介:  专业、快速的虚拟包装设计软件。模板很多,定制性强。3.1...

    coverflow图片滚动浏览,倒影效果

    一、Coverflow的基本原理 Coverflow效果主要通过CSS3和JavaScript来实现。CSS3用于创建元素的旋转、倾斜和阴影效果,而JavaScript则负责处理用户交互,如鼠标滚轮、键盘或触摸事件,以及调整元素的位置和动画效果。...

Global site tag (gtag.js) - Google Analytics