30

多年前有人问为什么 c# 不允许像 Java 这样的增量编译。El Skeet 说这与 Java 输出 .class 文件而不是程序集有关。

既然它的 2011 年和诸如 Mono 编译器即服务之类的时髦的东西已经发布,那么需要做些什么来为 c# 制作增量编译器?

编辑:对于每个都在谈论这不是问题的人,这是我链接到的线程中 Jon Skeet 的引述:

你是说你永远不会发现自己在等待构建吗?甚至15秒?如果构建需要 15 秒,而您想在一小时内构建 20 次(我当然会使用 TDD),这意味着我浪费了 5 分钟。休息 5 分钟是一回事——这是一种很好的放松方式等——但被耽搁 15 秒 20 次可能会非常令人沮丧。它不足以做任何有用的事情(除了可能喝一杯),但它足够长到刺激。

我怀疑有两个因素会导致我觉得其他人显然没有的烦恼程度:1)TDD 确实依赖于更快的周转时间 2)在 Eclipse 中使用 Java 时,这种延迟非常罕见

4

1 回答 1

11

如果没有这样做,那么只有一个原因:努力做到这一点高于可能的收益。

微软肯定不会这样做,因为成本太高:.net 代码存在于程序集中,没有人会改变它。是的,程序集会阻止逐类增量编译。没有人会停止使用程序集。

这是我的答案,为什么没有人需要它。您可以将构成单个项目的类分布在几个程序集中并一一编译。它实际上是增量编译,但不像逐类增量编译那样细粒度。如果您的架构设计得当,汇编级增量编译就足够了。

编辑:好的,我下载了 Mono C# 编译器来看看是否可以使其增量。我认为这不是很难。基本上它执行以下步骤:1)解析文件2)编译3)创建程序集。您可以在编译类型后挂钩某个位置,然后将其保存到某种中间文件中。然后只重新编译改变的。所以这是可能的,但看起来这不是 Mono 团队的高优先级问题。

编辑 2:我发现了这个有趣的线程,人们在其中讨论 Mono C# 编译器的增量编译。它相当古老,但关键解释可能仍然有效:

词法分析和解析通常非常快,并且仅取决于要解析的代码的大小。语义分析通常是最耗时的步骤,因为加载引用的程序集并筛选大量元数据以解析符号和类型确实是编译器的核心,此外,新的“编译”代码“附加”到此元数据/AST 增加了什么随着时间的推移解析符号的复杂性。代码的发射首先在内存中完成,因此速度很快。保存到磁盘很慢,但取决于发出的代码大小。

对于增量编译,缓存元数据会使一切变得非常快,因为通常很少会从一个编译到另一个编译。但是 gmcs 必须只使元数据/AST 的一部分无效,它不是为.

编辑 3:C# 编译器/incremental在 v1.0 和 v1.1 中有选项,但它已被删除

在 C# 编译器的 1.0 和 1.1 版本中找到的 /incremental 标志现在被认为已过时。

编辑 4:Miguel de Icaza 给出了明确的答案(1、2)为什么 Mono 编译不会是增量的:

还有很多很多地方 GMCS 并非设计用于编辑和继续场景。

如果有人想把这个作为他们的论文主题,我没问题,但是在太多领域的变化太大了。我什至不想费心列举它们。

我没有列出的原因是因为它们在编译器中无处不在。相信您一尝试就会遇到它们;-)

所以他认为这是一项比一个人的论文更艰巨的任务。而 Mono 有更多的突出和实际的任务。

于 2011-03-31T15:59:25.767 回答