作者 | Nia Catlin    译者 | 弯月

出品 | CSDN(ID:CSDNnews)

在本文中,我们将针对 13 种不同语言编写的“Hello World”演示程序,收集并可视化各个语言的指令踪迹。注意:本文主要展示了一些图表和统计结果,如果想了解指令踪迹技术细节,请参见这篇文章(https://ncatlin.github.io/rgatPages/instrumentation/pin/2021/11/03/gathering-traces.html)。

免责声明:本文中的图表是针对每种语言在 Windows 下的编译结果或解释器,对其指令踪迹进行的可视化。这些图表都是为了测试rgat而创建的,其目的并非从时间或空间的角度评价各个语言。

CSDN付费下载自视觉中国

方法论:测试程序是使用最新版本的 x64 编译工具,在 Windows 10 上编译 Hello World Collection 而获得的。

图表按照 Pin 工具记录的总执行指令数排序。原始的指令数使用Intel Pin Kit提供的Pintool收集,这些数字包含了Windows库中的代码。但是Windows目录下的代码不会在踪迹中显示,因此图中的指令数远远少于原始指令数。文中的“节点”指的都是特定地址上的指令,而“执行的指令”指的是指令总共被执行的次数。

我们选择的编程语言都来自 GitHub 的流行语言排行榜。

简介

本文的主要内容如下:

  • 介绍

  • x64 汇编(MASM)

  • C(GCC 4.8.3)

  • C++(MSVC14.29.30133,Visual Studio 社区版2019)

  • Ada(GNATStudio 社区 2021 [20210423])

  • Rust(1.56.1)

  • Delphi(EmbarcaderoDelphi 10.4 社区版)

  • Golang (go1.17.3windows/amd64) [失败]

  • AutoIt(v3,用 Aut2exe 打包成了一个 EXE)

  • Java(OpenJDK RuntimeEnvironment(build 17.0.1+12-39),用JRE直接执行)

  • C#(.NET 5,自包含的可执行文件)

  • Javascript(Node.jswindows-x64-17.1.0,用 nexe打包)

  • Python(CPython3.10, 由 PyInstaller 打包)

  • Ruby(ruby3.0.2p107, 由解释器直接执行)

  • 总结

x64汇编(MASM)

原始指令总数(包括 windows 库)

指令总数:220,029

基本块总数:49,627

比较基准如下:

没有特别之处,只有 11 个指令和几个 API 调用。

C(GCC 4.8.3)

原始指令总数(包括 windows 库)

指令总数:662,569

基本块总数:151,304

编译器给汇编指令填充了初始化栈的代码和和 C 运行时库。共计 536 个节点,执行了 1100 条指令。

C++(MSVC14.29.30133,Visual Studio 社区版2019)

原始指令总数(包括 windows 库)

指令总数:2,413,122

基本块总数:568,565

总共 520 个节点,执行了 511 条指令。

由于 API 使用量的增加,VC++ 输出执行的指令数量更多。实际执行的代码要少于GCC的C语言输出结果。

Ada(GNATStudio 社区 2021 [20210423])

原始指令总数(包括 windows 库)

指令总数:2,034,262

基本块总数:465,783

一般来说,恶意软件作者不太喜欢使用这种语言。只是我个人比较好奇这个庞大的委员会设计的语言究竟如何。

总共 3700 个节点,执行了 55.24K 条指令。

在标准的设置代码下面是一长串小循环。

Rust(1.56.1)

原始指令总数(包括 windows 库)

指令总数:4,326,506

基本块总数:984,090

上述绝大多数指令都在 Windows 库的调用中,Rust 的输出非常简单。

总共 1946 个节点,执行了 2.37K 条指令。

Delphi(EmbarcaderoDelphi 10.4 社区版)

原始指令总数(包括 windows 库)

指令总数:5,293,646

基本块总数:1,191,836

Delphi的设置代码担负起了一些实际的工作。总共2013 个节点,执行 56.5K 条指令。

Golang(go1.17.3 windows/amd64) [失败]

原始指令总数(包括 windows 库)

指令总数:? (> 5,956,506)

基本块总数:? (> 1,308,592)

Go的二进制文件逆向工程非常难,这个HelloWorld也不例外——在设置结束之前Pin就崩溃了。

尝试执行初始指令统计,结果如下:

Exception 0xc0000005 0x0 0xc000053d00 0xc000053d00
PC=0xc000053d00
runtime: unknown pc 0xc000053d00
stack: frame={sp:0xc000053bd0, fp:0x0}stack=[0xc000052000,0xc000054000)
0x000000c000053ad0: 0x0000000000000000 0x0000000000000000
0x000000c000053ae0: 0x0000000000000000 0x0000000000000000
0x000000c000053af0: 0x0000000000000000 0x0000000000000000
0x000000c000053b00: 0x0000000000000000 0x0000000000000000
0x000000c000053b10: 0x0000000000000000 0x0000000000000000
0x000000c000053b20: 0x0000000000000000 0x0000000000000000

rgat的 pintool 也遭遇了类似的命运,以下只是部分图:

主线程崩溃之前得到的结果。总共 2万5千个节点, 177万条指令。

AutoIt(v3,用 Aut2exe 打包成了一个 EXE) 

原始指令总数(包括 windows 库)

指令总数:23,807,052

基本块总数:5,376,610

我以为执行到 2300万条指令时会出现问题,但 AutoIt 生成了非常紧凑的图形。它一定是调用了大量的 Windows API。

总共 14,890 个节点,25.1 万条指令。圆柱图由于一个巨大的基本块而变形了。

Java(OpenJDKRuntime Environment(build 17.0.1+12-39),用JRE直接执行)

原始指令总数(包括 windows 库)

指令总数:101,474,902

基本块总数:20,404,201

Java是唯一一个生成了许多复杂线程的语言,所以形成了很多图形:


C#(.NET 5,自包含的可执行文件)

原始指令总数(包括 windows 库)

指令总数:115,535,357

基本块总数:25,272,210

与 Ruby 和 Python 相比,C#执行的指令数量相对较少。我以为这门语言比较容易跟踪处理,但最后生成的线程超过了 50 个,而且还有 28 万多个节点。

圆柱图。从左到右分别为:控制流图、热图和节点度渲染

复杂性都集中在线程上,Pin 目前不提供访问 Windows 命名管道的安全方式,而 rgat 依赖于Windows命名管道进行通信,它需要为每个线程生成一个管道,所以实际上每个线程都有可能产生死锁。指令计数器 pintool 只能看到 12 个线程,因此它可能正常地生成了线程。

节点数量也超出了我们可以使用 Fruchterman-Reingold 创建的力导向图。


Javascript(Node.jswindows-x64-17.1.0,用 nexe打包)

原始指令总数(包括 windows 库)

指令总数:234,399,444

基本块总数:41,162,137

主线程的力导向图符合预期——不难想象,2.05亿条指令生成的踪迹图,如果施加一个牵引力试图让它更好看些,那就会是这个样子。图中共有36万个节点。

热图还是很有用的。

图中未显示一些较小(更简单)的线程,如果统计进来指令数量将再增加几百万。


Python(CPython3.10, 由 PyInstaller 打包)

原始指令总数(包括 windows 库)

指令总数:268,1086,59

基本块总数:39,159,539

Python的解释器虽然比较大,但跟踪起来最简单,因为所有指令都是在单个线程内执行到,而且没有 JIT 代码,最后得到的图形只有 13,483 个节点。

Python3 的 Hello World 程序得出的力导向图,共计 2.6413 亿条指令(13,483 条唯一指令)。

圆柱热图:针对控制台的 WriteFile 指令在最底部。


Ruby(ruby3.0.2p107, 由解释器直接执行)

原始指令总数(包括 windows 库)

指令总数:314,162,380

基本块总数:63,395,930

现代处理器处理 3.14 亿条指令只在眨眼间,但记录和绘制指令轨迹非常有难度。

Ruby是最易于使用的 JIT 语言,它的绝大多数指令都发生在单个线程中。

针对15 万个高度连接的节点生成力导向图的标准结果。这些指令总共执行了 2.35 亿多次。为了清晰起见,返回指令对应的边和之前见过的指令对应的边都被淡化了。

圆柱热图用绿色显示了单次执行(主要是 JIT)的代码,然后是启动解释器后出现的更多循环控制流(所有其他颜色)。

力导向图中的 JIT 代码也有很多这样的泡泡结构,中央调度程序调用了许多微小的代码片段(内部的橙色边是返回指令),你也会看到某些类型的控制流,例如展平。

参考链接:

https://ncatlin.github.io/rgatPages/tracing/2021/11/19/visualising-hello-world.html

—END—

《新程序员001-004》全面上市,对话世界级大师,报道中国IT行业创新创造

《新程序员003》聚焦“云原生时代的开发者”与“全面数字化转型”两大主题,点击订阅

— 推荐阅读 —

☞李想称十年后要成为汽车界苹果;雅虎邮箱停服;Linux内核欲采用现代C语言标准 | 极客头条
☞时隔六年,FreeDOS终于更新,是否还能与Windows一战?
☞Python:Bug 官网不要了,全迁去 GitHub!

跑了 13 种编程语言的 Hello World,可视化后有了新发现!相关推荐

  1. python创意爱情代码-13种编程语言的命名创意,非常有趣!

    原标题:13种编程语言的命名创意,非常有趣! 编程语言的名称通常都很公式化和枯燥,但有些并不是.下面这13种编程语言的命名背后都有一段有趣的故事,一起来看看吧! 1. Python 这是荷兰人Guid ...

  2. 13种编程语言名称的来历

    转, 原文: http://jandan.net/2014/03/23/programming-languages.html ------------------------------------- ...

  3. 程序员的噩梦:世界上最难的5种编程语言

    导读:每个程序员都熟悉许多编程语言.许多编程语言都是高级的,它们的语法是人类可读的.然而,也有一些低级语言,对于一个人来说,读起来很困难,但是可以理解.您是否遇到过一种既不可读又不可理解的编程语言? ...

  4. 测试 C、Python、Java 等 16 种编程语言的 Hello World:7 种存在 Bug?

    译者 | 张洁 责编 | 屠敏 出品 | 程序人生 (ID:coder _life) Hello World 可能是最常用的计算机程序.几十年来,许多人在开始使用新的编程语言时,编写的第一个程序通常是 ...

  5. (转) 假如女人是一种编程语言

    计算机语言的实质其实是为了让人类能够更好与计算机打交道,最终结果都是通过编译成二进制代码或通过解释器转译成二进制代码的形式,由计算机来执行.而二进制就是0和1,假设1代表男人,0代表女人,那么瞬间就可 ...

  6. 13种重要的云原生工具,让交付过程更快

    来源 | SDNLAB 责编 | 寇雪芹 头图 | 下载于视觉中国 SUSE收购Rancher Pure Storage收购Portworx Veeam收购Kasten VMware收购Octarin ...

  7. php java c_当PHP、Java、C、C++ 这几种编程语言变成汽车是什么样的场景?

    在学习和工作中,人们常常会把各种编程语言拿出来做对比,特别是刚刚开始入门学习IT的同学.实际上,每门语言自己的优缺点有时候也正是语言本身的特性,在学习中,我们更应该关心的是应用场景,哪门语言适合哪个场 ...

  8. python十二星座符号_12种编程语言类比12星座女

    PS:这篇博文是一个技术群的码农写的,这哥们真有才,根据我对星座的看法,比喻得很靠谱,特转如下: 计算机语言的实质其实是为了让人类能够更好与计算机打交道,最终结果都是通过编译成二进制代码或通过解释器转 ...

  9. 13种老人不适合带孩子_让老人带娃却遭怒摔!细数13种不适合带孩子的老人!...

    让老人带娃却遭怒摔!细数13种不适合带孩子的老人! 一位妈妈说了自家老人带娃的事,让人捏了一把冷汗! 宝宝满月后,婆婆脾气越来越大,没有带过一天宝宝. 相处过程中,婆婆看一会,就让宝宝从很高的床上摔下 ...

最新文章

  1. java 调用r语言包传参数_Java与R语言的配置,调用
  2. Linux系统编程24:基础IO之在Linux下深刻理解C语言中的动静态库以及头文件和库的关系
  3. 101 LINQ Samples
  4. 联想e52进入bios_联想昭阳E52-80笔记本win10怎么改win7
  5. 文献笔记4 water volume variations
  6. win10位置定位服务器,win10定位设置在哪里进行设置|win10定位的设置方法详解
  7. Arch Linux 安装卓懿(xDroid)AUR 包
  8. html,css使用表格制作课程表
  9. POJ 1436 Horizontally Visible Segments(线段树区间修改)
  10. EasyExcel Invalid row number (65536) outside allowable range
  11. 华为新平板以美好体验定义青春
  12. Java入门-机票购买、座舱等级、淡旺季计算价格
  13. 【番外篇】Excel:一行转多行
  14. jdk1.8下载及安装
  15. 搜狗输入法的使用感受与评价
  16. mysql on delete_MySQL ON DELETE CASCADE
  17. 公子世无双,代码永流传!!!我与github。
  18. Python菜鸟学习之基础篇(持续学习中)
  19. 利用笔记本无线网卡实现共享上网
  20. 幼儿抽象逻辑思维举例_如何激发3-6岁孩子的学霸潜质?关键一招就在逻辑思维训练|绘本|数学|游戏书...

热门文章

  1. 剑指offer——4.二维数组中的查找
  2. 【英语】秋风吹---9月英语
  3. Flume-概述-安装
  4. 使用join()方法 分隔拆分后的数组
  5. C#,COM口,接收,发送数据
  6. LightOJ 1353 - Paths in a Tree DFS
  7. 第三篇 :微信公众平台开发实战Java版之请求消息,响应消息以及事件消息类的封装...
  8. Javascript浅谈之this
  9. VS找不到MFC90d.dll错误
  10. 优秀作品展示:15个使用了漂亮字体的网站