找回密码
 立即注册
查看: 360|回复: 0

lua中访问userdata中对象和访问table中对象的效率比较

[复制链接]
发表于 2021-8-19 08:03 | 显示全部楼层 |阅读模式
做cocos2d-x开发的人可能有不少人在实现类时会利用cocos2d-x自己给出的类的实现,也即在luaBinding目录下extern.lua的文件中给出的实现:
  1. --Create an class.
  2. function class(classname, super)
  3.     local superType = type(super)
  4.     local cls
  5.     if superType ~= "function" and superType ~= "table" then
  6.         superType = nil
  7.         super = nil
  8.     end
  9.     if superType == "function" or (super and super.__ctype == 1) then
  10.         -- inherited from native C++ Object
  11.         cls = {}
  12.         if superType == "table" then
  13.             -- copy fields from super
  14.             for k,v in pairs(super) do cls[k] = v end
  15.             cls.__create = super.__create
  16.             cls.super    = super
  17.         else
  18.             cls.__create = super
  19.         end
  20.         cls.ctor    = function() end
  21.         cls.__cname = classname
  22.         cls.__ctype = 1
  23.         function cls.new(...)
  24.             local instance = cls.__create(...)
  25.             -- copy fields from class to native object
  26.             for k,v in pairs(cls) do instance[k] = v end
  27.             instance.class = cls
  28.             instance:ctor(...)
  29.             return instance
  30.         end
  31.     else
  32.         -- inherited from Lua Object
  33.         if super then
  34.             cls = clone(super)
  35.             cls.super = super
  36.         else
  37.             cls = {ctor = function() end}
  38.         end
  39.         cls.__cname = classname
  40.         cls.__ctype = 2 -- lua
  41.         cls.__index = cls
  42.         function cls.new(...)
  43.             local instance = setmetatable({}, cls)
  44.             instance.class = cls
  45.             instance:ctor(...)
  46.             return instance
  47.         end
  48.     end
  49.     return cls
  50. end
复制代码
这里是支持lua中类继承自cocos2d-x的类的,这样的继承机制下,实例化出来的对象,其类型是一个userdata,那么类中的所有对象(属性或方法)其实都是被拷贝在了obj这个userdata内,之后的访问也都是在userdata中找。  上面这样说是因为这里的做法:
  1.         function cls.new(...)
  2.             --instance是一个userdata
  3.             local instance = cls.__create(...)
  4.             -- copy fields from class to native object
  5.             for k,v in pairs(cls) do instance[k] = v end
  6.             instance.class = cls
  7.             instance:ctor(...)
  8.             return instance
  9.         end
复制代码
那么这样作的话我们就得考虑一个问题,lua(或tolua++)的实现里,对userdata中的对象访问的速度够快吗?我们来做一个测试: ----------------------
测试代码1(o为table,val为table中变量):
  1.         local o = {}
  2.         o.val = 1
  3.         local t1 = os.clock()
  4.         for i = 1, 10000000, 1 do
  5.                 o.val = o.val + 1
  6.         end
  7.         local t2 = os.clock()
  8.         print(t2 - t1)
复制代码
多次运行,打印纸稳定在0.01数量级。


----------------------
测试代码2(o为userdata,val为userdata中变量):
  1.         local o = cc.Node:create()
  2.         o.val = 1
  3.         local t1 = os.clock()
  4.         for i = 1, 10000000, 1 do
  5.                 o.val = o.val + 1
  6.         end
  7.         local t2 = os.clock()
  8.         print(t2 - t1)
复制代码
多次运行,打印纸稳定在4.0数量级。  



******************
测试发现,前者的效率为后者的近400倍,也即在table中访问对象比在userdata中访问,速度有近400倍的提升。

因此,使用cocos2d-x给出的类的实现,虽然能做到支持继承cocos2d-x中的c++对象,但该机制的性能是值得注意的。
原因分析(这里只是猜测,因为暂未看lua及tolua++的实现):

1.tolua++在访问userdata中属性或方法时,会不会是遍历了一边userdata中所有东西然后一个一个比较,得出最后访问的数据的如果是这样,就可以勉强解释这个现象,因为table中访问某对象,是通过对key值的做哈希来访问的,其速度自然比遍历要快多了。
2.在userdata上增加变量,是由lua层通知c层最终在c层增加的,然后每次访问都要经历一个lua层到c层的过程现在是直接在lua层增加,所以访问时不再需要lua层到c层的交互。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-11-24 11:26 , Processed in 0.092275 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

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