mirror of
https://github.com/FreshRSS/FreshRSS.git
synced 2026-05-24 16:25:00 -04:00
Reduce API memory consumption (#6137)
`echo json_encode(...)` is very memory demanding for large responses, so optimised. Contributes to https://github.com/FreshRSS/FreshRSS/issues/6136 https://github.com/FreshRSS/FreshRSS/pull/6013#discussion_r1506779881
This commit is contained in:
committed by
GitHub
parent
96484d22a1
commit
5e54d5bc58
@@ -5,6 +5,24 @@ if (version_compare(PHP_VERSION, FRESHRSS_MIN_PHP_VERSION, '<')) {
|
||||
die(sprintf('FreshRSS error: FreshRSS requires PHP %s+!', FRESHRSS_MIN_PHP_VERSION));
|
||||
}
|
||||
|
||||
if (!function_exists('array_is_list')) {
|
||||
/**
|
||||
* Polyfill for PHP <8.1
|
||||
* https://php.net/array-is-list#127044
|
||||
* @param array<mixed> $array
|
||||
*/
|
||||
function array_is_list(array $array): bool {
|
||||
$i = -1;
|
||||
foreach ($array as $k => $v) {
|
||||
++$i;
|
||||
if ($k !== $i) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('mb_strcut')) {
|
||||
function mb_strcut(string $str, int $start, ?int $length = null, string $encoding = 'UTF-8'): string {
|
||||
return substr($str, $start, $length) ?: '';
|
||||
@@ -89,6 +107,45 @@ function classAutoloader(string $class): void {
|
||||
spl_autoload_register('classAutoloader');
|
||||
//</Auto-loading>
|
||||
|
||||
/**
|
||||
* Memory efficient replacement of `echo json_encode(...)`
|
||||
* @param array<mixed>|mixed $json
|
||||
* @param int $optimisationDepth Number of levels for which to perform memory optimisation
|
||||
* before calling the faster native JSON serialisation.
|
||||
* Set to negative value for infinite depth.
|
||||
*/
|
||||
function echoJson($json, int $optimisationDepth = -1): void {
|
||||
if ($optimisationDepth === 0 || !is_array($json)) {
|
||||
echo json_encode($json, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
|
||||
return;
|
||||
}
|
||||
$first = true;
|
||||
if (array_is_list($json)) {
|
||||
echo '[';
|
||||
foreach ($json as $item) {
|
||||
if ($first) {
|
||||
$first = false;
|
||||
} else {
|
||||
echo ',';
|
||||
}
|
||||
echoJson($item, $optimisationDepth - 1);
|
||||
}
|
||||
echo ']';
|
||||
} else {
|
||||
echo '{';
|
||||
foreach ($json as $key => $value) {
|
||||
if ($first) {
|
||||
$first = false;
|
||||
} else {
|
||||
echo ',';
|
||||
}
|
||||
echo json_encode($key, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE), ':';
|
||||
echoJson($value, $optimisationDepth - 1);
|
||||
}
|
||||
echo '}';
|
||||
}
|
||||
}
|
||||
|
||||
function idn_to_puny(string $url): string {
|
||||
if (function_exists('idn_to_ascii')) {
|
||||
$idn = parse_url($url, PHP_URL_HOST);
|
||||
|
||||
@@ -715,8 +715,9 @@ final class GReaderAPI {
|
||||
$response['continuation'] = '' . $entry->id();
|
||||
}
|
||||
}
|
||||
|
||||
echo json_encode($response, JSON_OPTIONS), "\n";
|
||||
unset($entries, $entryDAO, $items);
|
||||
gc_collect_cycles();
|
||||
echoJson($response, 2); // $optimisationDepth=2 as we are interested in being memory efficient for {"items":[...]}
|
||||
exit();
|
||||
}
|
||||
|
||||
@@ -805,8 +806,9 @@ final class GReaderAPI {
|
||||
'updated' => time(),
|
||||
'items' => $items,
|
||||
);
|
||||
|
||||
echo json_encode($response, JSON_OPTIONS), "\n";
|
||||
unset($entries, $entryDAO, $items);
|
||||
gc_collect_cycles();
|
||||
echoJson($response, 2); // $optimisationDepth=2 as we are interested in being memory efficient for {"items":[...]}
|
||||
exit();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user