#用户体验(UX)

今天给你们讲一个低性能芯片极限技术优化的故事 学了这篇推文,即使你不是做低性能芯片的场景也非常有用,操作系统老师傅倾情分享 当时我们面临的问题是这款国产芯片性能非常低,大概只有2000年奔腾处理器的水平,而且没有GPU和OpenGL的支持,内存带宽也非常低,面临的优化挑战非常大。 而现代软件库的开发效率很高,但是库本身的开销也非常大,面临X86这种CPU、GPU、内存带宽、显存带宽都很大的硬件,这些软件库的开销会被硬件的性能忽略掉,感受不出来。 而当年的国产芯片的性能,可以这样说,真实世界的硬件模拟器,任何代码没有极限优化的地方,它就奇慢无比,让你看到幻灯片的动画 我那时心里并不担心,因为我在2005年的时候,用J2ME做游戏,那个手机芯片的性能更弱,内存只有800KB,那个手机都能流畅的跑游戏,国产芯片肯定没问题。 当然,做极限优化肯定不能像原来做游戏那样从底层造图形库,虽然性能可以做到极致,但是长期来可维护性比较差,因为后来的人不懂原创的图形库细节。 遇到极限挑战的时候不要慌张,沉住气,想办法,一定可以解决,下面是我们的武功秘籍,板凳端好了: 1. 首先国产芯片不支持OpenGL,所以最开始的QML全部得用Qt Widget重写了,在有OpenGL显卡的情况下,带OpenGL的图形库要快很多,但是没有OpenGL的芯片运行OpenGL的代码就会非常吃力,因为Linux有Mesa硬件抽象库,当GPU缺乏OpenGL支持的时候,Mesa会自动用CPU去模拟OpenGL调用,这个会极大的增加CPU的负担,也会让系统整体变的很慢 2. 应用程序编写的时候,要仔细分析函数的依赖,在X86芯片上,可以随意写,不用过多考虑函数依赖,因为太快了,但是在国产芯片就要仔细分析函数的调用依赖,把界面显示的代码挪到最前面,先让用户看到界面,然后再是其他的。那时候先要做UX流程分析,代码除了按照底层逻辑顺序走,还要考虑UX流程,这样加载比较慢的代码,可以根据UX流程,一次逐步加载,比如一个控制中心模块,完全加载需要5秒,通过界面流程控制,点击某些地方的时候再执行代码,而不是模块执行就全部执行,这样每个界面可以控制在300~500ms之间展示 3. 函数循环要注意,尽量不要写那种一直等待的函数,用锁或者其他通知机制来替代,这样可以减少很多无谓的性能消耗 4. 其实很多代码慢不在代码本身,而在于加载某些动态库很慢,这种动态库的加载常规优化方法不行,太Hacking,我们就利用了现代CPU都具备的特性,内存缓存。我们会分析整个系统所需的动态库,也会分析用户从登录到进入各个界面的空闲时间。我们做了一个深度的优化,就是利用一切用户发愣的时间,比如输入登录密码的时候,桌面等的时候,不操作的时候......只要用户光标不动一段时间,我们就见缝插针的把动态库内容读取一次到内存。这样的好处是,原来应用程序加载的时候,先要加载动态库3秒,然后绘制界面50ms,总共3秒多的时间,因为动态库已经被预热到内存中去了,再次加载动态库的时候,就不用从磁盘读取到内存,直接去缓存里面调用,这样时间就从3050ms降低到50ms 5. 用户空间到内核空间,很多图形库的代码都在用户态运行,在X86芯片没问题,但是在低性能芯片上,这些用户态的逻辑功能就会变成非常多的syscall,syscall的调用非常多以后,代码就会内核中反复切换,这个切换的代价是非常大的。只要是CPU级别的优化,一定要防止代码在CPU和GPU之间反复搬运、磁盘和内存之间反复搬运、代码在内核态和用户态之间来回切换。所以,我们先上strace等工具,剖析系统调用频繁的代码,把这些代码直接写成内核模块,把原来上百次syscall的逻辑现在换成一次内核层的API,当系统调用从300次降低到一次以后,整个软件的性能就会层质的飞跃 6. 最后就是重写桌面环境后端,原来是Gnome的一部分代码,全部用golang重写后,删掉很多开源社区兼容各种人的代码,精简逻辑,很多都有70%以上的性能提升 好了,喜欢我创业故事的朋友欢迎点赞转发 今天这篇文章这么硬核,老板们不买台懒猫微服支持一下?你的支持是我持续分享硬核技术文章的动力,感谢老板,祝老板们发大财!