有趣的编程语言统计:Go 语言的启动时间是 C 语言的 300 多倍,C# 的关键字最多

提到编程语言,大多数的文章内容都这样的:Java 已死?Ruby 的“消亡史”;编程语言排行榜:Go 最流行,Rust 最有前途;Go 语言已经全面碾压 Python…

相信很多读者都已经阅读疲劳了,所以我们这次另辟蹊径,从更有趣的视角来看编程语言,分别是编程语言的启动时间和关键字,帮助开发者更深刻和全面的认识编程语言。

谁的启动时间最少?Go 语言的启动时间是 C 语言的 300 多倍

为什么我们要观察不同编程语言的启动时间呢?因为编程语言的启动时间对于短时间运行的程序非常重要,这些程序由用户交互调用,或者由其他程序 (多次) 调用。

版本控制系统 Git 是用 C 编写的,调用的命令 (如 Git status 和 Git log) 执行速度很快。版本控制系统 Bazaar 和 Mercurial 是用 Python 编写的,它们的执行时间比 Git 长得多,并且这种速度的快慢是可被程序员感知到的,导致这种速度差异的主要原因就是 Python 启动时间占据了执行时间的大部分。

为了验证每种编程语言的启动时间各是多少,GitHub 上的一位开发者  bdrung  专门设置了一个小小的项目,项目由许多不同语言的 hello world 程序和一个简单的 Makefile 组成,Makefile 编译程序并运行基准测试,每个程序通过一行代码(使用一个很小的 run.c 程序来最小化调用的开销)运行 1000 次:

time -f “%e” taskset -c 0 ./run 1000 $program

在运行基准测试之前,安装相关的编译器,如果是在 Debian / Ubuntu 上,可以运行 make install 以安装编译器,然后通过调用 make 启动基准。

测试结果如下:

Language version Intel Core i5 2400S Raspberry Pi 3
Pascal (fpc) 3.0.2 / 3.0.4 0.08 ms 0.66 ms
C (gcc) 7.2.0 0.26 ms 2.19 ms
Shell (dash) 0.5.8 0.33 ms 2.81 ms
Go (go) 1.8.3 / 1.9.3 0.41 ms 4.10 ms
Rust (rustc) 1.21.0 / 1.22.1 0.51 ms 4.42 ms
D (gdc) 7.2.0 0.57 ms
Lua 5.2.4 0.63 ms 6.23 ms
Bash 4.4.12(1) 0.71 ms 7.31 ms
C++ (g++) 7.2.0 0.79 ms 8.24 ms
Perl 5.26.0 / 5.26.1 0.94 ms 8.78 ms
Haskell (ghc) 8.0.2 0.72 ms 9.44 ms
ZShell 5.2 / 5.4.2 1.57 ms 11.04 ms
CShell 20110502 3.26 ms 10.98 ms
Python (with -S) 2.7.14 2.91 ms 32.77 ms
Python 2.7.14 9.43 ms 91.85 ms
PHP 7.1.11 / 7.2.2 8.71 ms 98.03 ms
Cython 0.25.2 / 0.26.1 9.91 ms 98.71 ms
Python3 (with -S) 3.6.3 / 3.6.4 9.31 ms 110.02 ms
C# (mcs) 4.6.2.0 13.37 ms 137.53 ms
PyPy 5.8.0 27.53 ms 183.50 ms
Cython3 0.25.2 / 0.26.1 26.04 ms 196.36 ms
Python3 3.6.3 / 3.6.4 25.84 ms 197.79 ms
Ruby 2.3.3p222 / 2.3.6p384 32.43 ms 421.53 ms
Java (javac) 1.8.0_151 54.55 ms 566.66 ms
Go (gccgo) 7.2.0 98.26 ms 898.30 ms
Scala (scalac) 2.11.8 310.81 ms 2989.72 ms

我们稍稍给这些结果分一下类,分为快速、普通、较慢、很慢。

如果在 Intel Core i5 2400S 的启动时间低于 1 ms,在 Raspberry Pi 3 的启动时间低于 10 ms,我们就认为这类编程语言的启动速度是快速,其中包括 Bash、C、C++、D (gdc)、Go (go)、Haskell、Lua、Pascal、Perl、Rust 和 Shell (dash)。

如果在 Intel Core i5 2400S 的启动时间介于 1 ms 到 5 ms 之间,在 Raspberry Pi 3 的启动时间介于 10 ms 到 50 ms 之间,那么我们就认为这类编程语言的启动速度是普通,其中包括 CShell、Python 2 (with -S) 和 ZShell。

如果在 Intel Core i5 2400S 的启动时间介于 5 ms 到 50 ms 之间,在 Raspberry Pi 3 的启动时间介于 50 ms 到 500 ms 之间,那么我们就认为这类编程语言的启动速度是较慢,其中包括 C# (mcs)、Cython (Python 2)、Cython3 (Python 3)、PHP、Python 2、Python 3、Python 3 (with -S)、PyPy (Python 2) 和 Ruby。

如果在 Intel Core i5 2400S 的启动时间超过 50ms,在 Raspberry Pi 3 的启动时间超过 500ms,我们就认为这类编程语言启动速度特别慢,其中包括 Java、Go (gccgo) 和 Scala。

从关键字的多少来看编程语言的复杂性,C#的关键字最多(77 个)

想要使用编程语言就避不开关键字,编程语言中关键字的数量在一定程度上可以表明编程语言的复杂性,甚至还会影响到开发者利用该编程语言创造的相应程序的复杂性,而复杂的程序维护成本更高,招聘难度也会升级。

编程语言关键字的统计最早是由  @leighmcculloch  开始做的,下图是他的统计结果。

有趣的编程语言:Go 语言的启动时间是 C 语言的300多倍,C# 的关键字最多

之后,GitHub 上的开发者 e3b0c442 对这个话题也非常感兴趣,所以他也做了一个相似的统计,下面我们就来看一下他的统计结果吧。

编程语言的具体关键字情况如下:
C (ANSI) (32 keywords)
http://port70.net/~nsz/c/c89/c89-draft.html#3.1.1

auto break case char
const continue default do
double else enum extern
float for goto if
int long register return
short signed sizeof static
struct switch typedef union
unsigned void volatile while

C (C18) (44 keywords)
http://www.open-std.org/jtc1/sc22/wg14/www/abq/c17_updated_proposed_fdis.pdf

auto break case char
const continue default do
double else enum extern
float for goto if
inline int long register
restrict return short signed
sizeof static struct switch
typedef union unsigned void
volatile while _Alignas _Alignof
_Atomic _Bool _Complex _Generic
_Imaginary _Noreturn _Static_assert _Thread_local

C# (5.0) (77 keywords)
https://download.microsoft.com/download/0/B/D/0BDA894F-2CCD-4C2C-B5A7-4EB1171962E5/CSharp%20Language%20Specification.docx

abstract as base bool
break byte case catch
char checked class const
continue decimal default delegate
do double else enum
event explicit extern false
finally fixed float for
foreach goto if implicit
in int interface internal
is lock long namespace
new null object operator
out override params private
protected public readonly ref
return sbyte sealed short
sizeof stackalloc static string
struct switch this throw
true try typeof uint
ulong unchecked unsafe ushort
using virtual void volatile
while

C++ (C++17) (73 keywords)
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/n4659.pdf

alignas alignof asm auto
bool break case catch
char char16_t char32_t class
const constexpr const_cast continue
decltype default delete do
double dynamic_cast else enum
explicit export extern false
float for friend goto
if inline int long
mutable namespace new noexcept
nullptr operator private protected
public register reinterpret_cast return
short signed sizeof static
static_assert static_cast struct switch
template this thread_local throw
true try typedef typeid
typename union unsigned using
virtual void volatile wchar_t
while

Dart (1) (33 keywords)
http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-408.pdf

assert break case catch
class const continue default
do else enum extends
false final finally for
if in is new
null rethrow return super
switch this throw true
try var void while
with

Elixir (1.7) (15 keywords)
https://github.com/elixir-lang/elixir/blob/master/lib/elixir/pages/Syntax%20Reference.md

true false nil when
and or not in
fn do end catch
rescue after else

Erlang (21.2) (27 keywords)
http://erlang.org/doc/reference_manual/introduction.html#reserved-words

after and andalso band
begin bnot bor bsl
bsr bxor case catch
cond div end fun
if let not of
or orelse receive rem
try when xor

Go (1.11) (25 keywords)
https://golang.org/ref/spec#Keywords

break case chan const
continue default defer else
fallthrough for func go
goto if import interface
map package range return
select struct switch type
var

JS (ES2018) (34 keywords)
https://www.ecma-international.org/ecma-262/9.0/index.html#sec-keywords

await break case catch
class const continue debugger
default delete do else
export extends finally for
function if import in
instanceof new return super
switch this throw try
typeof var void while
with yield

Java (SE 11) (51 keywords)
https://docs.oracle.com/javase/specs/jls/se11/html/jls-3.html#jls-3.9

abstract assert boolean break
byte case catch char
class const continue default
do double else enum
extends final finally float
for if goto implements
import instanceof int interface
long native new package
private protected public return
short static strictfp super
switch synchronized this throw
throws transient try void
volatile while

Kotlin (1.3) (30 keywords)
https://kotlinlang.org/docs/reference/keyword-reference.html

as as? break class
continue do else false
for fun if in
interface is
null object package return
super this throw true
try typealias val var
when while

PHP (7.0) (67 keywords)
http://php.net/manual/en/reserved.keywords.php

__halt_compiler() abstract and array()
as break callable case
catch class clone const
continue declare default die()
do echo else elseif
empty() enddeclare endfor endforeach
endif endswitch endwhile eval()
exit() extends final finally
for foreach function global
goto if implements include
include_once instanceof insteadof interface
isset() list() namespace new
or print private protected
public require require_once return
static switch throw trait
try unset() use var
while xor yield

Python (2.7) (31 keywords)
https://docs.python.org/2/reference/lexical_analysis.html#keywords

and as assert break
class continue def del
elif else except exec
finally for from global
if import in is
lambda not or pass
print raise return try
while with yield

Python (3.7) (35 keywords)
https://docs.python.org/3.7/reference/lexical_analysis.html#keywords

False None True and
as assert async await
break class continue def
del elif else except
finally for from global
if import in is
lambda nonlocal not or
pass raise return try
while with yield

R (3.5) (20 keywords)
https://cran.r-project.org/doc/manuals/r-release/R-lang.html#Reserved-words

FALSE Inf NA
NA_character_ NA_complex_ NA_integer_ NA_real_
NaN NULL TRUE break
else for function if
in next repeat while

Ruby (2.5) (41 keywords)
https://docs.ruby-lang.org/en/2.5.0/keywords_rdoc.html

ENCODING LINE FILE BEGIN
END alias and begin
break case class def
defined? do else elsif
end ensure false for
if in module next
nil not or redo
rescue retry return self
super then true undef
unless until when while
yield

Rust (1.31) (53 keywords)
https://doc.rust-lang.org/grammar.html#keywords

_ abstract alignof as
become box break const
continue crate do else
enum extern false final
fn for if impl
in let loop macro
match mod move mut
offsetof override priv proc
pub pure ref return
Self self sizeof static
struct super trait true
type typeof unsafe unsized
use virtual where while
yield

Scala (2.12) (40 keywords)
https://scala-lang.org/files/archive/spec/2.12/01-lexical-syntax.html

abstract case catch class
def do else extends
false final finally for
forSome if implicit import
lazy macro match new
null object override package
private protected return sealed
super this throw trait
try true type val
var while with yield

Swift (4.2) (70 keywords)
https://docs.swift.org/swift-book/ReferenceManual/LexicalStructure.html

associatedtype class deinit enum
extension fileprivate func import
init inout internal let
open operator private protocol
public static struct subscript
typealias var break case
continue default defer do
else fallthrough for guard
if in repeat return
switch where while as
Any catch false is
nil rethrows super self
Self throw throws true
try _ #available #colorLiteral
#column #else #elseif #endif
#error #file #fileLiteral #function
#if #imageLiteral #line #selector
#sourceLocation #warning

编程语言与关键字个数对比表:

编程语言 关键字个数
C(ANSI) 32
C(C18) 44
C#(5.0) 77
C ++(C ++ 17) 73
Dart(1) 33
Elixir(1.7) 15
Erlang(21.2) 27
Go(1.11) 25
JS(ES2018) 34
Java(SE 11) 51
Kotlin(1.3) 30
PHP(7.0) 67
Python(2.7) 31
Python(3.7) 35
R(3.5) 20
Ruby(2.5) 41
Rust(1.31) 53
Scala(2.12) 40
Swift(4.2) 70

总体来看,编程语言的关键字都集中在两位数,关键字个数在 50 以上的共有 6 个,其中最多的是 C#,共有 77 个关键字;关键字个数在 30-50 之间的编程语言共有 9 个;关键字个数低于 30 的编程语言有 4 个,其中最少的是 Elixir,只有 15 个关键字。

参考链接:

https://github.com/bdrung/startup-time

https://github.com/e3b0c442/keywords

本文文字及图片出自 InfoQ

余下全文(1/3)
分享这篇文章:

请关注我们:

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注