匿名函数gc分析
测试一:使用member function创建action会产生gc,不管该函数是否访问外部变量:
private System.Action memberAct = null;
// gc 112B
private void ActionWithMethod()
{
memberAct = new System.Action(LocalMethod);
}
// gc 112B, if LocalMethod() is static, then no gc
private void ActionWithMethod2()
{
memberAct = LocalMethod;
}
// no gc
private void ActionWithMethod3()
{
System.Action act = memberAct;
}
private void LocalMethod()
{
foreach (var item in lst)
Debug.Log(item);
}
ActionWithMethod和ActionWithMethod2是等效的,gc值如下所示:

IL代码也一摸一样:


所以将一个member function复制给一个action会产生gc,解决的办法就是ActionWithMethod3,也就是用一个actin member缓存起来,然后将缓存的action member复制给新建的action,这样只会产生一次gc:
private static void LocalMethod()
{
}

测试二:使用匿名函数,如果访问了外部变量,也会产生gc;如果不访问外部变量,则只产生一次gc
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TestAnonymousFunctionGC : MonoBehaviour
{
private System.Action actMember = null;
private int iMember = ;
public TestAnonymousFunctionGC()
{
}
private void Update()
{
UnityEngine.Profiling.Profiler.BeginSample("*** AnoymousFunctionWithoutArg ***");
AnoymousFunctionWithoutArg();
UnityEngine.Profiling.Profiler.EndSample();
UnityEngine.Profiling.Profiler.BeginSample("*** AnoymousFunctionWithMemberArg ***");
AnoymousFunctionWithMemberArg();
UnityEngine.Profiling.Profiler.EndSample();
UnityEngine.Profiling.Profiler.BeginSample("*** AnoymousFunctionWithLocalArg1 ***");
AnoymousFunctionWithLocalArg1();
UnityEngine.Profiling.Profiler.EndSample();
UnityEngine.Profiling.Profiler.BeginSample("*** AnoymousFunctionWithLocalArg2 ***");
AnoymousFunctionWithLocalArg2();
UnityEngine.Profiling.Profiler.EndSample();
UnityEngine.Profiling.Profiler.BeginSample("*** AnoymousFunctionWithLocalArg3 ***");
AnoymousFunctionWithLocalArg3();
UnityEngine.Profiling.Profiler.EndSample();
}
// no gc
private void AnoymousFunctionWithoutArg()
{
actMember = () => { };
}
// gc 112B
private void AnoymousFunctionWithMemberArg()
{
actMember = () =>
{
Debug.Log(iMember);
};
}
// gc 129B
private void AnoymousFunctionWithLocalArg1()
{
bool bValue = true;
actMember = () =>
{
Debug.Log(bValue);
};
}
// gc 132B
private void AnoymousFunctionWithLocalArg2()
{
int iValue = ;
actMember = () =>
{
Debug.Log(iValue);
};
}
// gc 136B
private void AnoymousFunctionWithLocalArg3()
{
int iValue = ;
int iValue2 = ;
actMember = () =>
{
Debug.Log(iValue);
Debug.Log(iValue2);
};
}
}

同时还可以发现,匿名函数引用的外部变量的个数会影响gc的值,为什么呢?来分析一波:




可以看匿名函数所访问的外部变量都会在临时类里面创建一个拷贝,这样每个类对象的大小就不一样了。
附上类型定义的完整代码,前因后果一目了然:
public class TestAnonymousFunctionGC : MonoBehaviour
{
// Fields
private Action actMember;
private int iMember; // Methods
public TestAnonymousFunctionGC()
{
this.actMember = null;
this.iMember = ;
base..ctor();
return;
} [CompilerGenerated]
private void <AnoymousFunctionWithMemberArg>b__5_0()
{
Debug.Log((int) this.iMember);
return;
} private void AnoymousFunctionWithLocalArg1()
{
<>c__DisplayClass6_0 class_;
class_ = new <>c__DisplayClass6_0();
class_.bValue = ;
this.actMember = new Action(class_.<AnoymousFunctionWithLocalArg1>b__0);
return;
} private void AnoymousFunctionWithLocalArg2()
{
<>c__DisplayClass7_0 class_;
class_ = new <>c__DisplayClass7_0();
class_.iValue = ;
this.actMember = new Action(class_.<AnoymousFunctionWithLocalArg2>b__0);
return;
} private void AnoymousFunctionWithLocalArg3()
{
<>c__DisplayClass8_0 class_;
class_ = new <>c__DisplayClass8_0();
class_.iValue = ;
class_.iValue2 = ;
this.actMember = new Action(class_.<AnoymousFunctionWithLocalArg3>b__0);
return;
} private void AnoymousFunctionWithMemberArg()
{
this.actMember = new Action(this.<AnoymousFunctionWithMemberArg>b__5_0);
return;
} private void AnoymousFunctionWithoutArg()
{
this.actMember = (<>c.<>9__4_0 != null) ? <>c.<>9__4_0 : (<>c.<>9__4_0 = new Action(this.<AnoymousFunctionWithoutArg>b__4_0));
return;
} private void Update()
{
Profiler.BeginSample("*** AnoymousFunctionWithoutArg ***");
this.AnoymousFunctionWithoutArg();
Profiler.EndSample();
Profiler.BeginSample("*** AnoymousFunctionWithMemberArg ***");
this.AnoymousFunctionWithMemberArg();
Profiler.EndSample();
Profiler.BeginSample("*** AnoymousFunctionWithLocalArg1 ***");
this.AnoymousFunctionWithLocalArg1();
Profiler.EndSample();
Profiler.BeginSample("*** AnoymousFunctionWithLocalArg2 ***");
this.AnoymousFunctionWithLocalArg2();
Profiler.EndSample();
Profiler.BeginSample("*** AnoymousFunctionWithLocalArg3 ***");
this.AnoymousFunctionWithLocalArg3();
Profiler.EndSample();
return;
} // Nested Types
[Serializable, CompilerGenerated]
private sealed class <>c
{
// Fields
public static readonly TestAnonymousFunctionGC.<>c <>;
public static Action <>9__4_0; // Methods
static <>c()
{
<> = new TestAnonymousFunctionGC.<>c();
return;
} public <>c()
{
base..ctor();
return;
} internal void <AnoymousFunctionWithoutArg>b__4_0()
{
return;
}
} [CompilerGenerated]
private sealed class <>c__DisplayClass6_0
{
// Fields
public bool bValue; // Methods
public <>c__DisplayClass6_0()
{
base..ctor();
return;
} internal void <AnoymousFunctionWithLocalArg1>b__0()
{
Debug.Log((bool) this.bValue);
return;
}
} [CompilerGenerated]
private sealed class <>c__DisplayClass7_0
{
// Fields
public int iValue; // Methods
public <>c__DisplayClass7_0()
{
base..ctor();
return;
} internal void <AnoymousFunctionWithLocalArg2>b__0()
{
Debug.Log((int) this.iValue);
return;
}
} [CompilerGenerated]
private sealed class <>c__DisplayClass8_0
{
// Fields
public int iValue;
public int iValue2; // Methods
public <>c__DisplayClass8_0()
{
base..ctor();
return;
} internal void <AnoymousFunctionWithLocalArg3>b__0()
{
Debug.Log((int) this.iValue);
Debug.Log((int) this.iValue2);
return;
}
}
} Collapse Methods
参考:https://blog.uwa4d.com/archives/Anonymous_heapmemory.html
Vector3.Equals函数会有gc:
// Vector3.Equeals有GC 28B
{
UnityEngine.Profiling.Profiler.BeginSample("*** Vector3.Equals ***");
Vector3 dir1 = Vector3.one, dir2 = Vector3.one;
var equals = dir1.Equals(dir2);
UnityEngine.Profiling.Profiler.EndSample();
}

匿名函数gc分析的更多相关文章
- Javascript闭包和C#匿名函数对比分析
C#中引入匿名函数,多少都是受到Javascript的闭包语法和面向函数编程语言的影响.人们发现,在表达式中直接编写函数代码是一种普遍存在的需求,这种语法将比那种必须在某个特定地方定义函数的方式灵活和 ...
- python——内置函数和匿名函数
内置函数 接下来,我们就一起来看看python里的内置函数.截止到python版本3.6.2,现在python一共为我们提供了68个内置函数.它们就是python提供给你直接可以拿来使用的所有函数.这 ...
- Python_匿名函数_47
匿名函数 Eva_J 匿名函数:为了解决那些功能很简单的需求而设计的一句话函数 #这段代码 def calc(n): return n**n print(calc(10)) #换成匿名函数 calc ...
- python----内置函数2与匿名函数
1.迭代器生成器相关 range:创建一个可迭代对象,一般与for混合使用,可设置步长. for i in range(0,10,2): #步长2范围为0-10不包括10 print(i) # 0 2 ...
- python全栈开发之匿名函数和递归函数
python 匿名函数和递归函数 python全栈开发,匿名函数,递归函数 匿名函数 lambda函数也叫匿名函数,即函数没有具体的名称.是为了解决一些功能很简单需求而设计的一句话函数.如下: #这段 ...
- python——内置函数和lambda匿名函数
内置函数 接下来,我们就一起来看看python里的内置函数.截止到python版本3.6.2,现在python一共为我们提供了68个内置函数.它们就是python提供给你直接可以拿来使用的所有函数.这 ...
- Python— 匿名函数
匿名函数 匿名函数:为了解决那些功能很简单的需求而设计的 “一句话函数” #初始代码 def calc(n): return n**n print(calc(10)) #换成匿名函数 calc = ...
- python之路——内置函数和匿名函数
阅读目录 楔子 内置函数 匿名函数 本章小结 楔子 在讲新知识之前,我们先来复习复习函数的基础知识. 问:函数怎么调用? 函数名() 如果你们这么说...那你们就对了!好了记住这个事儿别给忘记了,咱们 ...
- python 内置函数和匿名函数
内置函数 截止到python版本3.6.2,现在python一共为我们提供了68个内置函数. Built-in Functions abs() dict() help() min() ...
随机推荐
- 匪警请拨110——C++
问题描述 匪警请拨110,即使手机欠费也可拨通! 为了保障社会秩序,保护人民群众生命财产安全,警察叔叔需要与罪犯斗智斗勇,因而需要经常性地进行体力训练和智力训练! 某批警察叔叔正在进行智力训练: 1 ...
- 【DWM1000】 code 解密9一 ANCHOR response poll message
根据上面TAG发送的代码,我直接找到如下代码 case RTLS_DEMO_MSG_TAG_POLL: { if(inst->mode == LISTENER) ...
- [CSAcademy]Or Problem
[CSAcademy]Or Problem 题目大意: 一个长度为\(n(n\le2\times10^5)\)的序列\(A(0\le A_i<2^{20})\),将其分为恰好\(m\)个连续段, ...
- ubuntu 配置
这是安装语言包 sudo apt-get install language-pack-touch-zh-hans language-pack-touch-zh-hant 这是安装字体 sudo apt ...
- 如何修改PHP的memory_limit限制
在运行PHP程序,通常会遇到“Fatal Error: Allowed memory size of xx bytes exhausted”(允许内存大小为 xx 字节耗尽)的错误, 这个意味着PHP ...
- redis:set集合类型的操作(无序集合)
1. set集合类型的操作(无序集合) 集合具有无序性(没有顺序).确定性(描述是确定的).唯一性(没有重复的元素) 1.1. sadd key member [member ...] 语法:sadd ...
- java第二周的学习知识3(==与equals)
==与equals()的之间的差别1)对于==,如果作用于基本数据类型的变量,则直接比较其存储的 “值”是否相等:如果作用于引用类型的变量,则比较的是所指向的对象的地址 2)对于equals方法,注意 ...
- Spring-context 实现Hello World
Spring-context 实现Hello World 本文作为Spring入门笔记,用Spring-context实现控制台的hello world Spring简介 Spring是一个开放源代码 ...
- 实验楼-Git实战教程
实验1-git介绍 1.版本控制系统: 1)集中式版本控制系统:版本库是集中存放在中央服务器的,工作时需要先从中央服务器取得最新的版本,然后工作完成后把自己的修订推送给中央服务器.这类系统都有一个单一 ...
- 【小程序】小程序开发自定义组件的步骤>>>>>>>>>小程序开发过程中报错:jsEnginScriptError
报错:jsEnginScriptError VM6342: jsEnginScriptError Component is not found in path "component/spac ...