找回密码
 点一下
查看: 7090|回复: 18

出人意料的结果:触发的动作比条件要快(6月22日补充)

[复制链接]
发表于 2009-6-20 20:13:44 | 显示全部楼层 |阅读模式
6月22日补充

补充了一些测试,观察条件和动作在执行不同代码时的表现。结果发现:当代码做的工作不重(比如空函数或者没有循环,只是很简单的计算等等)的时候,特别是条件和动作都是空函数的情况下,条件比动作快(大概20%),随着代码的增加,这个差距越来越小,最后条件反而比动作慢

因此,把一些细小的判断工作和一些很小的任务放到条件里,能够提高整体的速度(特别是当条件不成立的时候)。

---------------------------------------

许多人都认为,触发的条件要比动作执行快。一开始我并不怀疑这个结论。但是还有人说:条件比动作要快20倍。这就非常令人怀疑了。因为即使条件比动作要快,但如此大的差距,是很难想象的。于是今天做了个试验,原本是想搞清楚触发的条件比动作到底快多少。但结果令人大吃一惊:总体上而言,触发的动作反而比条件略快。单纯执行Jass代码的话,触发的动作明显比条件要快。而且在某些方面(下面会提到),动作的速度平均比条件要快2~3倍。只有在执行CJ函数的时候,二者执行速度基本相等(没有明显的差别)。

测试方法简介

即使是魔兽里面最精确的timer,也不能测出微秒级别的时间差。因此时间测试单纯使用魔兽提供的工具是无能为力的。必须借助于其他东西。这里我借助于JAPI提供的一组StopWatch相关的函数。这些函数内部是使用QueryPerformanceCounter这个API的。这个函数的精度极高,在我电脑上,Performance Counter(性能计数器)每秒递增14318180次,也就是说,它的精确度是6.984e-08秒,也就是69.8纳秒(1纳秒是10的-9次方秒),我们姑且认为,精确度是0.1微秒好了。

测试过程与结果

我做了如下测试:

测试A

条件和动作里都是空循环6000次,然后测试TriggerEvaluate/Execute调用花了多少时间(也就是说,结果时间包含调用这两个函数的时间以及触发执行的时间)
测试A、B、以及C都是测试地图里面Test1触发(稍微改改)。

结果如下:
2009-6-20 下午 12-52-31.png

结论:单纯执行代码(Jass代码),动作比条件快

测试B

条件和动作里执行
[jass]call DestroyTimer(CreateTimer())[/jass]
500次。(一开始和测试A一样是6000次,结果悲剧了,死机了~~)

结果如下:
2009-6-20 下午 01-03-57.png

结论:执行CJ函数的时候,二者没有明显的差别。这是很自然的,CJ函数的实现大部分和虚拟机执行代码无关。

测试C

和测试B几乎一模一样,只不过执行的CJ函数换成了location。
[jass]call RemoveLocation(Location(0.0, 0.0))[/jass]

结果如下:
2009-6-20 下午 01-07-38.png

结论:同测试B

测试D

这个测试和前面3个不大一样,它是测试从执行TriggerEvaluate/Execute开始,到开始执行触发代码的“延迟”时间。(详细代码见附件地图里的Test2触发)
方法是在执行TriggerEvaluate/Execute之前,记下计时器值,然后一进入触发就立即计算时间。

结果如下:
2009-6-20 下午 01-28-43.png

结果是令人惊异的:在这种情况下,动作比条件快了两倍,甚至接近三倍的都有

另一方面,这也澄清了先前大家对这个延迟大小的认识。可以发现,不管是条件还是触发,从调用函数到开始执行代码,这个延迟都是0.00001秒数量级的,而不是先前大家认为的0.0015秒。延迟可能因CPU而异,但数量级不会变。

综上所述,我们得到结论是:总体而言,动作比条件要快


附注


    [li]测试地图里使用了vJass,但是这并不影响结果。假如不信,自己去看war3map.j就清楚了,我就不解释了。 [/li][li]测试地图可以正常打开(NewGen、WEH均可,要保存必须有vJass插件),但是要运行的话,请使用NewGen带的或者自己的JAPI。(用NewGen的时候要注意,关掉war3err,以免影响结果)[/li]

DemoTest.w3x

47 KB, 下载次数: 37

评分

参与人数 1威望 +5 收起 理由
血戮魔动冰 + 5

查看全部评分

阿里山慝少 该用户已被删除
发表于 2009-6-20 20:27:58 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
回复

使用道具 举报

发表于 2009-6-20 21:04:26 | 显示全部楼层
确实很出人意料~~

不过我在想,在我那个研究之三里,用action执行code明显比用condition执行慢且卡,又是为什么呢……

(慢是用挂角的fraps帧数来判断的,卡是计时器)

和我的测试方式是每5000次一个TriggerSleepAction(0)导致的精度有关?(测试规模是200*5000),不过卡也和这么有关么
回复

使用道具 举报

发表于 2009-6-20 21:44:40 | 显示全部楼层
以前有过这种感觉,被楼主证实了哈。
回复

使用道具 举报

发表于 2009-6-21 14:18:53 | 显示全部楼层
不过按照之前的研究,好像action占用的资源比较多?action另外占空间而condition是附在trigger上面的,排泄上也方便一些

期待更全面的研究,如果在0.x秒级,action仍然比condition快的话,那么就很有意义
回复

使用道具 举报

发表于 2009-6-21 15:05:34 | 显示全部楼层
对了,lz能不能补充测试一些需要执行的代码比较多的情况?或许能获得更多的线索
回复

使用道具 举报

发表于 2009-6-21 19:01:25 | 显示全部楼层
实际测试就知道了。。。
Action绝对比Condition慢。。。

因为Action是另外开的线程,申请资源,存储资源的操作远比执行代码消耗大了不知道多少倍。

Condition对应一个Trigger唯一,Action是每次执行都会抛出去新东西。

去测试一下循环malloc(n),显然这个东西会卡,但是malloc也许执行时间很短的说
回复

使用道具 举报

 楼主| 发表于 2009-6-21 20:50:27 | 显示全部楼层
这个测试只研究了很小的一部分内容,还有更多的需要研究
回复

使用道具 举报

发表于 2009-6-21 21:14:52 | 显示全部楼层
回复

使用道具 举报

发表于 2009-6-21 22:40:45 | 显示全部楼层
很支持LZ的研究.虽然我帮不上忙
回复

使用道具 举报

发表于 2009-6-21 22:54:28 | 显示全部楼层
默默在无聊中高潮.
然后也一起研究...
回复

使用道具 举报

发表于 2009-6-22 16:35:27 | 显示全部楼层
支持研究~
期待楼主进一步测试结论
回复

使用道具 举报

发表于 2009-6-22 17:05:23 | 显示全部楼层
我很想知道关于选取单位组时的条件和选取单位组作动作呢


“动作比条件快了两倍,甚至接近三倍的都有”
会不会只是固定要慢那么点时间量,用倍数来看不太好吧
回复

使用道具 举报

发表于 2009-6-22 18:41:40 | 显示全部楼层
如果检查动作代码执行的速度是看不出来的。。

【申请资源】《--这两个
执行代码
获得“执行时间”
执行代码
【释放资源】《--才是大头

也许还有个锁死游戏资源的操作。。这才是导致变卡的原因
回复

使用道具 举报

发表于 2009-6-24 20:15:02 | 显示全部楼层
支持研究,这篇的结果和橙子的单位组的速度研究一样让人出乎意料~
回复

使用道具 举报

发表于 2009-6-27 17:17:06 | 显示全部楼层
我本身不支持触发器动作。。。因为这个东西是无法删除的,而且确实他在锁死资源上不好说
回复

使用道具 举报

发表于 2009-6-29 20:50:24 | 显示全部楼层
支持研究,学习了
回复

使用道具 举报

发表于 2014-3-18 11:21:59 | 显示全部楼层
evaluate与excute和正常触发还是有区别 毕竟evaluate有个返回值问题
回复

使用道具 举报

发表于 2020-7-21 14:08:15 | 显示全部楼层
66666666666666666666666666666666
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 点一下

本版积分规则

Archiver|移动端|小黑屋|地精研究院

GMT+8, 2024-4-24 06:29 , Processed in 0.118559 second(s), 26 queries .

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表