写点什么

如何用 Swift 重写 C++/ObjC 代码库,并将其缩减 70%

  • 2022-07-29
  • 本文字数:2629 字

    阅读完需:约 9 分钟

如何用Swift重写C++/ObjC代码库,并将其缩减70%

疫情期间,作者花了 18 月的时间,将图形计算器(Graphing Calculator)从 C++/ObjC 移植到了 Swift 上,将代码量缩减为原来的 30%,并且没有明显的功能或性能损失。



图形计算器(Graphing Calculator)始于 1985 年,是为了 128K Macintosh 用 C 语言编写的,当时它仅有 16 位整数、黑白 Quickdraw 以及不带 MMU、FPU 和 GPU 的 8MHz 68000 CPU。那是一个简单的时代。之后很多事情都发生了变化。


我长期以来都坚持“如果没有坏,就不要去修”的理念,因此代码携带了许多它过去的痕迹——在当时有意义的设计选择,但在现在已经不适用了。它见证了 CPU 从 Motorola(摩托罗拉) 68K 到 IBM PowerPC 系列、再到 Intel 和 ARM 的变化。它最初是在 Macintosh 内部编写的经典 Mac API,然后是 Carbon,再是 Cocoa、AppKit & UIKit,现在是 SwiftUI。


通过编写新代码来添加新功能,并将古老的遗留代码隐藏在抽象层下,这是更容易做到的。最终的结果是:积累了数十年的技术债会使新的开发变得令人担忧。图形计算器(Graphing Calculator)仍然使用 Classic Mac OS 9 协作线程 API 来运行 20 世纪 80 年代冻结的非线程安全代码。从头开始重写所有内容,也就是从轨道上起飞并摧毁整个站点,这几乎从来都不是一个好主意。遗留代码包含了当前开发人员从未经历过的数十年的艰辛教训,即使是最初的开发人员,如果他们还在的话,也早就忘记了。虽然一个全新的开始可能会在美学上令人满意,但它也会为缺陷创造一个巨大的表面积。在典型的小版本发布中,专注于新特性的测试是很容易的。彻底重写后,一切都是新的。尽管如此,在把问题隐藏了 35 年之后,我决定的最好方式依然是重新审视一切,并从头开始重写。


C++ 一直是管理大型项目复杂性的有效语言,那么我为什么还要更换语言呢?我对苹果的增强现实技术印象深刻。在为我们的 iOS 产品添加了 AR 支持后,受 AR 在儿童故事书中使用的启发,我构建了一个原型应用程序,探索如何在数学教育中使用 AR。你可以在 http://PacificT.com/AR/https://twitter.com/RonAvitzur/status/1250520615993270272 查看相关的视频。该应用程序主要是用 C++ 和 ObjectiveC++ 编写的。原型使用 ARKit 进行视觉和机器学习,虽然在 Objective-C 中这是可行的,但在 Swift 中它会更容易。很显然,苹果的新技术将继续行得通。


我通过移植图形计算器(Graphing Calculator)的核心计算机代数系统来学习 Swift。它一开始只是一个学习练习活动,后来变成了一项可行性研究。疫情在这一决定中发挥了重要作用,因为这成为了我的疫情就地避难项目。重构本来可以用 C++ 和 Objective-C++ 来完成,但它不是那么有效,也不会那么有趣。该移植合并了许多转换:



该移植还涉及到了重构并重写核心算法,这些算法由于其功能的逐步发展而变得非常笨重了。


在过去的 18 个月里,我一直在努力重写所有这些内容。以下是我所学到的:


我喜欢 Swift 的语法。C++ 所需的大量重复样板代码在 Swift 中消失了,只剩下表示逻辑所需的代码,使含义更加清晰了。Swift 在集合类中使用了值类型,这使对它们的推理变得更加简单了;语法糖使得对它们的使用变得极其简单,并且它们还得到了一个实现支持,该实现使用自动引用计数和写时复制来使它们在几乎所有的使用中都具有高性能。(发现该语句的限制性仍然是优化图形计算机性能的一个重要课题。)使用带有内置 Unicode 支持的 Swift String 取代了混乱的 C++ char、UTF-8 和 UTF-16 表示,改进了代码组织,简化了代码推理。ARC、类型推断、可选项、闭包、关联值枚举、不需要头文件以及 Swift 并发,所有这些都对编写简洁、富有表现力的代码做出了重大的贡献。


最后,该移植的可维护性、可读性以及紧凑性都大大提高了。当我移植单独的功能部分时,Swift 源代码的大小通常是相应 C++ 代码的 30%。(虽然代码行数不是一个信息量很大的指标,但它却很容易衡量。)更少的代码意味着更少的调试、更少的阅读和理解,仅此一点就使移植更容易维护。使用 SwiftUI,视图控制器完全消失了:这是声明式编程对命令式编程的一大胜利。总之,源代码从 152,000 行减少到了 29,000 行,并且没有明显的功能或性能损失。


该移植的最大挑战是实现同等的速度。数十年的迭代改进以及对每个版本的低层优化为性能设定了一个很高的标准。在性能临界(performance-critical)代码中驾驭 Swift 的无数不安全 API 虽然很困难,但也很有效。剩下的最大挑战就是最小化 ARC 保留 / 释放导航表达式树的开销。依靠 ARC 消除了大量的代码复杂性。C++ 代码手动处理表达式的内存管理,这虽非常脆弱,但却非常快。Swift 版本更小,更容易编写正确的代码和推理,但有性能临界部分,我知道遍历树不会更改任何引用计数,但无法与编译器沟通,ARC 保留 / 释放的开销是不必要的。Swift 语言、库和运行时都有非常出色的文档,甚至可以在必要时查看开源实现。相比之下,SwiftUI 框架是闭源的。当 SwiftUI 工作时,它会给人带来近乎神奇的愉悦感,但当它的行为出乎意料或需要超出规定路径的行为时,它就变得很难理解,并且也很难饶过它的局限性。


是否值得我花时间将其移植到 Swift 上?我很喜欢学习 Swift,并且对现在的代码状态也很满意。用 Swift 写作纯粹是一种快乐。自 80 年代开始,我一直就在打算最终要开源我的代码。当我考虑使用 C++ 代码库做这件事时,我意识到这不会是一项有用的贡献,因为数十年来积累的技术债使 C++ 代码变得不可维护了。我现在很有信心将新代码制作成有用的独立 Swift 包,用于数学排版、编辑、数值和符号计算以及绘图。


Swift 兑现了它的承诺,实现了安全、快速且富有表现力的代码。SwiftUI 也兑现了它的承诺,用最少的代码实现了跨越苹果平台的卓越用户体验。我要感谢所有为 Swift 做出贡献的人,感谢他们的辛勤工作。用 Swift 编程真的很有趣。特别感谢所有花时间在 Swift 论坛和 Twitter 上回答菜鸟问题的人。在整个过程中,我无法表达我对你们耐心和专业帮助的感激之情。


图形计算器(Graphing Calculator)可在 macOS 和 iOS 上使用。


原文链接:


https://www.swift.org/blog/graphing-calculator/


今日好文推荐


搞不定移动端性能,全球爆火的 Notion 从 Hybrid 转向了 Native


离开谷歌的副作用:外面很难找到这么好用的开发工具


字节将大幅压缩招聘规模;滴滴被罚 80 亿,违法行为持续 7 年;各国软件开发者薪资统计:中国上榜全球开发者薪酬最低国家名单 | Q 资讯


编程不适合 12 小时工作制,“我有灵感才工作” | 专访《Java 编程思想》作者 Bruce Eckel


2022-07-29 16:273858

评论

发布
暂无评论
发现更多内容

在 Amazon DocumentDB 里处理 Decimal128类型数据的解决方案

亚马逊云科技 (Amazon Web Services)

Squids openGauss | 云上免费openGauss数据库服务

daydayup

中文多模态医学大模型智能分析X光片,实现影像诊断,完成医生问诊多轮对话

汀丶人工智能

人工智能 自然语言处理 计算机视觉 多模态大模型

平台工程动态 MonthlyNews 2023-7

杨振涛

云原生 研发效能 平台工程 开发者体验 内部开发者平台

ChatPaper全流程加速科研:论文阅读+润色+优缺点分析与改进建议+审稿回复

汀丶人工智能

人工智能 自然语言处理 nlp chatpaper

配置 Sublime Text4为 C++ 编辑器的方法

芯动大师

数字人第一剑,先斩“尹天仇”

脑极体

AI

远程控制软件安全吗?一文看懂ToDesk、RayLink、TeamViewer、Splashtop相关安全机制

颜淡慕潇

安全 远程控制 远程桌面工具 ToDesk

在Go中使用Arm的SIMD指令

geange

Go 汇编 neon arm64

Requests+Etree+BeautifulSoup+Pandas+Path+Pyinstaller应用 | 获取页面指定区域数据存入html、excel文档

Python pandas pyinstaller requests BeautifulSoup

北岩律师事务所:50000余家客户的选择,全国首家专注大消费领域的精品律所

联营汇聚

C++异步编程开源项目Workflow三岁啦 \^0^/

1412

开源项目 异步编程 异步任务编程 workflow C++

不用再写FlinkSQL了,使用开源XL-LightHouse轻松实现海量数据实时统计

feng

大数据 流式计算 流式大数据统计 流式统计 企业数据化运营

ShareSDK 国外平台登陆返回参数

MobTech袤博科技

前端 App

IoTOS-App v0.6.0 智能诊断、用量/会话记录、批量业务办理、

开源物联卡管理平台-设备管理

物联网平台 IoT 开源软件 国产开源 物联网展

大会议程正式公布 华为开发者大会看点前瞻

极客天地

openGauss运维能力之SQLPatch解密

daydayup

PoseiSwap:通过 RWA 的全新叙事,反哺 Nautilus Chain 生态

股市老人

Sprint Boot学习路线2

小万哥

Java spring Spring Cloud Spring Boot 后端

javascript数组基础

timerring

JavaScript

openGauss内核分析(四):查询重写(二)

daydayup

DHorse v1.3.0 发布,基于k8s的发布平台

tiandizhiguai

DevOps k8s

Apache IoTDB v1.1.1/v1.1.2 发布|增加 ZSTD 压缩,show variables 增加时间精度

Apache IoTDB

IoTDB Apache IoTDB

2023-07-31:用r、e、d三种字符,拼出一个回文子串数量等于x的字符串。 1 <= x <= 10^5。 来自百度。

福大大架构师每日一题

福大大架构师每日一题

惊喜!1行Python代码,瞬间测你工作量,分享一个统计代码行数的神器

程序员晚枫

Python GitHub 开源项目 工作量

PoseiSwap:通过 RWA 的全新叙事,反哺 Nautilus Chain 生态

鳄鱼视界

云原生大数据平台CloudEon V1.1.0版本发布!

CloudEon开源

大数据 云原生 容器化

如何用Swift重写C++/ObjC代码库,并将其缩减70%_语言 & 开发_Ron Avitzur_InfoQ精选文章