Un soir, tout en discutant des difficultés de développement d'un linter pour PHP en Go avec Iskander @quasilyte , Iskander a mentionné que les tests prennent beaucoup de temps lorsqu'ils sont exécutés localement (environ une minute, et il me semble que pour Go c'est assez long). Nous avons commencé à creuser, et il est rapidement devenu clair que les tests qui exécutent NoVerify (le nom du linter) dans le mode avec le détecteur de course activé sont principalement "ralentissant" . Le dépôt phpstorm-stubs est indexé à chaque lancement, qui contient toutes les définitions des fonctions / classes / constantes intégrées en PHP, et l'indexation de ce référentiel prend environ 4 secondes sur une machine à 4 cœurs (notez que sans détecteur de course, tout est beaucoup plus rapide). Comme il existe plusieurs exécutions de ce type, une pour chaque projet open source testé, le temps total d'exécution de tous les tests peut prendre quelques minutes. NoVerify se positionne comme un linter très rapide pour PHP, donc, bien sûr, cette performance est un peu triste et il a fallu trouver une solution.
Architecture NoVerify
Pour commencer, cela vaut toujours la peine de parler un peu du fonctionnement de NoVerify. Le travail de Linter est divisé en deux grandes phases: l'indexation et l'analyse directe.
L'indexation de projet signifie que les définitions et les types de toutes les fonctions, classes, méthodes, constantes et variables globales sont extraits de tous les fichiers PHP, et toutes ces informations sont stockées dans la RAM pour un accès rapide. En outre, ces informations sont enregistrées dans le cache sur le disque au format gob pour éviter d'avoir à analyser l'intégralité du projet à chaque fois. Il est important que même pour analyser un seul fichier, l'ensemble du projet soit indexé, car s'il y a un chargement automatique pour les classes en PHP, alors il n'y en a pas pour les fonctions, les constantes et plus encore les variables globales, et elles peuvent être définies n'importe où. Bien sûr, dans les projets PHP modernes, seules les classes sont généralement utilisées et de tels problèmes ne se posent pas, mais pour les projets avec une longue histoire, cela reste pertinent. C'est la nécessité d'indexer l'ensemble du projet pour son analyse qui a motivé l'écriture de NoVerify in Go, car ce langage supporte bien le multithreading, ce qui signifie qu'il sera capable d'indexer le projet beaucoup plus rapidement que ce n'est possible en 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 , .