快资讯:【速度测试】SketchUp图元类型判断的速度对比
上一篇文章[SU-2022-04]中提到,使用 typename来判断图元类型,由于涉及字符串的对比,执行效率较低,因而推荐使用grep或者is_a?方法。但是这两种判断方式在迭代图元的过程中的执行效率究竟差多少?为了解答这个问题,本文做一个实验测试一下。
一、图元类型判断的方法
【资料图】
判断一个图元是否属于某种类型有以下几种方法,第一种方法直接判断图元类型,这一种方法可用的语法很多,至少包括以下几种:
#令 ent 为一个图元putsent.typename=="Edge"puts ent.is_a?(Sketchup::Edge)puts ent.instance_of?(Sketchup::Edge)puts Sketchup::Edge === ent
以上均能够判断图元ent 是否是一个边线类图元,区别在于:第一种基于字符串的比较,等号左边可能是"Edge"、"Face"或者"Group"等字符串,通过和右边的"Edge" 对比确认ent 是否为边线类。余下三种都是基于ruby类的判断,通过比较ent是否属于 Sketchup::Edge 类来判断。其中第三种方法中的instance_of?需要图元必须是 Sketchup::Edge 也不能为其子类,但是对于 SketchUp 模型的情况而言,不存在上述情况,所以可以认为是等价的。
第二种方法是判断其是否拥有某些成员,例如边线类都拥有长度length成员,平面类都拥有面积area成员:
#令ent为一个图元putsent.respond_to?(:length)putsent.methods.include?(:length)
这种方法的好处在于其清晰的目标导向性,判断图元类型的很大一部分原因是为了避免类型不符的图元抛出 NoMethodError 错误,从而导致脚本意外终止。并且,对于某些特殊的情况可以很方便的表达,例如需要同时选出组件、群组和图片这三类图元时,由于这三种图元对象都包括:definition 方法,所以可以直接用以下方式判断:
putsent.respond_to?(:definition)
第三种方法是直接不进行判断,将可能的抛出的异常用begin rescueend的方法来处理,这不是一个负责任的做法,但是某些时候可以用来跳过一些比较麻烦的筛选问题。
begin# 不需要判断图元类型直接执行rescue# 如果报错了不会抛出异常而是执行这里的代码,这里也可以是空的end
二、测试不同方法的运行速度
这三种方法具体又可以分为不同的实现路径,以下选取几种方法,分别测试以下几段代码,测试其执行速度:
#对比class的方法GC.starttz=Time.now().to_fedge_longer_than_10_meters=0Sketchup.active_model.entities.to_a.each{|ent|if ent.class==Sketchup::Edge thenif ent.length>10.m thenedge_longer_than_10_meters+=1endend}puts "长度大于10米的边线图元数量:#{edge_longer_than_10_meters}"puts "总耗时:#{Time.now().to_f-tz}秒"#使用is_a?的方法GC.starttz=Time.now().to_fedge_longer_than_10_meters=0Sketchup.active_model.entities.to_a.each{|ent|if ent.is_a?(Sketchup::Edge) thenif ent.length>10.m thenedge_longer_than_10_meters+=1endend}puts "长度大于10米的边线图元数量:#{edge_longer_than_10_meters}"puts "总耗时:#{Time.now().to_f-tz}秒"#对比typename的方法GC.starttz=Time.now().to_fedge_longer_than_10_meters=0Sketchup.active_model.entities.to_a.each{|ent|if ent.typename=="Edge" thenif ent.length>10.m thenedge_longer_than_10_meters+=1endend}puts "长度大于10米的边线图元数量:#{edge_longer_than_10_meters}"puts "总耗时:#{Time.now().to_f-tz}秒"#使用grep的方法GC.starttz=Time.now().to_fedge_longer_than_10_meters=0Sketchup.active_model.entities.grep(Sketchup::Edge).each{|ent|if ent.length>10.m thenedge_longer_than_10_meters+=1end}puts "长度大于10米的边线图元数量:#{edge_longer_than_10_meters}"puts "总耗时:#{Time.now().to_f-tz}秒"#判断成员的方法GC.starttz=Time.now().to_fedge_longer_than_10_meters=0Sketchup.active_model.entities.to_a.each{|ent|if ent.respond_to?(:length) thenif ent.length>10.m thenedge_longer_than_10_meters+=1endend}puts "长度大于10米的边线图元数量:#{edge_longer_than_10_meters}"puts "总耗时:#{Time.now().to_f-tz}秒"#不使用to_a的is_a?方法GC.starttz=Time.now().to_fedge_longer_than_10_meters=0Sketchup.active_model.entities.each{|ent|if ent.is_a?(Sketchup::Edge) thenif ent.length>10.m thenedge_longer_than_10_meters+=1endend}puts "长度大于10米的边线图元数量:#{edge_longer_than_10_meters}"puts "总耗时:#{Time.now().to_f-tz}秒"#处理异常的方法GC.starttz=Time.now().to_fedge_longer_than_10_meters=0Sketchup.active_model.entities.to_a.each{|ent|beginif ent.length>10.m thenedge_longer_than_10_meters+=1endrescueend}puts "长度大于10米的边线图元数量:#{edge_longer_than_10_meters}"puts "总耗时:#{Time.now().to_f-tz}秒"#使用while的方法GC.starttz=Time.now().to_fedge_longer_than_10_meters=0index=0len=Sketchup.active_model.entities.lengthwhile index10.m thenedge_longer_than_10_meters+=1endendindex+=1endputs "长度大于10米的边线图元数量:#{edge_longer_than_10_meters}"puts "总耗时:#{Time.now().to_f-tz}秒"
三、测试结果
通过运行上一部分中的代码,测试结果如下图所示:
从测试结果来看,有以下几条结论:
(1)使用ruby对象类型的判断方法要比字符串判断方法节约30%左右的时间。
(2)在不涉及修改图元的情况下使用 while 语句非但没有提速,反而速度较慢,因次没有必要用它替代迭代器。
(3)判断是否拥有成员的respond_to?方法速度也与判断类型相近,因此对于上文所说的群组组件的判断,用此方法更为理想。
(4)有隔离影响功能的to_a方法会额外增加一小部分执行时间,因此使用grep方法既可以获得较高的执行效率,同时还可以做到隔离影响,是相对而言最合理的方法。
(5)处理异常的rescue 语句,速度低于字符串的比较,这是毫不意外的,实现具体功能时还是应该尽量避免本身可控的不确定性。
(完)
本文编号:SU-2022-05
相关阅读
-
世界热推荐:今晚7:00直播丨下一个突破...
今晚19:00,Cocos视频号直播马上点击【预约】啦↓↓↓在运营了三年... -
NFT周刊|Magic Eden宣布支持Polygon网...
Block-986在NFT这样的市场,每周都会有相当多项目起起伏伏。在过去... -
环球今亮点!头条观察 | DeFi的兴衰与...
在比特币得到机构关注之后,许多财务专家预测世界将因为加密货币的... -
重新审视合作,体育Crypto的可靠关系才能双赢
Block-987即使在体育Crypto领域,人们的目光仍然集中在FTX上。随着... -
简讯:前端单元测试,更进一步
前端测试@2022如果从2014年Jest的第一个版本发布开始计算,前端开发... -
焦点热讯:刘强东这波操作秀
近日,刘强东发布京东全员信,信中提到:自2023年1月1日起,逐步为...