使用VB/ c#诊断分析器/CodeFix/自动更新多个.vsix会导致性能问题吗?
本文关键字:vsix 问题 性能 更新 诊断 VB 分析器 CodeFix 使用 | 更新日期: 2023-09-27 18:17:32
我正在实现一个系统,它将实现代码质量作为内部质量度量的一部分。我以两种可能的实现方式构建了系统,如下所示:
实现1:(已经实现)
- 自动更新扩展(Stub)c# CodeQualityPlugin (Roslyn c#诊断分析器)代码修复)
- VB CodeQualityPlugin (Roslyn VB诊断分析仪)代码修复)
autouupdate功能通过验证其版本号来检查自身和其他CodeQuality插件的任何更新。一旦CodeQuality插件更新,它将在接下来的7天内停止更新。
这是目前我对实现的想法,但是开发被停止了,理由是可能与此实现中的扩展数量有关的性能问题,并且可能存在Visual Studio在其使用/性能方面的限制(正如团队所提到的)
实现2:(建议)
- c# CodeQualityPlugin (Roslyn c#诊断分析器,代码修复,自动更新)
- VB CodeQualityPlugin (Roslyn VB诊断分析器,代码修复,自动更新)
在这种情况下,更新功能是单独触发的,并保持单一责任哲学。
我不确定AutoUpdate项目(使用菜单命令模板)和c#/VB CodeFix/DiagnosticAnalyzer项目(Roslyn模板)是否可以共存?
实现3:(意见之一)
- CodeQualityPlugin (Roslyn c#/VB诊断分析器,代码修复,自动更新)
我甚至不确定这三个是否可以在一个vsix中共存。
所以我的问题是,在上述三种情况下,性能问题可能是什么,以及我们如何将基于Roslyn模板开发的插件实现为visual studio的普通菜单命令模板扩展。
——编辑——需求总结如下
-
共存: VSPackage扩展(扩展Visual Studio的shell命令组件)和Managed Extensibility Framework/MEF扩展(自定义和扩展编辑器以包含Roslyn DiagnosticAnalyzer/CodeFix),应该共存于
- 单一VSIX
- 最大2个vsix
-
Performance:共存不应影响性能,VSPackage扩展处理的自动更新不应创建冗余的服务调用
No
唯一真正的"性能问题"你可以把c#和VB的在同一个程序集中(注意,不是VSIX),这意味着当我们必须加载一个我们加载其他。
从MEF的角度来看,我们只是得到一个导出列表:我们不知道它们来自哪些vsix,即使我们想要弄清楚也很难弄清楚。因此,您将内容放入哪个VSIX并不重要:根据对您的用户有意义的内容对它们进行划分。
Roslyn和VSIX包装的注意事项:
如Srivatsn所述
-
同时引用
Microsoft.CodeAnalysis.CSharp
和Microsoft.CodeAnalysis.VisualBasic
的扩展名将- 加载两个编译器,即使我们试图打开一个c#项目,这不是理想的。
-
如果我们必须分析符号
ISymbolAnalyzer
,其中您只分析符号而不是语法节点,那么我们应该采用单一语言无关的分析器。这意味着我们不必引用任何c#/VB dll (甚至微软也在考虑实现更多与语言无关的分析器)。包括两个导出属性——每种语言一个,这些属性告诉VS在解决方案中包含相应的语言时实例化并调用这些分析器。 -
编译作为一个进程在编译完成后离开内存,但是由于几乎在每次击键时都发生编译,并且如果分析器同时引用c#和VB,它将把两个编译器都带入内存。由于存在持久性特性,如果在解决方案下存在大型项目(这是我的典型生产场景)
,则可能会出现问题。 在调用相应的语法方法时加载编译器还是在导出的分析器的实例化时加载编译器(再次通过MEF导出属性通过提到相应的语言用例进行过滤)存在混淆,因为他还提到如果引用两种语法节点的方法可能会使JIT编译并加载dll。
任何链接到菜单命令的分析器都将是VS特定的,如果它们链接到项目,那么它也将参与构建,即使在VS之外通过MSBuild
VSIX应该能够导出多个组件来扩展这两个扩展点。
正如VSadov提到的
- 语法树数据结构的持久性和每次击键都需要重新进行分析(增量编译:这就是Srivatsn的编译意味着)使他们设计了红绿树方法,这有助于增量编译的性能。
- MEF导出是否打包在单个VSIX中没有任何区别(,但应该注意的是,将两个类型分析器合并到一个MEF导出程序集中存在性能问题)
正如Kevin Pilch提到的
- 尽管这些程序集被打包在哪里并不重要,除非它们在涉及特定语言引用时是分开的。
- 如果分析器同时引用c#和VB特定的Roslyn程序集,并且这些编译程序集很大,则将保留虚拟内存
- 性能问题是磁盘加载和JIT成本(我不确定如何有一个JIT成本,如果没有编译,只有引用在它),但由于有一个地址空间保留可能有一个问题在VS (我不确定这将如何成为一个问题。)
根据他的说法,微软所做的是创建三个项目来处理这个问题(根据Srivatsn,微软仍在尝试开发与语言无关的分析器)
- 共享(没有特定于语言的二进制文件)
- c#专用(+共享库)
- VB Specific (+共享库)
如果没有特定于语言的二进制文件被引用,如果MEF导出适当地归因于
ContentType
或LanguageName
,那么上述问题可以解决- 我们可以将额外的程序集捆绑到一个VSIX中(通过将其他项目嵌入其中), VS将独立加载每个
最终实现:
所以最后我和我的团队讨论后得出了如下结论
- 通过在其中嵌入以下项目来实现单个VSIX
- 更新插件
- 检查过去7天内是否有更新
- 然后通过JSON请求从服务器端检查Plugin的版本号
- 然后从服务器下载插件,将下载日期存储在VS设置中用于初始检查
- 禁用前一个插件
- 卸载之前的插件
- 安装新插件
- 此功能在以下情况触发
- VS负载
- 手动菜单命令(应该覆盖下载日期检查)
- c#插件
- 实现并引用c# 的规则
- VB插件
- 实现并引用VB 的规则
- 更新插件