Квест → Как хакнуть форму
Прошли: 77
Фреймворк Laravel имеет отличный класс для работы с коллекциями, который имеет много полезных операций. Класс также является macroable. Это означает, что к нему можно добавлять функции во время выполнения путем вызова его метода macro
и передачи названия и замыкания. В наших проектах мы, как правило, пишем один и тот же макрос снова и снова. Вот почему мы вынесли эти макросы в пакет laravel-collection-macros, так что вы можете их использовать, котоый основан на amphp/parallel.
В этом посте я хотел бы поговорить немного о новом макросе, называемом parallelMap
. parallelmap
идентична map`у, но каждый элемент в коллекции будут обрабатываться параллельно.
Давайте взглянем на пример:
$pageSources = collect($urls)->parallelMap(function($url) { return file_get_contents($url); });
Содержимое данных $urls
будет получено одновременно. Это будет гораздо быстрее, чем последовательное извлечение содержимого для каждого URL-адреса. Классная штука!
Вот еще один кусок кода, взятый из наших тестов:
/** @test */ public function it_can_perform_async_map_operations() { $this->startStopWatch(); $collection = Collection::make([1, 2, 3, 4, 5])->parallelMap(function (int $number) { sleep(1); return $number * 10; }); $this->assertTookLessThanSeconds(2); $this->assertEquals([10, 20, 30, 40, 50], $collection->toArray()); }
Вам, наверное, интересно, как эта магия работает. Ну, самое трудное внутри нового пакета Amp's parallel-functions
. Вот краткое описание того, что это взято из их документации:
amphp/parallel-functions - это упрощенный слой над amphp/parallel. Он позволяет параллельное выполнение кода за счет использования потоков или процессов, в зависимости от установленных расширений. Все данные, отправленные / полученные от дочерних процессов / потоков, должны быть сериализуемыми с использованием функцию РНР
serialize()
.
Вот пример, опять же взятый из их документации, о том, как можно использовать пакет напрямую:
use Amp\Promise; use function Amp\ParallelFunctions\parallelMap; $values = Promise\wait(parallelMap([1, 2, 3], function ($time) { \sleep($time); // a blocking function call, might also do blocking I/O here return $time * $time; }));
ParallelMap
macro в нашем пакете просто использует свою магию. Вот определение macro:
Collection::macro('parallelMap', function (callable $callback): Collection { $promises = parallelMap($this->items, $callback); $this->items = wait($promises); return $this; });
Помните, что вы не должны использовать parallelMap
, если можно очень просто выполнить ту же самую работу через closure. Использование parallelMap
это достаточно большой overhead. Не используйте его для небольших операций или для больших коллекцию.
Спасибо Никлас Келлер за Amp и за замечательный amphp/parallel-functions