Ruby Meta Programming: define_method or class_eval

今天刚巧看到Matt Aimonetti的blog上讨论ruby meta programming的执行效率问题,就跟着做了一下,还是学到了不少东西。大致说一下吧,首先Matt写了一个简单的计算时间的DSL类:

module TimeDSL
def second
self * 1
end
alias_method :seconds, :second

def minute
self * 60
end
alias_method :minutes, :minute

def hour
self * 3600
end
alias_method :hours, :hour

def day
self * 86400
end
alias_method :days, :day

def week
self * 604800
end
alias_method :weeks, :week

def month
self * 2592000
end
alias_method :months, :month

def year
self * 31471200
end
alias_method :years, :year
end
Numeric.send :include, TimeDSL


这个类很简单,就是为Numeric类增加了与时间相关的一些方法,这样就可以使用类似的代码计算时间了,例如:

1.hours + 20.minutes # => 一小时20分钟是多少秒
3.days + 5.hours # => 3天零5小时
2.years + 10.months # => 两年十个月


代码很简单,不过请大家注意Matt使用
Numeric.send :include, TimeDSL
方法为Numeric类增加了TimeDSL这个模块。
然后他又写了一个利用define_method方式实现TimeDSL的类(为了方便说明,我略作了修改)

module BadMetaTimeDSL

{:second => 1,
:minute => 60,
:hour => 3600,
:day => [24,:hours],
:week => [7,:days],
:month => [30,:days],
:year => [364.25, :days]}.each do |meth, amount|
define_method "b_#{meth}" do
amount = amount.is_a?(Array) ? amount[0].send(amount[1]) : amount
self * amount
end
alias_method "b_#{meth}s".intern, "b_#{meth}"
end
end
Numeric.send :include, BadMetaTimeDSL


他发布了这两个类benchmark的测试数据,并得出结论说ruby的meta programming基本上要比正常方式慢3倍左右(我自己的测试数据是2倍左右)
这个结论很快就引来了很多人的的讨论,最后Wycats提出了改进方案

module GoodMetaTimeDSL
SECOND = 1
MINUTE = SECOND * 60
HOUR = MINUTE * 60
DAY = HOUR * 24
WEEK = DAY * 7
MONTH = DAY * 30
YEAR = DAY * 364.25

%w[SECOND MINUTE HOUR DAY WEEK MONTH YEAR].each do |const_name|
meth = const_name.downcase
class_eval <<-RUBY
def g_#{meth}
self * #{const_name}
end
alias g_#{meth}s g_#{meth}
RUBY
end
end
Numeric.send :include, GoodMetaTimeDSL

新的类执行效率直逼正常方式定义的类,可以说基本上没有太大的差异了。究其原因define_method需要创建Proc才能执行,而class_eval和ruby自身执行方式没有什么差别,都是直接解释执行。

最后的结论是:如果可能,尽量使用class_eval进行meta programming

不知道怎么把附件的图贴进来,大家看附件吧,也包括源代码。
整个测试都在jruby 1.1.3下通过

可以参考[url]http://railsontherun.com/2008/6/18/about-metaprogramming-speed[/url]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
monitoring_point.h头文件内容如下: #ifndef MONITORING_POINT_H #define MONITORING_POINT_H #endif // MONITORING_POINT_H #include<QString> #include"monitoring_sensor.h" using namespace std; class Monitoring_point { private: QString JCD_Name;//监测点名称 QString JCD_Type;//监测点所检测的数据类型 QString JCD_Number;//监测点编号 public: Monitoring_sensor sensor;//监测点有传感器 void set_JCD_Name(QString n); void set_JCD_Type(QString t); void set_JCD_Number(QString n); QString get_JCD_Name(); QString get_JCD_Type(); QString get_JCD_Number(); }; monitoring_point.cpp源文件内容如下: #include"monitoring_point.h" #include"mainwindow.h" using namespace std; void Monitoring_point::set_JCD_Name(QString n) { JCD_Name = n; } void Monitoring_point::set_JCD_Type(QString t) { JCD_Type = t; } void Monitoring_point::set_JCD_Number(QString n) { JCD_Number = n; } QString Monitoring_point::get_JCD_Name() { return JCD_Name; } QString Monitoring_point::get_JCD_Type() { return JCD_Type; } QString Monitoring_point::get_JCD_Number() { return JCD_Number; } monitoring_sensor.h头文件内容如下: #ifndef MONITORING_SENSOR_H #define MONITORING_SENSOR_H #endif // MONITORING_SENSOR_H #include<QString> using namespace std; class Monitoring_sensor { private: QString CGQ_Number;//传感器编号 QString CGQ_State;//传感器状态 QString CGQ_Manufacturer;//生产商 QString CGQ_Outnumber;//出厂号 public: void set_CGQ_Number(QString n); QString get_CGQ_Number(); void set_CGQ_State(QString s); QString get_CGQ_State(); void set_CGQ_Manufacturer(QString m); QString get_CGQ_Manufacturer(); void set_CGQ_Outnumber(QString o); QString get_CGQ_Outnumber(); }; monitoring_sensor.cpp源文件内容如下: #include "monitoring_sensor.h" #include"mainwindow.h" using namespace std; void Monitoring_sensor::set_CGQ_Number(QString n) { CGQ_Number=n; } QString Monitoring_sensor::get_CGQ_Number() { return CGQ_Number; } void Monitoring_sensor::set_CGQ_State(QString s) { CGQ_State = s; } QString Monitoring_sensor::get_CGQ_State() { return CGQ_State; } void Monitoring_sensor::set_CGQ_Manufacturer(QString m) { CGQ_Manufacturer = m; } QString Monitoring_sensor::get_CGQ_Manufacturer() { return CGQ_Manufacturer; } void Monitoring_sensor::set_CGQ_Outnumber(QString o) { CGQ_Outnumber=o; } QString Monitoring_sensor::get_CGQ_Outnumber() { return CGQ_Outnumber; } 为什么报错E:\qiaoliangjiance\monitoring_sensor.h:8: error: redefinition of 'class Monitoring_sensor' class Monitoring_sensor ^~~~~~~~~~~~~~~~~
最新发布
07-10
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值