目录

Xlua性能测试

xlua 性能分析测试

lua中os.clock():
解释:返回一个程序使用CPU时间的一个近似值。
引用:https://www.jianshu.com/p/46e0d70746cc

xlua 常用说明

详细说明:https://github.com/Tencent/xLua/blob/master/Assets/XLua/Doc/configure.md

XLua.LuaCallCSharp

一个C#类型加了这个配置,xLua会生成这个类型的适配代码(包括构造该类型实例,访问其成员属性、方法,静态属性、方法),否则将会尝试用性能较低的反射方式来访问。

一个类型的扩展方法(Extension Methods)加了这配置,也会生成适配代码并追加到被扩展类型的成员方法上。

xLua只会生成加了该配置的类型,不会自动生成其父类的适配代码,当访问子类对象的父类方法,如果该父类加了LuaCallCSharp配置,则执行父类的适配代码,否则会尝试用反射来访问。

反射访问除了性能不佳之外,在il2cpp下还有可能因为代码剪裁而导致无法访问,后者可以通过下面介绍的ReflectionUse标签来避免。

XLua.CSharpCallLua

如果希望把一个lua函数适配到一个C# delegate(一类是C#侧各种回调:UI事件,delegate参数,比如List:ForEach;另外一类场景是通过LuaTable的Get函数指明一个lua函数绑定到一个delegate)。或者把一个lua table适配到一个C# interface,该delegate或者interface需要加上该配置。

XLua.DoNotGen

指明一个类里头的部分函数、字段、属性不生成代码,通过反射访问。

只能标准Dictionary<Type, List>的field或者property。key指明的是生效的类,value是一个列表,配置的是不生成代码的函数、字段、属性的名字。

和ReflectionUse的区别是:1、ReflectionUse指明的是整个类;2、当第一次访问一个函数(字段、属性)时,ReflectionUse会把整个类都wrap,而DoNotGen只wrap该函数(字段、属性),换句话DoNotGen更lazy一些;

和BlackList的区别是:1、BlackList配了就不能用;2、BlackList能指明某重载函数,DoNotGen不能;

../../imgs/2022-02-15-19-00-37.png

xlua 性能测试

环境 win 平台的 unity2020.3.21f1c1,xlua版本2.2.16

性能测试结果(1+2加法运算执行1亿次的耗时,毫秒单位)

案例 结果
CSharp 内调用 20.5071
lua 内调用 3000.00
Hotfix 模式Hotfix Inject In Editor 170.0945
xlua.hotfix()修复后调用 9175.6273
LuaCallCSharp 标记前调用 184000.00
LuaCallCSharp 标记后调用 6000.00

Hotfix 模式下执行Hotfix Inject In Editor后 执行lua的xlua.hotfix()修复后调用

性能测试代码

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
using UnityEngine;
using XLua;
namespace LuaAnalysis
{
#region Calc Class
    

    
    /// <summary>
    /// 纯CSharp调用
    /// LuaCallCSharp 标记前调用
    /// </summary>
    public class Calc1
    {
        public static int Add(int a,int b)
        {
            return a+b;
        }
    }

    /// <summary>
    /// LuaCallCSharp 标记后调用
    /// </summary>
    [LuaCallCSharp]
    public class Calc
    {
        public static int Add(int a,int b)
        {
            return a+b;
        }
    }

    [Hotfix]
    public class HotfixCalc
    {
        public int Add(int a, int b)
        {
            return a - b;
        }
        /// <summary>
        /// Hotfix 标记后
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns></returns>
        public static int Add1(int a, int b)
        {
            return a - b;
        }        
        /// <summary>
        /// Hotfix 标记后,注入后且xlua.hotfix修复后执行lua代码
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns></returns>        
        public static int Add2(int a, int b)
        {
            return a - b;
        }                         
    }

    public class NoHotfixCalc
    {
        public int Add(int a, int b)
        {
            return a + b;
        }
    }
#endregion


    public class Analysis : MonoBehaviour
    {
    static string lua=@"
            
            local Add= function(a, b)
                return a + b
            end
            local count=100 * 1000 * 1000
            
            starttime = os.time()
            for i=1,count,1 do
                Add(2,1)
            end
            endtime=os.time()
            print(string.format('Lua内调用   : %.2f', (endtime - starttime)*1000))

            starttime = os.time()
            for i=1,count,1 do
                CS.LuaAnalysis.Calc1.Add(2,1)
            end
            endtime=os.time()
            print(string.format('LuaCallCSharp 标记前调用(反射访问) : %.2f', (endtime - starttime)*1000))            

            starttime = os.time()
            for i=1,count,1 do
                CS.LuaAnalysis.Calc.Add(2,1)
            end
            endtime=os.time()
            print(string.format('LuaCallCSharp 标记后调用(绑定访问) : %.2f', (endtime - starttime)*1000))                        

            xlua.hotfix(CS.LuaAnalysis.HotfixCalc, 'Add2', function(a,b)
                return a+b
            end)     
            
        ";

        // Start is called before the first frame update
        void Start()
        {
            LuaEnv luaenv = new LuaEnv();   
            HotfixCalc calc = new HotfixCalc();
            int CALL_TIME = 100 * 1000 * 1000;
            System.DateTime start;
            double d=0;

            luaenv.DoString(lua); 

            start = System.DateTime.Now;
            for (int i = 0; i < CALL_TIME; i++)
            {
                Calc1.Add(2, 1);
            }
            d = (System.DateTime.Now - start).TotalMilliseconds;
            Debug.Log("CSharp 内调用(静态方法):" + d);  

            start= System.DateTime.Now;
            for (int i = 0; i < CALL_TIME; i++)
            {
                calc.Add(2, 1);
            }
            d = (System.DateTime.Now - start).TotalMilliseconds;
            Debug.Log("Hotfix 标记后(成员方法):" + d); 

            start= System.DateTime.Now;
            for (int i = 0; i < CALL_TIME; i++)
            {
                HotfixCalc.Add1(2, 1);
            }
            d = (System.DateTime.Now - start).TotalMilliseconds;
            Debug.Log("Hotfix 标记后(静态方法):" + d); 

                       

            start= System.DateTime.Now;
            for (int i = 0; i < CALL_TIME; i++)
            {
                HotfixCalc.Add2(2, 1);
            }
            d = (System.DateTime.Now - start).TotalMilliseconds;
            Debug.Log("Hotfix 标记后(静态方法) lua.hotfix修复后:" + d);    

            // start= System.DateTime.Now;
            // for (int i = 0; i < CALL_TIME; i++)
            // {
            //     HotfixCalc.Add3(2, 1);
            // }
            // d = (System.DateTime.Now - start).TotalMilliseconds;
            // Debug.Log("Hotfix 标记后(静态方法,CSharpCallLua) lua.hotfix修复后:" + d);                         


                
            
             
            luaenv.Dispose();
        }

    }
}

打印结果

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
LUA: Lua内调用   : 3000.00

LUA: LuaCallCSharp 标记前调用(反射访问) : 184000.00

LUA: LuaCallCSharp 标记后调用(绑定访问) : 6000.00

CSharp 内调用(静态方法):20.5071

Hotfix 标记后(成员方法):170.0945

Hotfix 标记后(静态方法):171.2534

Hotfix 标记后(静态方法) lua.hotfix修复后:9175.6273