一天晚上,在讨论使用Iskander @quasilyte在Go中为PHP开发一个linter的困难时,Iskander提到测试在本地运行需要很长时间(大约一分钟,在我看来,Go相当长)。我们开始进行挖掘,很快就发现,在打开种族检测器的模式下运行NoVerify(短绒的名称)的测试主要是“慢下来” 。每次启动都会为phpstorm-stubs存储库建立索引,其中包含PHP中内置函数/类/常量的所有定义,并且在4核计算机上对该存储库建立索引大约需要4秒钟(请注意,如果没有竞争检测器,一切都会更快)。由于有多个这样的运行,每个测试的开源项目一个,因此所有测试的总执行时间可能需要几分钟。NoVerify将自己定位为PHP的非常快速的学习者,因此,这种性能当然让人有些难过,因此有必要找到一些解决方案。
NoVerify体系结构
首先,还是值得谈论一下NoVerify的工作原理。皮特工作分为两个主要阶段:索引编制和直接分析。
项目索引意味着从所有PHP文件中提取所有函数,类,方法,常量和全局变量的定义和类型,并将所有这些信息存储在RAM中以便快速访问。该信息也以gob格式存储在磁盘上的高速缓存中,以避免每次都需要解析整个项目。 即使分析单个文件,也必须对整个项目建立索引,这一点很重要。,因为如果PHP中有自动加载类的功能,则函数,常量甚至全局变量都没有这种功能,并且可以在任何地方定义它们。当然,在现代PHP项目中,通常仅使用类,并且不会出现此类问题,但是对于历史悠久的项目而言,这仍然很重要。在Go中编写NoVerify的原因是需要对整个项目进行索引,这是因为该语言很好地支持多线程,这意味着它将能够比在PHP中更快地对项目进行索引。
既可以对选定文件(例如,在当前提交中已更改的文件)也可以对整个项目进行分析。在第一种情况下,分析所花费的时间少于建立索引所花费的时间,有时花费的时间很多(如上面的测试示例所示,对phpstorm-stubs进行索引需要90%以上的时间)。该分析使用有关所有声明的函数/类/方法的类型的信息,这些信息是在索引阶段收集的。
加快phpstorm-stubs索引编制
, , , , phpstorm-stubs, , , «» (.. ) // PHP, 25% , , . , : phpstorm-stubs «» , , , , , , .., , .
«» :
, . , phpstorm-stubs .
phpstorm-stubs , , .
, gob.
, phpstorm-stubs , Go- phpstorm-stubs . , , , 2-3 .
, (2), . , (1), , , . , , Go phpstorm-stubs ~200 (.. 20 ), , 18 , , .
?
, golden- , , , - . , , phpstorm-stubs. , -.
, ( Laravel, composer create-project --prefer-dist laravel/laravel blog
, 1.6 PHP) 450 ( 4 ), NoVerify , , , , language server.
/
Go- 1.6 20-60 , , , , . .
: noverifyturbo 20 100 , ~80 1.6 PHP-.
, - NoVerify, , NoVerify. , .
-
: , Go- fmt.Printf("%#v", value)
.
, , , , GoStringer(), .
PHP- Go-, map[string]func()*PerFileCache
, ( PHP- , , ), , PHP-. , , , , map ( - , ), , , , map , .
+ , , - stat() , .
Laravel 1.6 , composer create-project --prefer-dist laravel/laravel blog
, :
, 1 : 4
-, 1 : 400
, 12 : 1 (10 )
-, 12 : 240 (800 )
, - , , - map , , . , - , , .
— , , , , ( Google, ).
NoVerify Go, , phpstorm-stubs «» . . , , NoVerify workflow , PHPStorm VS Code , .
NoVerify — PHP .
phpstorm-stubs — «» PHP .