热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

嵌入式Linux系统性能提升的关键切入点与优化策略

在嵌入式Linux系统中,性能低下通常由CPU、内存和I/O三个关键因素引起。为了有效提升系统性能,首先需要识别并定位性能瓶颈。通过综合分析这些瓶颈,可以采取针对性的优化措施,如调整内核参数、优化算法和改进数据结构等,从而显著提高系统的整体性能。

   系统软件性能低下的问题,主要与三种因数有关:CPU、内存、IO。
   如何优化系统的性能?
   第一步,找出系统性能的瓶颈。
(1)程序的运算量很大,CPU过于繁忙,CPU是瓶颈。
    可以通过top命令观察CPU的利用率情况。
(2)过多或过于频繁的读写文件、内存等I/O操作,CPU更多的是处于等待,(存储设备、网络设备、异步IO)等I/O操作是性能瓶颈。
(3)内存不够。物理内存不够时会使用交换内存, 使用交换内存会带来磁盘IO和CPU的开销增加.交换空间是专门用于临时存储内存的一块磁盘空间,通常在页面调度和交换进程数据时使用.调页算法是将内存中最近不常使用的页面换到磁盘上,把常使用的页面(活动页面)保留在内存中供进程使用。当程序运行需要的内存大于物理内存时,linux系统采用了调页机制,即系统copy一些内存中的页面到磁盘上,腾出来空间供进程使用。
大多数系统可以忍受偶尔的调页,但是频繁的调页会使系统性能急剧下降。

  (4) 带宽。如网络带宽、系统总线带宽等

(5)文件系统性能(大文件优化、小文件优化、写优化、读优化、网络文件系统)。

  (6) 多线程性能

 

   一些经验:

1.   小文件读写的性能瓶颈是磁盘的寻址(随机读写性能更差),评估的标准是tps

2.   大文件读写的性能瓶颈是带宽,评估的标准是持续的读写速度

3.   Linux可以利用空闲内存作文件系统访问的cache,因此系统内存越大存储系统的性能也越好

 

   第二步,着手进行优化

1.堆内存和数据段内存的优化:

   malloc一般会实现一个内存堆来管理这些内存,malloc分配的内存都会以若干chunk的方式放到内存堆中。每次用户调用malloc动态分配内存的时候,malloc会先到内存堆里进行查找,如果内存堆里没有合适的空闲chunk,再利用brk/malloc系统调用分配一大块内存,然后把新分配的大块内存放到内存堆中,并生成一块合适的chunk块返回给用户。
   


当用户用free释放chunk的时候,可能并不立即使用系统调用释放内存,而是将释放的chunk作为空闲chunk加入内存堆中,和其他的空闲chunk合并,便于下次分配的时候再次使用。
   
   一般说来,释放的chunk如果标记为mmap申请的,则使用munmap释放。如果是brk申请的,进一步判断堆顶之下的空闲chunk是否大于128KB,如果是,则使用brk()释放。如果小于128KB,仍由内存堆维护。这样对brk()的使用就会有个问题,当brk()释放的内存块在堆顶之下,且内存块到堆顶之间还有未释放的内存。那么这块内存的释放将不会成功,从而形成内存空洞。 

glibc管理的内存唯一释放的条件是堆顶存在128k(M_TRIM_THRESHOLD)或以上的空闲区时才会释放.这样就会形成内存空洞。

内存空洞:当存在内存空洞时,它会从空洞中分配,并不会导致内存使用的增加;

内存泄露:当libc收到内存分配请求时,只能占用更多内存。

针对大块内存的申请和释放不会导致内存空洞的形成。

 

堆内存的优化:

(1)glibc管理的内存绝大多数情况下不会释放。
     因此编程时如果是小内存分配要尽快使用,尽快用完,尽快释放(变成空闲chunk),不要停留,否则一直摞着,线性地址后面的就形成了空洞。


(2)如果是想内存总在控制中,可以分配大内存,自行管理释放和分配。不用的时候可以释放地很干净
(3)不要分配很小的内存比如几个字节,因为一次malloc至少分配16个字节,如果每次分配都很小,就太亏了。
所以尽量减少小块内存的申请,避免内存浪费。

(4)降低M_MMAP_THRESHOLD,可以让更多的分配走mmap,避免brk的种种问题,特别是64位机器的情况下。
(5)降低M_TRIM_THRESOLD,让堆顶的空闲内存更容易释放。

   以上(4)(5)都不可避免会增加系统调用的机会,使用中需要慎重。

 

数据段内存的优化:

(1)将只读的全局变量,加上const,从而使其转移到代码段;

(2)去除不必要的全局变量;

(3)减少全局变量的尺寸;

可以通过nm,查找到所有在数据段的符号,从而想办法修改它。

 

动态库的使用:

(1)静态加载:无法按需动态卸载动态库

(2)dlopen:可按需卸载动态库,从而节省了内存,但程序在启动时,需要查找定位代码,从而会降低性能。

 

代码优化的一些经验:

(1)运算处理优化:简化数学表达式、用移位运算代替乘除运算、乘法运算比除运算快、使用增量和减量运算符等;

(2)算法优化:根据发生频率对switch语句进行排列、将大的switch语句简化为嵌套switch语句等、用指针取代数组、使用宏函数取代函数。



推荐阅读
  • 深入解析C语言中的动态规划算法:以背包问题为例
    本文深入探讨了C语言中动态规划算法的应用,以经典的背包问题为例进行详细解析。通过实例分析,展示了如何利用动态规划解决复杂优化问题,并提供了高效的代码实现方法。文章不仅涵盖了算法的基本原理,还讨论了其在实际编程中的应用技巧和优化策略,为读者提供了全面的理解和实践指导。 ... [详细]
  • 本文探讨了利用JavaScript实现集合的对称差集算法的方法。该算法旨在处理多个数组作为输入参数,同时保留每个数组中元素的原始顺序。算法不会移除单个数组内的重复元素,但会删除在不同数组之间出现的重复项。通过这种方式,能够有效地计算出多个数组的对称差集。 ... [详细]
  • AIX编程挑战赛:AIX正方形问题的算法解析与Java代码实现
    在昨晚的阅读中,我注意到了CSDN博主西部阿呆-小草屋发表的一篇文章《AIX程序设计大赛——AIX正方形问题》。该文详细阐述了AIX正方形问题的背景,并提供了一种基于Java语言的解决方案。本文将深入解析这一算法的核心思想,并展示具体的Java代码实现,旨在为参赛者和编程爱好者提供有价值的参考。 ... [详细]
  • 2012年9月12日优酷土豆校园招聘笔试题目解析与备考指南
    2012年9月12日,优酷土豆校园招聘笔试题目解析与备考指南。在选择题部分,有一道题目涉及中国人的血型分布情况,具体为A型30%、B型20%、O型40%、AB型10%。若需确保在随机选取的样本中,至少有一人为B型血的概率不低于90%,则需要选取的最少人数是多少?该问题不仅考察了概率统计的基本知识,还要求考生具备一定的逻辑推理能力。 ... [详细]
  • JavaScript XML操作实用工具类:XmlUtilsJS技巧与应用 ... [详细]
  • 在编程笔试和面试中,全排列算法因其适中的难度而备受青睐,不仅能够考察应聘者的算法基础,还能测试其对递归和回溯的理解。本文将深入解析全排列算法的实现原理,探讨其应用场景,并提供优化建议,帮助读者更好地掌握这一重要算法。 ... [详细]
  • CentOS 7环境下Jenkins的安装与前后端应用部署详解
    CentOS 7环境下Jenkins的安装与前后端应用部署详解 ... [详细]
  • Spring框架的核心组件与架构解析 ... [详细]
  • 本文对常见的字符串哈希函数进行了全面分析,涵盖了BKDRHash、APHash、DJBHash、JSHash、RSHash、SDBMHash、PJWHash和ELFHash等多种算法。这些哈希函数在不同的应用场景中表现出各异的性能特点,通过对比其算法原理、计算效率和碰撞概率,为实际应用提供了有价值的参考。 ... [详细]
  • 总数 | 小规模算法动态规划第3讲:LeetCode 62 不同路径详解 | 从自顶向下到自底向上的动态规划方法分析
    总数 | 小规模算法动态规划第3讲:LeetCode 62 不同路径详解 | 从自顶向下到自底向上的动态规划方法分析 ... [详细]
  • C++入门必备:首个博客知识点汇总
    本文总结了C++初学者需要掌握的关键知识点,特别强调了成员类型的区分。其中,protected成员与private成员在本类中的作用相同,但protected成员允许派生类的成员函数访问,而private成员则不允许。此外,文章还介绍了其他重要的C++基础概念,如类的构造函数、析构函数以及继承机制,为初学者提供了一个全面的学习指南。 ... [详细]
  • 在CodeIgniter框架中集成新库文件的过程中,我遇到了一些困惑。具体来说,在跟随nettuts的认证教程时,对于在Welcome控制器中添加的构造函数代码,特别是关于Session的验证部分,我感到不太理解。这部分内容涉及如何确保Session已经初始化并具备相应的功能,这对于实现用户认证至关重要。为了更好地掌握这一知识点,我计划深入研究CodeIgniter的官方文档,并参考更多相关资源,以确保能够正确地集成和使用新库文件。 ... [详细]
  • 本文详细探讨了Zebra路由软件中的线程机制及其实际应用。通过对Zebra线程模型的深入分析,揭示了其在高效处理网络路由任务中的关键作用。文章还介绍了线程同步与通信机制,以及如何通过优化线程管理提升系统性能。此外,结合具体应用场景,展示了Zebra线程机制在复杂网络环境下的优势和灵活性。 ... [详细]
  • 在 openSUSE Tumbleweed 系统上搭建 51 单片机开发环境并进行编程实践。首先,通过 `sudo zypper in emacs` 命令安装文本编辑器 Emacs。接着,使用 `sudo zypper in sdcc` 安装 SDCC 编译器。最后,利用 `wget` 下载 sdcflash Python 脚本,以便于单片机的烧录和调试。此外,还介绍了如何配置开发环境,确保各组件协同工作,提高开发效率。 ... [详细]
  • 在使用Keil C51创建51单片机项目时,启动代码中包含多个关键元素,这些元素确保了系统的正确初始化和运行。主要包括复位向量、中断向量表、系统时钟配置、寄存器初始化以及主函数入口等。这些组件共同协作,为后续的应用程序执行提供稳定的基础。 ... [详细]
author-avatar
高玉成
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有