Skip to content

Commit

Permalink
perf: change index to a tree to speed up completion (#680)
Browse files Browse the repository at this point in the history
Refactors Index into a tree structure, rather than an array of Fqns to definitions.

Closes #274
  • Loading branch information
MichaelBelgium authored and felixfbecker committed Nov 11, 2018
1 parent 18c6ccd commit 24388bc
Show file tree
Hide file tree
Showing 16 changed files with 945 additions and 242 deletions.
89 changes: 89 additions & 0 deletions benchmarks/completion.php
@@ -0,0 +1,89 @@
<?php

namespace LanguageServer\Tests;
require __DIR__ . '/../vendor/autoload.php';

use Composer\XdebugHandler\XdebugHandler;
use Exception;
use LanguageServer\CompletionProvider;
use LanguageServer\DefinitionResolver;
use LanguageServer\Index\Index;
use LanguageServer\PhpDocument;
use LanguageServer\StderrLogger;
use LanguageServerProtocol\Position;
use Microsoft\PhpParser;
use phpDocumentor\Reflection\DocBlockFactory;
use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;

$logger = new StderrLogger();
$xdebugHandler = new XdebugHandler('PHPLS');
$xdebugHandler->setLogger($logger);
$xdebugHandler->check();
unset($xdebugHandler);

$totalSize = 0;

$framework = "symfony";

$iterator = new RecursiveDirectoryIterator(__DIR__ . "/../validation/frameworks/$framework");
$testProviderArray = array();

foreach (new RecursiveIteratorIterator($iterator) as $file) {
if (strpos((string)$file, ".php") !== false) {
$totalSize += $file->getSize();
$testProviderArray[] = $file->getRealPath();
}
}

if (count($testProviderArray) === 0) {
throw new Exception("ERROR: Validation testsuite frameworks not found - run `git submodule update --init --recursive` to download.");
}

$index = new Index;
$definitionResolver = new DefinitionResolver($index);
$completionProvider = new CompletionProvider($definitionResolver, $index);
$docBlockFactory = DocBlockFactory::createInstance();
$completionFile = realpath(__DIR__ . '/../validation/frameworks/symfony/src/Symfony/Component/HttpFoundation/Request.php');
$parser = new PhpParser\Parser();
$completionDocument = null;

echo "Indexing $framework" . PHP_EOL;

foreach ($testProviderArray as $idx => $testCaseFile) {
if (filesize($testCaseFile) > 100000) {
continue;
}
if ($idx % 100 === 0) {
echo $idx . '/' . count($testProviderArray) . PHP_EOL;
}

$fileContents = file_get_contents($testCaseFile);

try {
$d = new PhpDocument($testCaseFile, $fileContents, $index, $parser, $docBlockFactory, $definitionResolver);
if ($testCaseFile === $completionFile) {
$completionDocument = $d;
}
} catch (\Throwable $e) {
echo $e->getMessage() . PHP_EOL;
continue;
}
}

echo "Getting completion". PHP_EOL;

// Completion in $this->|request = new ParameterBag($request);
$start = microtime(true);
$list = $completionProvider->provideCompletion($completionDocument, new Position(274, 15));
$end = microtime(true);
echo 'Time ($this->|): ' . ($end - $start) . 's' . PHP_EOL;
echo count($list->items) . ' completion items' . PHP_EOL;

// Completion in $this->request = new| ParameterBag($request);
// (this only finds ParameterBag though.)
$start = microtime(true);
$list = $completionProvider->provideCompletion($completionDocument, new Position(274, 28));
$end = microtime(true);
echo 'Time (new|): ' . ($end - $start) . 's' . PHP_EOL;
echo count($list->items) . ' completion items' . PHP_EOL;
18 changes: 13 additions & 5 deletions Performance.php → benchmarks/parsing.php
@@ -1,23 +1,31 @@
<?php

namespace LanguageServer\Tests;
require __DIR__ . '/vendor/autoload.php';
require __DIR__ . '/../vendor/autoload.php';

use Composer\XdebugHandler\XdebugHandler;
use Exception;
use LanguageServer\DefinitionResolver;
use LanguageServer\Index\Index;
use LanguageServer\PhpDocument;
use LanguageServer\DefinitionResolver;
use LanguageServer\StderrLogger;
use Microsoft\PhpParser;
use phpDocumentor\Reflection\DocBlockFactory;
use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;

$logger = new StderrLogger();
$xdebugHandler = new XdebugHandler('PHPLS');
$xdebugHandler->setLogger($logger);
$xdebugHandler->check();
unset($xdebugHandler);

$totalSize = 0;

$frameworks = ["drupal", "wordpress", "php-language-server", "tolerant-php-parser", "math-php", "symfony", "codeigniter", "cakephp"];

foreach($frameworks as $framework) {
$iterator = new RecursiveDirectoryIterator(__DIR__ . "/validation/frameworks/$framework");
$iterator = new RecursiveDirectoryIterator(__DIR__ . "/../validation/frameworks/$framework");
$testProviderArray = array();

foreach (new RecursiveIteratorIterator($iterator) as $file) {
Expand All @@ -37,8 +45,8 @@
if (filesize($testCaseFile) > 10000) {
continue;
}
if ($idx % 1000 === 0) {
echo "$idx\n";
if ($idx % 500 === 0) {
echo $idx . '/' . count($testProviderArray) . PHP_EOL;
}

$fileContents = file_get_contents($testCaseFile);
Expand Down
10 changes: 10 additions & 0 deletions fixtures/completion/used_namespace.php
@@ -0,0 +1,10 @@
<?php

namespace Whatever;

use TestNamespace\InnerNamespace as AliasNamespace;

class IDontShowUpInCompletion {}

AliasNamespace\I;
AliasNamespace\;
5 changes: 5 additions & 0 deletions fixtures/symbols.php
Expand Up @@ -103,3 +103,8 @@ class Example {
public function __construct() {}
public function __destruct() {}
}

namespace TestNamespace\InnerNamespace;

class InnerClass {
}

0 comments on commit 24388bc

Please sign in to comment.