在C ++中优化空间而不是速度
当你说“优化”时,人们往往会认为“速度”。 但是嵌入式系统的速度并不是那么重要,但内存是一个主要的限制因素呢? 什么是一些指导方针,技巧和技巧可用于削减ROM和RAM中的额外千字节? 一个“配置文件”代码如何查看内存膨胀的位置?
PS有人可能会争辩说,在嵌入式系统中过早地优化空间并不是那么糟糕,因为你为数据存储和蠕变提供了更多的空间。 它还允许您降低硬件生产成本,因为您的代码可以在较小的ROM / RAM上运行。
PPS也欢迎参考文章和书籍!
PPPS这些问题密切相关:404615,1561629
我的经验来自一个非常有限的嵌入式内存环境:
你可以做许多事情来减少你的记忆足迹,我相信人们已经写了关于这个主题的书籍,但其中一些主要的是:
编译器选项以减少代码大小(包括-Os和包装/对齐选项)
链接器选项去除死代码
如果您从闪存(或ROM)加载到RAM以执行(而不是从闪存执行),请使用压缩的闪存映像,并使用引导加载程序对其进行解压缩。
使用静态分配:堆是分配有限内存的低效方式,并且如果它受限制可能由于碎片而失败。
用于查找堆栈高水印的工具(通常它们用堆栈填充堆栈,执行程序,然后查看模式的剩余位置),因此您可以优化地设置堆栈大小
当然,优化用于内存占用的算法(通常以速度为代价)
一些明显的
const
声明常量数据表。 这将避免数据从闪存复制到RAM 将知识折叠成数据
Unix哲学的一个规则可以帮助使代码更紧凑:
表示规则:将知识叠加到数据中,因此程序逻辑可能很愚蠢和强大。
我无法计算我已经看到了多少次精心设计的分支逻辑,跨越多个页面,这些页面可能已经被折叠成规则,常量和函数指针的紧凑表格。 状态机通常可以用这种方式表示(状态模式)。 命令模式也适用。 这完全是关于编程的声明式和命令式编程。
日志代码+二进制数据,而不是文本
而不是记录纯文本,记录事件代码和二进制数据。 然后使用“短语手册”重新构建事件消息。 短语集中的消息甚至可以包含printf样式的格式说明符,以便事件数据值在文本中整齐地显示。
尽量减少线程数量
每个线程都需要它自己的内存块以用于堆栈和TSS。 在不需要抢占的地方,考虑在同一线程内合作执行任务(协作式多任务)。
使用内存池而不是囤积
为了避免堆碎片,我经常看到单独的模块为自己的用途囤积大量的静态内存缓冲区,即使偶尔需要内存。 可以使用内存池,以便内存仅在“按需”使用。 但是,这种方法可能需要仔细分析和检测,以确保池在运行时不会耗尽。
仅在初始化时动态分配
在只有一个应用程序无限期运行的嵌入式系统中,您可以以合理的方式使用不会导致碎片的动态分配:只需在各种初始化例程中动态分配一次,并且永不释放内存。 reserve()
你的容器到正确的容量,不要让它们自动增长。 如果您需要频繁分配/释放数据缓冲区(例如,用于通信数据包),请使用内存池。 我曾经甚至扩展了C / C ++运行时,以便在初始化序列后尝试动态分配内存时它会中止我的程序。
上一篇: Optimizing for space instead of speed in C++
下一篇: Is it premature optimization to develop on slow machines?