From ad7a039c34ab9da2e2ee3e8ec5f18b8d32e6aaa3 Mon Sep 17 00:00:00 2001 From: Don Hardman Date: Thu, 16 Jan 2025 09:05:34 +0700 Subject: [PATCH] Use simd extension for json decode and tune performance in core Network Request --- src/ManticoreSearch/Client.php | 4 ++-- src/Network/Request.php | 7 ++++--- src/Network/Struct.php | 7 +++---- src/Plugin/Pluggable.php | 6 +++--- src/Tool/KeyboardLayout.php | 2 +- src/Tool/SqlQueryParser.php | 1 - test/src/Trait/TestFunctionalTrait.php | 6 +++--- 7 files changed, 16 insertions(+), 17 deletions(-) diff --git a/src/ManticoreSearch/Client.php b/src/ManticoreSearch/Client.php index 2a53987..173308f 100644 --- a/src/ManticoreSearch/Client.php +++ b/src/ManticoreSearch/Client.php @@ -414,7 +414,7 @@ public function getSettings(): Settings { protected function fetchSettings(): Settings { $resp = $this->sendRequest('SHOW SETTINGS'); /** @var array{0:array{columns:array,data:array{Setting_name:string,Value:string}}} */ - $data = (array)json_decode($resp->getBody(), true); + $data = (array)simdjson_decode($resp->getBody(), true); $settings = new Vector(); foreach ($data[0]['data'] as ['Setting_name' => $key, 'Value' => $value]) { // If the key is plugin_dir check env first and after choose @@ -442,7 +442,7 @@ protected function fetchSettings(): Settings { // Gather variables also $resp = $this->sendRequest('SHOW VARIABLES'); /** @var array{0:array{columns:array,data:array{Setting_name:string,Value:string}}} */ - $data = (array)json_decode($resp->getBody(), true); + $data = (array)simdjson_decode($resp->getBody(), true); foreach ($data[0]['data'] as ['Variable_name' => $key, 'Value' => $value]) { $settings->push( new Map( diff --git a/src/Network/Request.php b/src/Network/Request.php index 7b7bdf0..c5341f3 100644 --- a/src/Network/Request.php +++ b/src/Network/Request.php @@ -81,6 +81,7 @@ public static function default(string $id = '0'): static { * @param string $id * @return static */ + public static function fromString(string $data, string $id = '0'): static { $self = new static; $self->id = $id; @@ -155,7 +156,7 @@ public static function validateOrFail(string $data): array { * message:array{path_query:string,body:string}, * version:int} $result */ - $result = json_decode($data, true, 512, JSON_INVALID_UTF8_SUBSTITUTE); + $result = simdjson_decode($data, true, 512); if (!is_array($result)) { throw new InvalidNetworkRequestError('Invalid request payload is passed'); } @@ -234,11 +235,11 @@ protected function parseOrFail(array $payload): static { $this->path = $path; $this->format = $format; $this->endpointBundle = $endpointBundle; - $this->mySQLTool = static::detectMySQLTool($payload['message']['body']); + $this->mySQLTool = $format === RequestFormat::SQL ? static::detectMySQLTool($payload['message']['body']) : null; $this->payload = (in_array($endpointBundle, [Endpoint::Elastic, Endpoint::Bulk])) ? trim($payload['message']['body']) : static::removeComments($payload['message']['body']); - $this->command = strtok(strtolower($this->payload), ' ') ?: ''; + $this->command = strtolower(strtok($this->payload, ' ') ?: ''); $this->error = $payload['error']['message']; $this->errorBody = $payload['error']['body'] ?? []; $this->version = match ($payload['version']) { diff --git a/src/Network/Struct.php b/src/Network/Struct.php index ac233e7..6142209 100644 --- a/src/Network/Struct.php +++ b/src/Network/Struct.php @@ -111,9 +111,7 @@ public function addBigIntField(string $field): void { * @return bool */ public static function isValid(string $json): bool { - // TODO: replace with json_validate once we more to 8.3 - $result = json_decode($json, true, static::JSON_DEPTH, static::JSON_FLAGS); - return !!$result; + return simdjson_is_valid($json); } /** @@ -123,9 +121,10 @@ public static function isValid(string $json): bool { */ public static function fromJson(string $json): self { /** @var array */ - $result = (array)json_decode($json, true, static::JSON_DEPTH, static::JSON_FLAGS); + $result = (array)simdjson_decode($json, true, static::JSON_DEPTH); $bigIntFields = []; if (static::hasBigInt($json)) { + // We need here to keep original json decode cuzit has bigIntFields /** @var array */ $modified = json_decode($json, true, static::JSON_DEPTH, static::JSON_FLAGS | JSON_BIGINT_AS_STRING); static::traverseAndTrack($modified, $result, $bigIntFields); diff --git a/src/Plugin/Pluggable.php b/src/Plugin/Pluggable.php index 6912679..6032040 100644 --- a/src/Plugin/Pluggable.php +++ b/src/Plugin/Pluggable.php @@ -219,7 +219,7 @@ public function getList(): array { return []; } /** @var array{require?:array} $composerJson */ - $composerJson = json_decode($composerContent, true); + $composerJson = simdjson_decode($composerContent, true); if (!isset($composerJson['require'])) { return []; } @@ -274,7 +274,7 @@ public function getClassNamespaceByFullName(string $name): string { throw new Exception("Failed to get contents of composer.json for plugin: $name"); } - $composerJson = json_decode($composerContent, true); + $composerJson = simdjson_decode($composerContent, true); if (!$composerJson) { throw new Exception("Failed to decode contents of composer.json file for plugin: $name"); } @@ -465,7 +465,7 @@ public function fetchLocalPlugins(): array { throw new Exception("Failed to read composer file for plugin: $shortName"); } /** @var array{name:?string} */ - $composer = json_decode($composerContent, true); + $composer = simdjson_decode($composerContent, true); if (!isset($composer['name'])) { throw new Exception("Failed to detect local plugin name from file: $composerFile"); } diff --git a/src/Tool/KeyboardLayout.php b/src/Tool/KeyboardLayout.php index 47d7739..e3ec89c 100644 --- a/src/Tool/KeyboardLayout.php +++ b/src/Tool/KeyboardLayout.php @@ -156,7 +156,7 @@ protected static function getLangMap(): array { } /** @var array> $langMap */ - $langMap = json_decode($configContent, true); + $langMap = simdjson_decode($configContent, true); if (!is_array($langMap)) { throw new Exception("Invalid keyboard layout config file at '$configPath'"); } diff --git a/src/Tool/SqlQueryParser.php b/src/Tool/SqlQueryParser.php index 7f079c4..9f7e994 100644 --- a/src/Tool/SqlQueryParser.php +++ b/src/Tool/SqlQueryParser.php @@ -82,7 +82,6 @@ private static function getCreator(): PHPSQLCreator { * @throws GenericError */ public static function parse(string $payload, Closure $preProcessorCallback, mixed $args): ?array { - $result = (bool)call_user_func($preProcessorCallback, $args); if ($result === false) { return null; diff --git a/test/src/Trait/TestFunctionalTrait.php b/test/src/Trait/TestFunctionalTrait.php index 06c30f5..2c17ca9 100644 --- a/test/src/Trait/TestFunctionalTrait.php +++ b/test/src/Trait/TestFunctionalTrait.php @@ -318,13 +318,13 @@ protected static function runHttpQuery( /** @var array>,total?:string,columns?:string}> $result */ $result = match ($path) { - 'cli_json', 'sql', 'sql?mode=raw' => (array)json_decode(implode(PHP_EOL, $output), true), + 'cli_json', 'sql', 'sql?mode=raw' => (array)simdjson_decode(implode(PHP_EOL, $output), true), 'cli' => [ ['columns' => implode(PHP_EOL, $output), 'data' => [], 'error' => ''], ], // assuming Elastic-like endpoint is passed default => [ - ['data' => [(array)json_decode($output[0] ?? '{}', true)], 'error' => ''], + ['data' => [(array)simdjson_decode($output[0] ?? '{}', true)], 'error' => ''], ], }; print_r($output); @@ -361,7 +361,7 @@ protected static function runHttpBuddyRequest( $redirect = $redirectOutput ? '2>&1' : ''; exec("curl -s 127.0.0.1:$port -H 'Content-type: application/json' -d @$payloadFile $redirect", $output); /** @var array{version:int,type:string,message:array,data:array>}>} $result */ - $result = (array)json_decode($output[0] ?? '{}', true); + $result = (array)simdjson_decode($output[0] ?? '{}', true); return $result; }