C#笔记 垃圾回收garbage collection

托管堆(managed heap)
托管堆指的是c#创建引用类型变量的内存。会定时使用垃圾回收(Garbage Collect)机制来释放不需要的内存,有必要的时候堆大小是会改变的。回收过程和改变大小会引起变量在内存里位置的变化(所以对于引用类型c#不提供指针。同时也要注意引用类型中的值类型成员的指针使用)。
如果想要利用好这个自动管理机制,要避免对不需要的内存保留引用,否则内存不会被回收。内存也就浪费了。
对象的分配:new 和 Instantiate(Unity常用的一个操作,其实内部也是new)。
结束对象引用:设置为null或引用其它、超出作用域、调用Destory( )。

ToString装箱,给托管带来的负担
装箱就会产生引用对象,引用对象多了就会给托管堆造成负担,应尽量避免。
负面例子:

// 以下用法不好
public class ExampleScript : MonoBehaviour {
    void ConcatExample(int[] intArray) {
        string line = intArray[0].ToString();
        for (i = 1; i < intArray.Length; i++) {
            line += ", " + intArray[i].ToString();
        }
        return line;
    }
}

循环每次调用ToString产生堆上的引用对象然后又结束引用。类似用法应避免,使用System.Text.StringBuilder来代替。
另一个例子:

// 以下用法不好
// 每帧更新分数,也会给托管带来负担。
void Update() {
        string scoreText = "Score: " + score.ToString();
        scoreBoard.text = scoreText;
    }

// 应该这样
// 加个判断,没必要就不更新
void Update() {
        if (score != oldScore) {
            scoreText = "Score: " + score.ToString();
            scoreBoard.text = scoreText;
            oldScore = score;
        }
    }

函数返回一个数组,给托管带来负担
这也是个负面的例子:

// 每次调用都会分配一块内存
void RandomList(int numElements) {
        var result = new float[numElements];
        for (int i = 0; i < numElements; i++) {
            result[i] = Random.value;
        }
        return result;
    }

// 不会产生额外分配
void RandomList(float[] arrayToFill) {
        for (int i = 0; i < arrayToFill.Length; i++) {
            arrayToFill[i] = Random.value;
        }
    }

Garbage Collection的2个策略
这2个策略是Unity官方文档提供的,没必要盲目使用。
1)小heap快速且经常的GC策略。200kb的堆在iphone3G上大概需要5ms,1mb则需要7ms。

if (Time.frameCount % 30 == 0)
{
   System.GC.Collect();
}

2)大heap慢速且不经常的GC策略。避免在需要流畅运行中发生GC动作(如打斗场景中)。以下代码手动扩展了堆大小,从而影响系统策略。

void Start() {
        var tmp = new System.Object[1024];

        // make allocations in smaller blocks to avoid them to be treated in a special way, which is designed for large blocks
        for (int i = 0; i < 1024; i++)
            tmp[i] = new byte[1024];

        // release reference
        tmp = null;
    }

pool
可以借助reuseable object pools来牺牲一些内存换取效率,也就是复用gameobject(应该释放但不释放)。甚至有可能在需要流畅运行的场景中不调用Instantiate和Destroy来避免瞬时卡顿,可提前建立pool里所有的gameobject。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

好热哦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值