提到编程语言,大多数的文章内容都这样的: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 对这个话题也非常感兴趣,所以他也做了一个相似的统计,下面我们就来看一下他的统计结果吧。
编程语言的具体关键字情况如下:
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
评论 2 条评论