我的DeLorean运行Perl

当人们从看到DeLorean在街上行驶的惊讶中回过神来之后,他们的下一个惊喜是它有一个用Perl编写的仪表盘电脑。
521 位读者喜欢这篇文章。

我最近的标志性业余项目是为我的汽车(恰好是DeLorean)制作一个计算机化的仪表盘。但是,每当我向别人展示它时,我通常需要给他们一些时间来惊叹于这辆车,然后他们才会注意到仪表盘上有一个电脑屏幕。当我开始描述软件时,也会遇到类似的问题;当程序员得知仪表数据的实时OpenGL渲染都是用Perl编写的时,他们会立刻纠结于“为什么是Perl???”。因此,任何关于我的项目的讨论通常都从DeLorean的历史或关于Perl与其它更常用的工具的优缺点的讨论开始。

The author and the Delorean

作者和DeLorean合影。照片由Michael Conrad拍摄。

我在2010年启动了这个项目,最初的想法是在仪表盘中集成一台电脑作为个人助理,但它很快变成了一个用软件渲染的东西来替换原厂仪表盘的项目。基于我想要的处理水平(我梦想远大)和我想要的屏幕尺寸,我放弃了人们可能使用的常用高端微控制器,而是选择了一台完整的Linux PC和桌面显示器,以及一个低端微控制器来读取汽车的模拟测量数据。当时我在工作中做OpenGL和C++,所以这是我软件的首选。我可以写多篇文章关于硬件选择,但在这篇文章中我将尽量专注于软件。(你可以在我的网站 nrdvana.net 上找到更多关于这个故事的信息。)

Demo mode

演示模式。照片由Michael Conrad拍摄。

经过几年的努力,很明显C++不适合我的大型个人项目。虽然C++产生了很好的性能和低资源使用率,但我最大的资源短缺是时间和“精神状态”。有时我会离开项目整整一个月,当最终有一天空闲时间来处理它时,我却花了时间试图回忆起我停在哪里。最糟糕的是,我通常无法在一个会话中完成重构我的设计,所以当我几周后回到它时,我没有捕捉到设计更改破坏代码的所有地方。此外,虽然C++在捕获错误方面通常比C更好,但我仍然会遇到偶尔的内存损坏,这可能会耗费数小时的调试时间。编写诊断实时、多线程应用程序所需的日志记录和调试例程也有大量的开发开销。

与此同时,我的日常工作已经转向使用Perl。我不是自己主动寻找Perl的;它只是随着紧急项目一起被推到我面前。然而,在几个月内,我对它的可能性产生了兴趣,现在它是我最喜欢的语言。

进入Perl

在2014年,我毅然决然地用Perl重写了仪表盘软件。在用C++艰难跋涉多年之后,我能够在几个月内获得一个可用的原型(至少是软件),并在2015年转向完成硬件和微控制器。

我的Perl小成功故事主要关于敏捷性。我不是一个流行语爱好者,也不是那种阅读方法论书籍的人,但“敏捷”现在对我来说绝对意味着一些东西。我觉得Perl达到了一个神奇的平衡点,它提供了足够的结构来构建一个正确、高性能的程序,同时又足够简洁和通用,可以轻松地将各种东西连接在一起,甚至提供了足够的语法特性来用简洁但可读的代码表达复杂的操作。(如果您不熟悉Perl的功能,请参阅我的配套文章“从系统程序员的角度看Perl”,其中详细阐述了Perl如何适用于系统工作。)

Dash view

仪表盘视图。照片由Michael Conrad拍摄。

主要的、持续的好处是能够进行临时更改。因为我没有太多时间来规划我的对象的全部需求,所以只需在不知情的对象上添加一些额外的属性,或者根据需要在Java或C++中需要笨拙的反射代码的标准快速排序对象列表,这对生产力是一个很大的提升。如果我决定喜欢这个更改,我会回去用正确声明的属性和接口重写它。我发现我可以在不到一个小时的时间内编写一个新的图形小部件,包括动画。

工具链

对于我的项目的C++版本来说,真正的杀手之一是保持所有二进制级别代码的同步。各种组件(渲染、消息总线、逻辑核心、微控制器固件、控制工具、调试工具)都在共享二进制数据结构,而在makefile中保持依赖关系清晰是一个令人头疼的问题。我个人对automake 系列的工具感到不满,所以每当我需要做一些奇怪的事情(比如使用avr-gcc编译微控制器代码)时,我都会冒着沮丧的风险,绕道进入一个新的宏伟计划,创建一个autotools的替代品(当然,这是一件我不需要浪费 时间的事情)。

在我转向Perl的过程中,我将微控制器转换为显示为Linux串行设备,并将协议更改为短文本符号的字符串。(这些消息实际上比我之前使用的二进制数据包结构更小。)这让我可以使用简单的socat 在/dev/ttyS0上对其进行调试。这也简化了与微控制器通信的守护程序。C++版本是用两个线程编写的,因为我使用的是libusb,并且它最简单的操作模式有一个阻塞读取方法。Perl版本只是打开一个到字符设备的流并读取文本行。

我对主机端通信做了类似的更改,并让守护程序生成JSON行而不是二进制数据包。由于使用像AnyEvent这样的库在Perl中实现这一点非常容易,所以我完全放弃了“消息总线”的想法,而是让每个程序创建自己的Unix套接字,其他程序可以根据需要连接到该套接字。调试单线程要容易得多,而且无论如何也没有太多调试要做,因为AnyEvent为我完成了大部分工作。

由于所有内容都作为JSON传递,因此不再需要担心任何消息结构。我的Perl程序都不再需要make 过程,因此项目中唯一仍然有makefile的部分是微控制器固件,它非常简单,以至于我只是手工编写了它。

性能

直接使用Perl处理底层数学运算可能很慢,但在性能至关重要的场合使用Perl的最佳方法是将C库粘合在一起。Perl有一个名为XS的扩展系统,可以帮助您将C代码绑定到Perl函数,但更好的是,有一个CPAN仓库模块名为Inline,它允许您将C或C++(以及其他语言)直接粘贴到Perl模块中,并且在首次加载模块时进行编译。(但是,是的,我在为汽车构建固件映像之前预编译了它们。)

感谢Inline,我可以根据需要将代码在Perl和C之间来回移动,而无需处理库版本。我能够将我的一些C++类直接引入到新Perl版本的仪表盘中。我还能够包装用于OpenGL的FreeType (FTGL) 库的C++对象,这是一个重要的部分,我不想重新发明。

使用C++实现时,系统的CPU使用率约为15%。使用Perl时,约为40%。几乎所有这些都是渲染代码,所以如果需要,我可以随时将其中的更多代码推回C++。但是,我也可以直接升级计算机,而40%甚至不是问题,因为我保持了完整的每秒60帧(并且我运行的是一个6.4瓦的处理器)。

更广阔的前景

与其它语言相比,Perl的CPAN公共软件包仓库特别庞大、文档齐全、经过测试且稳定。当然,这取决于个别作者 (并且有很多反例),但我对测试覆盖率和有用的文档的普遍文化印象深刻。安装和使用新的Perl模块也异常容易。我不仅避免了C/C++的工具链工作,还获得了Perl作者的优势,他们已经克服了冲突的线程模型或事件循环或日志记录系统,为我提供了插件体验。

由于所有内容都是用Perl编写的,我可以从CPAN中获取我喜欢的任何东西。例如,我可以让汽车给我发送电子邮件或短信,托管一个Web应用程序通过手机控制功能,编写燃油里程的Excel文件等等。我还没有开始研究这些功能,但障碍消失的感觉真好。

回馈社区

在做C++的十年中,我从未发布过一个供公众使用的库。很大程度上是由于autotools的极端笨拙,以及即使不正确地打包分发,仅仅创建一个系统安装的C++库也是一件非常痛苦的事情。

Perl使模块编写 、测试 和 文档编写变得非常容易。它非常容易,以至于我为了自己的利益为我的Math-InterpolationCompiler 编写了测试用例和文档,然后将它们发布在CPAN上,因为“为什么不呢?”。我还成为了X11-Xlib的维护者,并大大扩展了它的API,然后编写了X11-GLX,以便我最终可以将所有OpenGL设置代码按正确的顺序排列。(这也是我尝试将仪表渲染器制作成合成窗口管理器的一部分,结果证明这比我预期的要困难得多。)目前,我正在努力将我的地图/导航数据库也制作成一个CPAN模块。

但为什么不...

“但是,为什么不是语言X呢?” 你可能会说,其中“Python”是X的常用值。好吧,首先,我比Python更了解Perl。我正在使用许多深入和高级的Perl功能,因此学习Python将是另一个漫长的学习曲线。我也偏爱Perl的工具链,尤其是像proveperldoc这样的元素。我怀疑也可以在Python中完成所有这些,但我没有令人信服的理由进行切换。对于任何其他语言X...嗯,没有其他语言可以与Perl或Python提供的软件包的丰富性相媲美,因此我不太倾向于尝试它们。我可以混合使用语言,因为我的项目由多个进程组成,但是所有东西都使用同一种语言意味着我可以更轻松地在程序之间共享代码。

“为什么不选择Android呢?” 是另一个常见问题。的确,平板电脑比整台PC更易于嵌入,并且它可以访问地图应用程序。显而易见的第一个问题是,我将回到Java,并失去我珍视的大部分敏捷性。其次,我不知道有任何方法可以合并不同应用程序的图形(例如在仪表盘中使用Google地图作为纹理),尽管可能存在一种方法。第三,我一直在开发一个功能,将视频源直接连接到图形中作为纹理。我 不知道有任何平板电脑可以以足够低的延迟从外部源实时捕获视频,更不用说直接进入图形纹理缓冲区了。Linux桌面软件对于这种深度处理更加开放,所以我可能会继续使用它。

总的来说,我很高兴我完成了足够的程度,可以驾驶我的DeLorean了。

标签
User profile image.
IntelliTree Solutions的软件工程师。Michael专注于Web应用程序、嵌入式系统和性能调优。

3 条评论

只要能用就行,我们有什么资格评判呢?
88 英里/小时,那是当然! 😉

我很好奇你是否考虑过Wayland。它比X更易于使用,并且他们添加了专门用于车载设备的东西。

““更易于使用”有点主观 ;-) 我很清楚Wayland是未来的方向,尤其是在深入研究了xlib内部结构的恐怖之处之后。对我来说,GLX“更易于使用”,因为我在2008年就已经编写了显示设置代码,我只是围绕它包装了一个perl模块。为了切换到Wayland,我首先需要将我的笔记本电脑切换到Wayland进行开发,然后学习所有的EGL API并将它们包装成一个perl模块,然后更改我的嵌入式映像中的一堆软件包。我也还没有找到像X11的Xephyr这样的等效Wayland测试工具;我正在努力将仪表盘制作成窗口管理器,如果我需要一个带显示器的专用盒子来测试这个,那就很尴尬了。”

回复 by Trey Dempsey (not verified)

Creative Commons License本作品根据知识共享署名-相同方式共享 4.0 国际许可协议获得许可。
© 2025 open-source.net.cn. All rights reserved.