Exakat 0.11.0 review
Exakat 0.11.0 (Immortal Ruyi) is out with great new version! This week, Exakat is on composer! A two lines installation is ready for faster usage. And Exakat accelerated the result extraction phase by removing prepared statements : less queries to the database is always faster. Exakat is also suggesting to use str_repeat() instead of loops, and it warns us when using crc32 that it might be negative on certain plat-forms. Read to learn more!

Exakat via composer

After a long wait, here it is: exakat is available on packagist, via composer.
composer require exakat/exakat.
In fact, Exakat requires a gremlin server. After the composer command, there is another one liner to build. The instructions are available for OSX and Debian/Ubuntu, in a separate repository: https://github.com/exakat/gremlin3neo4j2. We are welcoming PR for any other OS.

Give a try to the installation via composer and tell us about it! Now, there are installation instructions for Exakat on Docker, on Vagrant, via composer, or just bare metal. Just pick your solution!

Removal of prepared statements

First, let me mention this is quite a shock title. Prepared statement is still the safest mean to use when sending data to a SQL or NoSQL query. It separate strictly the query from its processed data, avoid any perturbation of the actual query.
In terms of performances, reducing the number of queries is usually the best way to go. Less queries, however small they are, to the database, is a gain speed. This is the base for infamous N+1 problem.

Once the results are available on the Gremlin server, Exakat dumps them into a SQLITE database. This process was based on prepared inserts:

<?php
$query = 'insert into results values (null, :analyzer, :file, :line, :code);
foreach($results as $result) {
$stmt = $sqlite->prepare($query);
$stmt→bindValue('analyzer',  $result->analyzer, SQLITE3_TEXT);
$stmt→bindValue('file',  $result->file, SQLITE3_TEXT);
$stmt→bindValue('line',  $result->line, SQLITE3_INTEGER);
$stmt→bindValue('code',  $result->code, SQLITE3_TEXT);
$stmt->execute();
}
?>

Being prepared, the statement is actually only played on the newly bind values. Yet, this means as many insert as there are issues found in the code : that means easily a few thousands, on middle sized code.
The multiple insertions were replaces by a multiple-value INSERT. Results are collected in the foreach, and then executed once. Instead of indicating the type of data (INTEGER/STRING) to SQLITE3, we now have to escape them with escapeString. Code is longer, and uglier.

<?php
$values = array();
foreach($results as $result) {
$values[] = '("'.$sqlite->escapeString($result→analyzer'”, “'.$sqlite->escapeString($result→file'”, '.$sqlite→escapeString($result→line', “'.$sqlite→escapeString($result→code'”)';
}
$query = 'INSERT INTO results (null, “analyzer”, “file”, “line”, “code”) VALUES '.
implode(',', $values);
?>

Most of the queries were inserts, so this gave a massive acceleration of the dump. There is currently an UPDATE left, which is hard to turn into a multiple value update, so it is left until refactoring.

str_repeat() instead of loops

This is a simple analysis, that optimize code : when a literal is concatenated in a loop, it may probably better be replaced by a str_repeat(). This kind of situation occurs often when a string has to be filled : it feels normal to loop until the counter reaches a limit, while counting the elements then using str_repeat or str_pad() in that case is actually cleaner and faster.

<?php
for($i = $done; $i < $n; ++$i) {
	$string .= 'filler';
}

// Equivalent to
$string.= str_repeat('filler', $n - $done);
?>

crc32() might be a negative number

crc32() returns a number, that is supposed to be unsigned. On 32-bits plat-forms, this might be a number so large that it fills PHP’s signed integer, leading to a negative number. On 64-bits plat-forms, integers are larger, and accommodate any CRC32 value, so this disappears.
This means that crc32() numbers should be printed with printf(‘%u’), and that crc32 checksums should not be concatenated directly, without a sprintf(), dechex() call or any other unsigned representation.
This kind of bug may be rare. It is actually difficult to turn the warning from the documentation into a possible, or probable issue. However, this is also why such analysis are important : when the bug bites, it is important to have some clues about the bugs.

Happy PHP code reviews

Exakat 0.11.0 adds new installations, speed gains and more gotchas coverages. One important usage of code review is to bring a second look on the code : suggesting pieces of code that might take better advantage of PHP native features. It’s like having a permanent reviewer for your code, with an ever growing experience. This soon may be yours too.

All the 310+ analyzers are presented in the docs, including the classic ‘Could be class constant‘. Download Exakat on exakat.io, upgrade it with ‘exakat.phar upgrade -u’ and like us on github.