it编程 > 编程语言 > Delphi

Modern Pascal is Still in the Race (Modern Pascal 仍在竞赛中)

69人参与 2024-06-01 Delphi

modern pascal 仍在竞赛中

作者:arnaud bouchez,2022年11月26日。永久链接

最近在lazarus/fpc 论坛上的一项民意调查突显了一个事实:pascal 程序员比其他大多数程序员年龄都大。通常来说,到了我们这个年纪,应该做管理人员而非开发人员了。但我们仍喜欢用 pascal 编程。几十年过去了,它仍然很有趣!

但这是否意味着你不应该使用 pascal 来做任何新项目呢?语言/编译器/库是否过时了呢?

在我目前工作的公司里,我们有一些年轻的程序员,他们有的是刚毕业,有的还在上学,他们加入了团队并写出了出色的代码!

img

最近在同一个论坛上的一个帖子讨论了使用 c#、go、scala、typescript、elixir 和 rust 等语言实现 rest 服务器的比较。

即将贡献出几个 pascal 版本,其中之一就是 mormot 大放异彩的版本。

挑战与算法

最初的挑战可在 transit-lang-cmp 找到,其中包含所有这些花哨语言和库的源代码。

实际上,此测试程序的目标是加载两个大型 csv 到内存中(80mb + 2mb),然后通过 http 提供由路由标识符生成的 json,同时连接两个 csv。

生成的 json 大小可能在 30kb 到 2mb 之间。所有数据都是根据内存中的 csv 实时生成的。

说句公道话,一个普通的商业程序员会为此使用数据库。而不是傻傻的内存结构。并要求资金支持,以建立一组庞大的云计算机器和负载均衡。😃

遵循mormot的方式

对于fpc中的mormot版本,我采用了另一种方法,使用了两种不同的算法:

这里没有使用像手动生成json或使用复杂数据结构这样的底层技巧——数据结构仍然是高级的,具有可读的字段名等。逻辑和意图都是清晰可读的。
我们只是利用了pascal语言和mormot的特性。例如,如果需要,字符串内联是框架的一部分。

查看我们存储库中的源代码

结果如下:

img

算法的重要性

主要的思想是让算法匹配输入数据和预期的结果集。
就像程序员在编程游戏时所做的那样。而不像编码人员在编写商业软件时那样随意。😉

公平地说,我使用了类型化指针,但理解它们的目的并不难,而且fpc会将此函数编译成非常高效的汇编代码。我本来可以使用带有索引的常规动态数组访问,这样虽然会稍微慢一点,但并不更容易跟踪,也不更安全(如果我们在没有范围检查的情况下编译)。tscheduler.buildtripresponse

值得注意的是,我们没有进行任何特定的调优,例如像其他框架所做的那样使用常量预分配结果。我们只是指定了数据,然后让mormot来处理它——仅此而已。
mormot的rtti级别符合我们对现代框架的期望:不仅仅是用一些类来存储json,还可以使用像类或记录这样的结构进行方便的序列化/反序列化。
使用现代pascal动态数组和记录来定义数据结构,让编译器为我们利用内存,无需编写任何块和使用接口。pascal的“手动内存管理”不是强制性的,而且可以很容易地绕过。只有对于webserver,我们有一个预期会关闭它的 try..finally..freefree

给我一些数字

以下是与go的性能比较(左侧为fpc,右侧为go):

参数 fpc性能 go性能
- 在968.43毫秒内解析了1790905个停车时间 在3.245251432秒内解析了1790905个停车时间
- 在39.54毫秒内解析了71091次行程 在85.747852毫秒内解析了71091次行程
- 正在运行(0m33.4s),00/50 vus,348个完成,0个中断 正在运行(0m32.3s),00/50 vus,320个完成,0个中断
- 默认✓ [===================] 50 vus 30 默认✓ [===================] 50 vus 30
数据接收量 31 gb,933 mb/s 31 gb,971 mb/s
数据发送量 3.2 mb,97 kb/s 3.0 mb,92 kb/s
http请求被阻止 平均=9微秒,最小=1.09微秒 平均=6.77微秒,最小=1.09微秒
http请求连接 平均=2.95微秒,最小=0秒 平均=1.73微秒,最小=0秒
http请求持续时间 平均=47.59毫秒,最小=97.28微秒 平均=49.02毫秒,最小=123.81微秒
平均=47.59毫秒,最小=97.28微秒 平均=49.02毫秒,最小=123.81微秒
http请求失败 0.00%,✓ 0,✗ 0.00%,✓ 0,✗ 3
http请求接收 平均=9.66毫秒,最小=15.35微秒 平均=5.92毫秒,最小=14.76微秒
http请求发送 平均=87.24微秒,最小=5.2微秒 平均=70.71微秒,最小=5.2微秒
http请求tls握手 平均=0秒,最小=0秒 平均=0秒,最小=0秒
http请求等待 平均=37.83毫秒,最小=54.74微秒 平均=43.02毫秒,最小=91.84微秒
http请求 34452,1032.205528/秒 31680,981.949476/秒
迭代持续时间 平均=4.72秒,最小=3.54秒 平均=4.86秒,最小=2.19秒
迭代次数 348,10.426318/秒 320,9.918682/秒
vus 30,最小=30,最大 15,最小=15,最大
vus_max 50,最小=50,最大 50,最小=50,最大

其实文本也很好看

parsed 1790905 stop times in 968.43ms                          | parsed 1790905 stop times in 3.245251432s
parsed 71091 trips in 39.54ms                                  | parsed 71091 trips in 85.747852ms

running (0m33.4s), 00/50 vus, 348 complete and 0 interrupted   | running (0m32.3s), 00/50 vus, 320 complete and 0 interrupted
default ✓ [======================================] 50 vus  30    default ✓ [======================================] 50 vus  30

     data_received..................: 31 gb  933 mb/s          |      data_received..................: 31 gb  971 mb/s
     data_sent......................: 3.2 mb 97 kb/s           |      data_sent......................: 3.0 mb 92 kb/s
     http_req_blocked...............: avg=9µs     min=1.09µs   |      http_req_blocked...............: avg=6.77µs  min=1.09µs
     http_req_connecting............: avg=2.95µs  min=0s       |      http_req_connecting............: avg=1.73µs  min=0s   
     http_req_duration..............: avg=47.59ms min=97.28µs  |      http_req_duration..............: avg=49.02ms min=123.81µ
       { expected_response:true }...: avg=47.59ms min=97.28µs  |        { expected_response:true }...: avg=49.02ms min=123.81µ
     http_req_failed................: 0.00%  ✓ 0           ✗  |      http_req_failed................: 0.00%  ✓ 0          ✗ 3
     http_req_receiving.............: avg=9.66ms  min=15.35µs  |      http_req_receiving.............: avg=5.92ms  min=14.76µs
     http_req_sending...............: avg=87.24µs min=5.2µs    |      http_req_sending...............: avg=70.71µs min=5.2µs 
     http_req_tls_handshaking.......: avg=0s      min=0s       |      http_req_tls_handshaking.......: avg=0s      min=0s   
     http_req_waiting...............: avg=37.83ms min=54.74µs  |      http_req_waiting...............: avg=43.02ms min=91.84µs
     http_reqs......................: 34452  1032.205528/s     |      http_reqs......................: 31680  981.949476/s
     iteration_duration.............: avg=4.72s   min=3.54s    |      iteration_duration.............: avg=4.86s   min=2.19s 
     iterations.....................: 348    10.426318/s       |      iterations.....................: 320    9.918682/s
     vus............................: 30     min=30        ma  |      vus............................: 15     min=15       max
     vus_max........................: 50     min=50        ma  |      vus_max........................: 50     min=50       max

因此,csv加载速度要快得多,而http服务器的性能则几乎相同。

no alzheimer---无阿尔茨海默症

以下是一些关于内存消耗的数据:

在完成csv加载后,mormot仅占用80mb,天哪,这么少。听起来有点神奇。但在负载测试中,它在250-350mb之间波动,测试结束后又回到80mb。go版本在加载完csv后占用925mb。在负载测试中,它最高达到了1.5gb,之后又回到了925mb。

读起来不错。😃

pascal拥有一个现代且功能强大的生态系统

这篇文章不仅仅是关于pascal的,还涉及到算法和库。
最初的挑战是比较它们。不仅仅是作为不现实的微观基准测试,或“计算机语言基准测试游戏”,而是作为实际应用场景中的数据处理能力。

而且……pascal当然还在竞争中!
不仅仅是为了像我这样的“老人”——我刚满50岁 (译者注:本文作者arnaud bouchez发表于2022年11月26日 )。😉

我们传播的这类信息越多,就越少有人会拿pascal程序员开玩笑。
delphi和fpc与java一样古老,所以是时候看到大局了,而不是跟随市场趋势。

(0)

您想发表意见!!点此发布评论

推荐阅读

Safe locks for multi-thread applications(多线程应用程序的安全锁)

06-01

End Of Live OpenSSL 1.1 vs Slow OpenSSL 3.0

05-27

Three Locks To Rule Them All(三把锁统治一切)

05-27

IDocList/IDocDict JSON for Delphi and FPC

05-23

解决升级到 Delphi 12 后遇到 SQLite 不兼容的问题

05-16

delphi JSON序列化(四)

05-16

猜你喜欢

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论