Uma noite, enquanto discutia as dificuldades de desenvolver um linter para PHP em Go com Iskander @quasilyte , Iskander mencionou que os testes demoram muito quando executados localmente (cerca de um minuto, e me parece que para Go é muito longo). Começamos a cavar e rapidamente ficou claro que os testes que executam NoVerify (o nome do linter) no modo com o detector de corrida ligado estão principalmente "diminuindo a velocidade" . O repositório phpstorm-stubs é indexado para cada lançamento, que contém todas as definições de funções / classes / constantes integradas que estão no PHP, e a indexação desse repositório leva cerca de 4 segundos em uma máquina de 4 núcleos (observe que sem um detector de corrida tudo é muito mais rápido). Como existem várias execuções, uma para cada projeto de código aberto testado, o tempo total de execução de todos os testes pode levar minutos. NoVerify se posiciona como um linter muito rápido para PHP, então, é claro, esse desempenho é um pouco triste e era necessário encontrar uma solução.
Arquitetura NoVerify
Para começar, ainda vale a pena falar um pouco sobre como funciona o NoVerify. O trabalho do linter divide-se em duas grandes fases: indexação e análise direta.
A indexação do projeto significa que as definições e tipos de todas as funções, classes, métodos, constantes e variáveis globais são extraídos de todos os arquivos PHP, e todas essas informações são armazenadas na RAM para acesso rápido. Além disso, essas informações são salvas no cache do disco no formato gob para evitar a necessidade de analisar todo o projeto todas as vezes. É importante que mesmo para analisar um único arquivo, todo o projeto deve estar indexado, porque se houver um carregamento automático para classes em PHP, então não existe tal coisa para funções, constantes e ainda mais variáveis globais, e elas podem ser definidas em qualquer lugar. Claro, em projetos PHP modernos, normalmente apenas classes são usadas e tais problemas não surgem, mas para projetos com uma longa história isso ainda é relevante. A necessidade de indexar todo o projeto para sua análise foi o motivo de escrever NoVerify em Go, uma vez que esta linguagem suporta multithreading bem, o que significa que será capaz de indexar o projeto muito mais rápido do que é possível em 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 , .