Nickzhu微软开发部门高级项目经理大家好,欢迎来到最新的VisualStudioCodeJava更新!在本文中,我们将深入探讨最近针对代码完成的性能优化。性能改进-更快的代码完成在最近发布的Java语言服务器1.0版本中,我们对代码完成的性能进行了重大改进。下图比较了最近版本之间的代码完成响应时间。对于补全类型、构造函数名称等常见场景,代码补全性能较之前版本(v0.80、v0.81、v.0.82)有明显提升。性能改进概述代码完成引擎包括三个阶段:阶段1(P1)–在索引器中搜索建议阶段2(P2)–将建议转换为完成阶段3(P3)–根据我们的分析计算代码片段建议,我们在所有三个阶段都发现了改进的空间。下表显示了我们在过去版本中所做的改进。我们将在下一节中更详细地讨论这些更改的细节。关键更改详细信息版本0.81.0-减少WindowsI/O操作。#1831在以往的性能测试中,我们发现很大一部分时间成本都花在了文件URI的计算上。这一发现证实了我们之前的观察,即由于JVM中特定于平台的文件系统相关实现,Windows平台上的代码完成性能相对较差。我们通过删除不必要的URI计算提高了性能,尤其是在Windows平台上。版本0.81.0-常量/默认值的优化。#1835当我们完成常量字段(例如Constants.*)时,完成弹出窗口将在选择列表中显示建议的字段名称及其常量值(例如Bit1:int=1)。我们的分析发现,当类包含大量常量字段成员时,这会导致完成速度非常慢。这是因为我们从ASTTree计算字段值,这在对大文件进行操作时开销很大。为了优化它,我们决定推迟解析常量值。代码完成简化了建议的标签并仅显示字段名称(例如Bit1:int)。当您将鼠标悬停在Javadoc完成项上时,其常量值将显示在Javadoc部分中。下面是一个具有1400多行和150多个常量字段的类的字段完成的性能比较。版本0.82.0-延迟解析通用片段。#1838有两种类型的代码片段:通用代码片段(例如foreach、fori、ifelse等)和通用代码片段的类型定义代码片段(例如类、接口等),它在构建完成之前使用给定的上下文评估模板item的“TextEdit”,这样的评价可贵了。我们现在将此类评估推迟到解决阶段。创建代码完成项时,模板模式将作为占位符填充。实际值在求解阶段进行评估,这不会阻止显示已完成的项目。这也是一个关于“惰性解析TextEdit”能在多大程度上提高性能的实验,在大多数情况下,它应该可以正常工作。版本0.82.0-优化匿名构造函数优化匿名构造函数。#1836当我们要完成一个新的Runnable时,预期结果是这样的:Runnable(){}它由两部分组成Runnablenameblankbodyfragmentbody(){\n\t\n}通过profiling,我们发现CodeFormatUtil.format需要很多时间。它们被格式化为当前首选项,以便具有正确的缩进和行分隔符。格式化是昂贵的,并且相同的内容(空主体)会为所有项目(有时多达数千个)重复格式化。为了改进它,我们将空卷格式设置为一次性操作,并在所有项目中重复使用。版本1.0.0-改进的代码完成搜索速度为了优化索引搜索性能,我们进行了两个关键更改。使索引搜索任务更有效率。#1846、#575562我们的性能分析表明,索引查询任务97%的CPU时间花在了从磁盘加载索引内容的I/O操作上。这是因为我们使用的索引机制倾向于节省内存并且在搜索引擎中使用很少的缓存。几乎每个查询都必须从磁盘重新加载索引内容。一个直接的优化是降低I/O的频率。一个Java索引器由多个哈希表组成,每个哈希表用于记录某一类代码段,如类型声明、方法声明、引用、方法引用等。典型的查询作业从索引中读取一个或多个哈希表,然后将这些索引条目连接到目标结果中。当我们完成类型/构造函数名称(例如Str或newStr)时,索引查找作业会读取两个哈希表,一个是用于查找匹配类型名称的typeDecl表,另一个是用于查找类文件路径的documentName表声明了对应的类型。由于我们的目的只是补全类型名,自动导入对应的包,所以typeDecl表足以满足我们的要求,不需要类文件路径。我们的优化是只读typeDecl索引表,事实证明少读一张索引表可以节省很多I/O开销。优化索引读取操作。#574464此更改来自社区开发人员对上游JDT项目的贡献。Java索引使用UTF-8编码索引字符。我们在加载索引时将它们解码回来。由于大多数索引字符只是ASCII字符,我们优化了解码方法以使其更快地读取ASCII。未来计划我们上面列出的改进使自动完成速度更快,但我们还没有完成。未来,性能仍然是我们的首要任务,我们将继续优化自动完成性能。以下是我们计划在接下来几个月进行的一些项目:LazyResolveTextEdit由于大多数语言客户端不支持完成的延迟解析文本编辑,因此Java语言服务器必须在完成响应文本编辑器中计算所有完成的值。这是最昂贵的计算的原因。我们正在与作者合作探索对延迟解析文本编辑的支持。MoreEfficientIndexArchitectureMoreEfficientIndexer目前的索引数据对于构造函数等一些代码补全场景来说还不够。例如,构造函数完成需要知道类是否有泛型类型参数,并决定是否在构造函数引用中添加菱形<>。构造函数索引表不包含此类类型参数信息,我们必须从Java模型中对其进行解析,而此类解析操作开销很大。我们正在考虑优化索引架构以包含更多信息。反馈与建议请积极使用我们的产品!您的反馈和建议对我们非常重要,将帮助我们做得更好。有几种方式可以给我们反馈:填写中文问卷在本文下方留言在我们的GitHubrepo上创建Issue资源以下链接和资源可以帮助您更好地了解VisualStudioCode上的Java相关信息了解更多关于Java的更多信息VisualStudioCode一步步探索VisualStudioCodeJava教程欢迎关注微软中国MSDN订阅号获取更多最新资讯!
