提案详情
某些工具链,如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以支持当前用例。
7条答案
按热度按时间hkmswyz61#
x/tools/internal 是一个不可见的API,因此无需经过提案过程。
mkh04yzy2#
CC @golang/tools-team
egdjgwm83#
这是我的错误,它也会影响
x/tools/imports
(非内部)的API。x/tools/imports
有一个名为Process的函数,它调用了x/tools/internal/imports
中的另一个名为Process的函数。vxqlmq5t4#
修订:缓存不再作为第一个位置参数传递给
Process
,而是通过现有的opt *Options
参数作为Options
中的一个字段传递。这将允许现有代码保持不变,因为值将默认为nil
。falq053o5#
cc @findleyr,最近一直在从事导入工作。我们一直在讨论一个可能的导入API,该API允许将读取/解析/推断/修复/格式化操作表示为具有不固有依赖于外部状态的可组合函数。目前我称之为“推断”的步骤是运行模块解析器,针对GOMODCACHE生成和排名候选项;许多客户端(包括gopls)希望能够将这一步骤钩入他们自己的数据结构中,以获得更确定或可定制的行为。(GOMODCACHE是用户以前习惯的积累。)
lf3rwulv6#
@pjweinb 实际上正在研究goimports。
确实,这听起来可能与gopls的需求相符。
我在#59216中研究了goimports的性能,虽然我为gopls做了一些改进,但我也得出结论,goimports的扫描和解析应该从头开始重新思考。在gopls内部,我们重用了internal/imports.ProcessEnv,但我认为修复的方法不是从x/tools/imports中暴露出该类型--我们应该提出一个更简单的新API。
这个新API的一个要求是,gopls本身可以作为输入提供包信息给goimports算法。现在,包解析隐藏在一个(相当复杂的)Resolver类型后面,它有自己的模块缓存扫描启发式方法,可能与gopls关于要导入的最佳包或模块不一致。参见#36077。
inn6fuwd7#
@adonovan@findleyr 正在发生令人兴奋的事情。听起来有很多范围,我想知道它是否与优化当前流程是单独的任务?(这个工单只是为了记忆现有的逻辑。)