提到编程语言,大多数的文章内容都这样的: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 开始做的,下图是他的统计结果。
之后,GitHub 上的开发者 e3b0c442 对这个话题也非常感兴趣,所以他也做了一个相似的统计,下面我们就来看一下他的统计结果吧。
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
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
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
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
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
true
false
nil
when
and
or
not
in
fn
do
end
catch
rescue
after
else
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
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
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
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
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
__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
private
protected
public
require
require_once
return
static
switch
throw
trait
try
unset()
use
var
while
xor
yield
and
as
assert
break
class
continue
def
del
elif
else
except
exec
finally
for
from
global
if
import
in
is
lambda
not
or
pass
raise
return
try
while
with
yield
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
…
FALSE
Inf
NA
NA_character_
NA_complex_
NA_integer_
NA_real_
NaN
NULL
TRUE
break
else
for
function
if
in
next
repeat
while
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
_
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
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
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 个关键字。
参考链接: