Тестовое задание Bitrix

Задача 1. Сортировка массива

Я сортирую массив целых чисел по возрастанию. Цель - самый быстрый способ при минимальном расходе памяти. Беру SplFixedArray для генерации (плотный C-массив без хеш-таблицы) и нативный sort(). Размер до 200 000 уходит в браузер меньше чем за секунду.

Запустить

Исходный код

Local\Sort\Sorter

<?php

declare(strict_types=1);

namespace Local\Sort;

use SplFixedArray;

final class Sorter
{
    public static function generate(int $size, int $seed = 42): SplFixedArray
    {
        mt_srand($seed);
        $arr = new SplFixedArray($size);
        for ($i = 0; $i < $size; $i++) {
            $arr[$i] = mt_rand(-1_000_000, 1_000_000);
        }
        return $arr;
    }

    public static function sort(SplFixedArray $arr): SplFixedArray
    {
        $tmp = $arr->toArray();
        sort($tmp, SORT_NUMERIC);
        return SplFixedArray::fromArray($tmp, false);
    }
}

AJAX-эндпоинт

<?php

declare(strict_types=1);

require_once __DIR__ . '/_bootstrap.php';
require_once PROJECT_ROOT . '/local/php_interface/lib/Sort/Sorter.php';

use Local\Sort\Sorter;

set_time_limit(120);
ini_set('memory_limit', '512M');

$size = (int)($_GET['size'] ?? 10_000);
if ($size < 100 || $size > 200_000) {
    demo_json(['error' => 'size: допустимый диапазон 100..200000'], 400);
}

$memBefore = memory_get_peak_usage(true);

$tGenStart = hrtime(true);
$arr = Sorter::generate($size);
$tGenMs = (hrtime(true) - $tGenStart) / 1e6;

$tSortStart = hrtime(true);
$sorted = Sorter::sort($arr);
$tSortMs = (hrtime(true) - $tSortStart) / 1e6;

$peak = memory_get_peak_usage(true);

$head = [];
$tail = [];
for ($i = 0; $i < min(5, $size); $i++) {
    $head[] = $sorted[$i];
}
for ($i = max(0, $size - 5); $i < $size; $i++) {
    $tail[] = $sorted[$i];
}

$ok = true;
for ($i = 1; $i < $size; $i++) {
    if ($sorted[$i - 1] > $sorted[$i]) {
        $ok = false;
        break;
    }
}

demo_json([
    'php'         => PHP_VERSION,
    'size'        => $size,
    'gen_ms'      => $tGenMs,
    'sort_ms'     => $tSortMs,
    'total_ms'    => $tGenMs + $tSortMs,
    'peak_bytes'  => $peak,
    'delta_bytes' => max(0, $peak - $memBefore),
    'ok'          => $ok,
    'head'        => $head,
    'tail'        => $tail,
]);