为什么你写的代码占用内存这么大?
你做的模块,测试反馈说,进去就卡顿,按钮点击半天才反应。这是为什么呢?
要想知道这个问题的答案,首先需要搞懂怎样估算对象和结构体的大小。
一、如何估算结构体的大小
结构是值类型,它的结构体的实例是存放在栈中或者堆中。
结构体在内存中所占的大小,就是其字段所占的大小,但是,它的大小并不是所有字段大小相加,而是存在一个对齐的规则,在默认的对齐规则中,基本类型字段是按照自身大小对齐的,如byte是按1字节对齐。
struct A{ byte a1;}
如上面这个结构体的大小就是1字节,如果是下面这个:
struct A{byte a1;int a2;}
这个结构体所占内存大小是8字节,因为int是4字节对齐的,所以只能从第四个字节开始。
如果再添加一个字段:
struct A{byte a1;int a2;byte a3;}
这个结构体大小是12,由于struct本身也要是对齐的,所以它的对齐规则是按照其中元素最大的对齐规则决定的。也就是说上面这个结构体要按照4字节对齐,不足4字节要补齐,所以是12个字节大小。
如果想要优化它的大小,可以调整顺序如下:
struct A{byte a1;byte a3;int a2;}
这个时候这个结构体所占的大小就是8字节了。
二、如何估算类的大小
类是引用类型,它的对象实例存放在堆中,对象实例一定是会占用堆内存的,而在栈中,保存的是实例的引用。对象在堆中分成3个区域,vtable、monitor和字段。
其中vtable是类的共有数据,包含静态变量和方法表,这个应该就是类本身所占用的大小和具体的对象无关。monitor是线程同步用的,这2个指针分别占用一个inptr.Size大小,字段是从第9个字节或17个字节开始的,字段的对齐规则和结构体的对齐规则相同,区别是Mono中对象的实例会把引用类型的引用放在最前面。一个对象实例的大小就是 inptr.Size *2+字段的大小。
通过调整字段的顺序,也可以优化对象的大小。
还可以通过StructLayoutAttribute自定义类和结构体的对齐方式。
public struct A {byte a1;int a2;byte a3; }
上面这个结构体强制按照1字节对齐,所以他的大小是6字节,但这样做可能会降低性能。
所以具体情况还是要具体分析,懂得了如何估算结构体和类的大小,就更容易知道该如何使用它们了。
我们的目标就是让测试下岗,因为没有BUG他就没工作了
要编写精简高效的代码是个大调站 代码写的大是因为定义的全局变量比较多 一般得看你程序习惯的,要是全局变量多也会导致代码内存占用的大 可以习惯性的使用结构体,这样会好很多 其实都是这样,有很多时候会定义一个buf,这个buf如果是全局变量,那占得空间可太大了 楼主讲的通透,其实就是善用结构体和联合体 我一般程序都是这样,能用局部变量就不用全局变量,能用结构体就用结构体 编程的好习惯就是要这么养成的,不能因为现在的MCU资源很多,就随意浪费,哈哈 还就就是建议全局变量少用,也会减少很多的空间的 讲的不错,属实是结构体是个降低存储占用的好方法,而且还可以方便修改 有很多工程师喜欢用结构体就是因为这个内存占用问题 如果代码的逻辑非常复杂,包含了大量的条件语句、循环语句和函数调用等,那么生成的机器码就会非常庞大,从而导致代码占用内存过大。 使用过多的库函数也会占用较多的内存空间。 如果采用了低效的算法或者没有进行优化,就容易导致代码占用内存过大。 如果定义了过多的全局变量或者静态变量,就会占用大量的内存空间 如果编译选项未设置正确,编译器可能会生成一些冗余的代码,从而增加程序的大小。 在需要的情况下启用硬件加速功能、DMA传输模式等,以最大限度地减小代码空间的占用。 优化算法和实现方式,避免使用过于复杂或低效的算法。 可以考虑将一些重复代码提取出来,避免过多的宏定义。