go x/tools/imports:支持在Process和FixImports中进行会话以提高性能

eimct9ow  于 4个月前  发布在  Go
关注(0)|答案(7)|浏览(51)

提案详情

某些工具链,如Ent,在循环中大量使用imports.Process(...)来格式化目录中的多个文件。然而,由于每次调用Process本身也会通过parseOtherFiles在目录中的多个文件上执行循环,因此在这个用例中,复杂度可能达到O(N^2)。
因此,这个提案的目的是引入对传递给Process的session对象的支持:

func Process(s *Session, filename string, src []byte, opt *Options) (formatted []byte, err error) {
   ...
}

会话将是一个LRU缓存的轻量级 Package 器,它可以使用现有的LRU功能(可以轻松地将其重新定位到internal/lru):

type Session struct {
	Cache *lru.Cache
	Fset  *token.FileSet
}

用法如下:

s := NewSession(10) // 10 MB cache
return Process(s, file, contents, opts)

LRU键类似于(file path, file contents),值是解析后的AST。这将有助于防止对parse的重复调用导致显著的性能开销。
允许会话为nil以支持当前用例。

hkmswyz6

hkmswyz61#

x/tools/internal 是一个不可见的API,因此无需经过提案过程。

mkh04yzy

mkh04yzy2#

CC @golang/tools-team

egdjgwm8

egdjgwm83#

这是我的错误,它也会影响x/tools/imports(非内部)的API。x/tools/imports有一个名为Process的函数,它调用了x/tools/internal/imports中的另一个名为Process的函数。

vxqlmq5t

vxqlmq5t4#

修订:缓存不再作为第一个位置参数传递给Process,而是通过现有的opt *Options参数作为Options中的一个字段传递。这将允许现有代码保持不变,因为值将默认为nil

falq053o

falq053o5#

cc @findleyr,最近一直在从事导入工作。我们一直在讨论一个可能的导入API,该API允许将读取/解析/推断/修复/格式化操作表示为具有不固有依赖于外部状态的可组合函数。目前我称之为“推断”的步骤是运行模块解析器,针对GOMODCACHE生成和排名候选项;许多客户端(包括gopls)希望能够将这一步骤钩入他们自己的数据结构中,以获得更确定或可定制的行为。(GOMODCACHE是用户以前习惯的积累。)

lf3rwulv

lf3rwulv6#

@pjweinb 实际上正在研究goimports。
确实,这听起来可能与gopls的需求相符。
我在#59216中研究了goimports的性能,虽然我为gopls做了一些改进,但我也得出结论,goimports的扫描和解析应该从头开始重新思考。在gopls内部,我们重用了internal/imports.ProcessEnv,但我认为修复的方法不是从x/tools/imports中暴露出该类型--我们应该提出一个更简单的新API。
这个新API的一个要求是,gopls本身可以作为输入提供包信息给goimports算法。现在,包解析隐藏在一个(相当复杂的)Resolver类型后面,它有自己的模块缓存扫描启发式方法,可能与gopls关于要导入的最佳包或模块不一致。参见#36077

inn6fuwd

inn6fuwd7#

@adonovan@findleyr 正在发生令人兴奋的事情。听起来有很多范围,我想知道它是否与优化当前流程是单独的任务?(这个工单只是为了记忆现有的逻辑。)

相关问题