单令牌前瞻的性能损失是多少?
What is a perfomance penalty for single token lookahead?
在比较Go和Scala的语句结束检测时,我发现Scala的规则更丰富,即:
A line ending is treated as a semicolon unless one of the following
conditions is true:
- The line in question ends in a word that would not be legal as the end of a statement, such as a period or an infix operator.
- The next line begins with a word that cannot start a statement.
- The line ends while inside parentheses (...) or brackets [...], because these cannot contain multiple statements anyway.
引自Scala - The rules of semicolon inference.
规则 #1 也是 Go 的工作方式。规则 #3 也是。唯一的区别是规则 #2——它涉及单一前瞻,因为涉及一个标记 ("word")。
涉及哪种性能损失:慢 1%、5%、10%?
我很想看到评论(不是问题)为什么 Go 设计者遗漏了这条规则——如果不是为了性能,它使语言更可靠,例如在方法中链接:
x = some_object.select(...)
.sort(...)
.reverse(...)
.where(...)
.single()
如果我没有误认为 Go 是一个错误(你可以通过两种可能的方式解决它——将整个语句放在大括号中或将表达式放在括号中,但这是手动调整),Scala 会按原样处理.
与编译器必须做的其他事情相比,性能损失完全可以忽略不计。 Scala-internals 邮件列表在 Haoyi Li 和 Martin Odersky 之间就 Haoyi 为 Scala 编写的 parboiled2 解析器进行了以下交流:
Haoyi Li: In terms of perf[ormance], it can parse everything in scala/scala, lift, scalaz, scalajs, playframework and shapeless in 15 seconds.... Does anyone know how much of the time in the compiler and macros is spent parsing? My impression is that the vast vast vast majority of the time is spent in the typechecker.
Odersky: Yes, parsing is pretty insignificant compared to the other tasks of a compiler ... That said, the [parser for the next-generation Scala compiler] (hand-written, 2100 lines including error reporting, accurate positions and tree construction) achieves several hundred thousand lines a second. So parboiled still has some way to go to beat that :-)
当我们谈论每秒解析数十万行代码时包括规则 #2,可以推断速度不是问题。 Go 编译往往以每秒 around 20k lines 的速度进行,所以即使 Go 解析花费了零时间,而 Scala 解析的 整个 时间都被单行前瞻占用了, 对构建过程的惩罚不到 10%。
实际上它应该更接近 0%。 Lookahead 通常非常便宜;你已经有了一个令牌流,所以你只看下一个。
似乎如果行以除语句以外的任何内容开头,编译器会报错。你也可以在 Go https://play.golang.org/p/h8NYnBXjFI
中链接方法
在比较Go和Scala的语句结束检测时,我发现Scala的规则更丰富,即:
A line ending is treated as a semicolon unless one of the following conditions is true:
- The line in question ends in a word that would not be legal as the end of a statement, such as a period or an infix operator.
- The next line begins with a word that cannot start a statement.
- The line ends while inside parentheses (...) or brackets [...], because these cannot contain multiple statements anyway.
引自Scala - The rules of semicolon inference.
规则 #1 也是 Go 的工作方式。规则 #3 也是。唯一的区别是规则 #2——它涉及单一前瞻,因为涉及一个标记 ("word")。
涉及哪种性能损失:慢 1%、5%、10%?
我很想看到评论(不是问题)为什么 Go 设计者遗漏了这条规则——如果不是为了性能,它使语言更可靠,例如在方法中链接:
x = some_object.select(...)
.sort(...)
.reverse(...)
.where(...)
.single()
如果我没有误认为 Go 是一个错误(你可以通过两种可能的方式解决它——将整个语句放在大括号中或将表达式放在括号中,但这是手动调整),Scala 会按原样处理.
与编译器必须做的其他事情相比,性能损失完全可以忽略不计。 Scala-internals 邮件列表在 Haoyi Li 和 Martin Odersky 之间就 Haoyi 为 Scala 编写的 parboiled2 解析器进行了以下交流:
Haoyi Li: In terms of perf[ormance], it can parse everything in scala/scala, lift, scalaz, scalajs, playframework and shapeless in 15 seconds.... Does anyone know how much of the time in the compiler and macros is spent parsing? My impression is that the vast vast vast majority of the time is spent in the typechecker.
Odersky: Yes, parsing is pretty insignificant compared to the other tasks of a compiler ... That said, the [parser for the next-generation Scala compiler] (hand-written, 2100 lines including error reporting, accurate positions and tree construction) achieves several hundred thousand lines a second. So parboiled still has some way to go to beat that :-)
当我们谈论每秒解析数十万行代码时包括规则 #2,可以推断速度不是问题。 Go 编译往往以每秒 around 20k lines 的速度进行,所以即使 Go 解析花费了零时间,而 Scala 解析的 整个 时间都被单行前瞻占用了, 对构建过程的惩罚不到 10%。
实际上它应该更接近 0%。 Lookahead 通常非常便宜;你已经有了一个令牌流,所以你只看下一个。
似乎如果行以除语句以外的任何内容开头,编译器会报错。你也可以在 Go https://play.golang.org/p/h8NYnBXjFI
中链接方法