VisualC++产品自成立以来就一直有项目。 Visual C++通过Visual Studio 6拥有了自己的IDE。 从VisualStudio.NET开始,C++移到VisualBasic、C++、C++和其他工具共享的新IDE。 这个新的IDE到处都使用COM,解决方案资源管理器中的项都是基于COM的 第四政权 . 许多现有的项目系统保持原封不动,但它是通过一组实现IVsHierarchy和其他接口的新COM对象公开的。
在visualstudio2010中,底层的项目/生成系统是 改变 从VCBuild到MSBuild。 这也是文件扩展名从.vcproj更改为的时候。VCX项目。 此时,保留了现有的一组(相对较新的)COM对象,但将其转发到一组新的托管“填充”对象中,然后将这些对象调用到新的项目系统中。 这个新的项目系统最终被称为visualstudio项目系统(VSPS)。
随着时间的推移,开发人员创建了越来越大的解决方案和项目。 这就产生了一个问题,因为visualstudio加载这些不断增加的解决方案的时间越来越长。 每个项目都会被解析,并在内存中创建一个大型对象图并保存在内存中。 层次结构中的每个节点至少会创建一个对象。 这种方法需要大量的时间和占用大量的内存。 visualstudio试图跟上并实施了各种策略来支持大型项目。 例如,您可以显式卸载项目以防止它们被加载和ASL( 异步解决方案加载 )在Visual Studio 2013中引入。 ASL尝试在后台线程上加载大多数项目,并使UI立即响应其他任务。
虽然ASL在很大程度上可以工作,但我们从许多开发人员那里听说,他们更喜欢在尝试使用IDE之前等待整个解决方案完成加载和所有其他后台工作完成。 你知道,打开你的解决方案去喝咖啡。
即使在所有的项目都被加载之后,仍然有其他事情正在发生,那就是使用CPU和磁盘。 在状态栏中,您可能习惯于看到以下内容:
这个消息意味着我们正在进行我们称之为“设计时构建”的工作。 VSP正在评估项目,弄清楚要建什么和怎么建。 我们这样做是为了为每个项目中的每个文件生成命令行,然后将它们与存储在 浏览数据库 . 如果它们发生了变化,我们将它们写入数据库。 命令行用于Intellisense,也用于解析在浏览数据库中索引的包含文件。
在这个“初始化”阶段之后,您将看到我们正在检查过期的文件(然后在需要时更新它们)。 最后,状态栏显示就绪。 然而,如果您查看任务管理器,您会注意到一个CPU仍然被大量使用。 在后台,我们还在做工作。 第一个任务是填充每个项目的“外部依赖项”节点。 此节点包含项目中未显式包含但由项目中的某个文件直接或间接包含的文件。 在这个步骤之后,还有一个不可见的步骤检查数据库中的孤立记录,例如我们索引的文件,这些文件不再被任何项目(直接或间接)使用。 所有这些都会在每次打开解决方案时发生,即使自上次使用该解决方案以来完全没有任何变化。
让我们看看如何加载铬溶液,看看在VisualStudio2015 Update 3 vs。 Visual Studio 15预览版5 . 如果你遵循 Chromium网站上的说明 ,解决方案由命令“gn gen–ide=vs outDefault”生成。 这将导致约4600个项目,其中约1000个是“解决方案文件夹”,其他项目是.vcxproj项目。
以下结果是在我的个人计算机上的Windows10上得到的,这台计算机是Intel Core i7-4790@3.6GHz和两个SSD:一个作为系统驱动器,一个作为源代码(Samsung 850 Pro)。 第一组结果在Visual Studio 2015 Update 3中,第二组结果来自 Visual Studio 15预览5 .
我们意识到“解析/解析包含”阶段比VS2015 Update 3慢25%。 我们也在努力改善这一点,并期望很快得到解决。
为什么visualstudio“15”的解决方案加载速度要快得多?
由于我们现有的分层体系结构,插入一个新的缓存层比较容易,它可以回答有关项目和配置的许多问题,而不必将项目实际加载到vsp中。 这个新层使用SQLite数据库按需快速检索信息。
当一个解决方案被加载并且我们被要求加载一个C/C++项目时,我们得到了这个解决方案将加载的所有.vcxProjl文件的列表。 我们检查数据库,看看我们是否已经有这些项目,如果有任何文件已经改变。 如果我们需要更新关于一组项目的信息,那么这些项目就会被放入一个队列中。 该队列由多个外部进程处理,这些进程使用MSBuild加载项目并收集有关项目的信息并将其写入数据库。
当我们被要求加载每个项目时,我们创建了一组小的填充对象,这些对象可以为许多请求提供服务,而无需完全加载项目。 我们可以提供Intellisense引擎所需的所有信息,也可以通过数据库中的信息提供解决方案资源管理器所需的信息。 如果调用的API需要一个真实的项目(比如修改项目设置),那么底层填充程序将动态加载项目并委托给它。
由于这种变化,单个项目的加载时间下降了很多,但没有我们期望的那么低。 分析揭示了一些非常糟糕的算法,在不同的地方有N^2的时间复杂度。 在这个改变之后,我们的内存使用也急剧下降,但是我们在自己的对象中也发现了一些非常糟糕的内存使用。 我们能够将解决方案中表示文件的每个对象(包括外部依赖项)的大小从每个实例120字节缩减到44字节。 看起来不多,但一些大型解决方案最终会有数百万个这样的对象。 我们仍在努力改进projectload的性能,我希望在发布最终版本之前看到一些额外的改进。
此功能是 真正的实验性 ,在快速项目加载方面仍有一些问题需要您注意。
- 需要升级的项目应该先升级,然后再尝试对它们使用快速项目加载,因为升级不会在FPL期间发生。
- 我们今天的故事是能够建立并没有完成这个预览版本。一个项目可能会构建非常简单的解决方案,但基本上就是这样。
- 项目将按需通过VSP加载,例如在显式编辑项目时(例如添加文件或更改属性)。 一个大的项目可能需要几秒钟才能加载。 我们想向用户发出这个信号,但我们还没有在所有情况下。
- 第三方插件可以选择遍历整个解决方案层次结构,要求属性将所有项目完全加载到vsp中,从而有效地破坏FPL的任何好处。
每当一个项目被完全加载到vsp中时,IDE的输出窗口就会显示一条消息。 如果您意外地看到这些消息,请通知我们。
轻量级解决方案负载
在visualstudio中,还有另一项实验工作正在进行,以改进解决方案负载,称为“轻量级解决方案负载”。 您可以启用此功能 使用以下选项。
这是一种完全不同的方法,您可以在visualstudio博客上阅读 在这里 . 通常,它将完全避免加载项目,并且只在用户在解决方案资源管理器中显式展开项目时加载项目。 C++团队一直专注于快速的项目负载,因此我们对轻量级解决方案负载的支持目前是最小的。 在RC中 释放 Visual Studio 15 ,我们希望结合轻量级解决方案负载来支持FPL。 这种结合应该会提供很好的体验。
总结
一如既往,我们欢迎您的反馈,我们很乐意在您尝试这些功能时从您的经验中学习。如果您在尝试快速加载解决方案时遇到任何问题,请务必通知我们 报告问题工具 .