Асинхронний паралельний запуск коду в PHP на прикладі Laravel Collection
Фреймворк 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