├── .gitignore ├── src ├── gerador-de-arquivo.php ├── Generator │ ├── ReadFileGenerators.php │ └── generators.php └── Fibers │ ├── ReadFileFibers.php │ └── fibers.php ├── composer.json ├── composer.lock └── readme.md /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | vendor 3 | file.csv -------------------------------------------------------------------------------- /src/gerador-de-arquivo.php: -------------------------------------------------------------------------------- 1 | arquivo = fopen($nomeArquivo, 'r'); 11 | } 12 | 13 | public function lerArquivo(): iterable 14 | { 15 | while(!feof($this->arquivo)) { 16 | yield fgetcsv($this->arquivo); 17 | } 18 | } 19 | 20 | public function __destruct() 21 | { 22 | fclose($this->arquivo); 23 | } 24 | } -------------------------------------------------------------------------------- /src/Fibers/ReadFileFibers.php: -------------------------------------------------------------------------------- 1 | arquivo = fopen($nomeArquivo, 'r'); 13 | } 14 | 15 | public function lerArquivo() 16 | { 17 | while(!feof($this->arquivo)) { 18 | Fiber::suspend(fgetcsv($this->arquivo)); 19 | } 20 | } 21 | 22 | public function __destruct() 23 | { 24 | fclose($this->arquivo); 25 | } 26 | } -------------------------------------------------------------------------------- /src/Generator/generators.php: -------------------------------------------------------------------------------- 1 | lerArquivo(); 9 | 10 | foreach ($conteudo as $item) { 11 | printf('%s tem %d anos%s', $item[0], $item[1], PHP_EOL); 12 | } 13 | 14 | $memoria = round(memory_get_peak_usage() / 1024, 0); 15 | $tamanho =round(filesize('../file.csv') / 1024 / 1024, 0); 16 | 17 | echo "Memória utilizada: " . $memoria . "KB" . PHP_EOL; 18 | echo "Tamanho do arquivo: " . $tamanho . "MB" . PHP_EOL; -------------------------------------------------------------------------------- /composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", 5 | "This file is @generated automatically" 6 | ], 7 | "content-hash": "28a45d6782eb1a5460b2e65ed2954059", 8 | "packages": [], 9 | "packages-dev": [], 10 | "aliases": [], 11 | "minimum-stability": "stable", 12 | "stability-flags": [], 13 | "prefer-stable": false, 14 | "prefer-lowest": false, 15 | "platform": [], 16 | "platform-dev": [], 17 | "plugin-api-version": "2.3.0" 18 | } 19 | -------------------------------------------------------------------------------- /src/Fibers/fibers.php: -------------------------------------------------------------------------------- 1 | lerArquivo(); 11 | }); 12 | echo $fiber->start(); 13 | while ($item = $fiber->resume()) { 14 | printf('%s tem %d anos%s', $item[0], $item[1], PHP_EOL); 15 | } 16 | 17 | $memoria = round(memory_get_peak_usage() / 1024, 0); 18 | $tamanho =round(filesize('../file.csv') / 1024 / 1024, 0); 19 | 20 | echo "Memória utilizada: " . $memoria . "KB" . PHP_EOL; 21 | echo "Tamanho do arquivo: " . $tamanho . "MB" . PHP_EOL; -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | ## Big File Challenge 2 | 3 | Este desafio foi proposto pelo [Zanfranceschi](https://twitter.com/zanfranceschi/) 4 | 5 | Você pode ver a proposta do desafio [aqui](https://dev.to/zanfranceschi/desafio-processar-arquivos-grandes-com-restricao-de-memoria-2ie3) ou então pelo [Twitter](https://twitter.com/zanfranceschi/status/1532505851658784768) 6 | 7 | 8 | Para a implementação da solução utilizei os seguintes conceitos: 9 | - Generators, que aprendi no [video](https://www.youtube.com/watch?v=1_TnGAxEoPk) do [Vinicius Dias - Dias de Dev](https://twitter.com/cviniciussdias), a solução que está neste repositório é a do vídeo do Vinicius :) 10 | - Fiber, que aprendi no [video](https://www.youtube.com/watch?v=P7ucMvlVhGc) do [Leonardo Tumadjian - DifferDev](https://www.linkedin.com/in/leonardotumadjian/) e resolvi aplicar este desafio usando Fibers! 11 | 12 | ## Explicação 13 | O grande ponto do desafio é limitar sua infra, onde não é possível sua aplicação carregar em memória um arquivo enorme, dessa forma resolvi 14 | utilizar Generators que trabalha com Corrotinas e Fibers que permite trabalhar também com Corrotinas no PHP 8.1 > 15 | 16 | A ideia de corrotinas é permitir que um processo seja parado, retorne para a função principal e em seguida volte para o mesmo ponto para continuar executando o processo. 17 | A ideia de corrotinas permite trabalhar de forma assíncrona! 18 | 19 | ## Como executar o projeto: 20 | 21 | 1 - Clone este repositório: 22 | ```shell 23 | git clone git@github.com:NicolasPereira/process-big-file-php.git 24 | ``` 25 | 26 | 2 - Crie o arquivo gigante 27 | ```shell 28 | php gerador-de-arquivo.php 29 | ``` 30 | 31 | 3 - Para rodar usando generators execute 32 | ```shell 33 | cd src/Generators 34 | php generators.php 35 | ``` 36 | 37 | 4 - Para rodar usando Fibers execute 38 | ```shell 39 | cd src/Fibers 40 | php fibers.php 41 | ``` 42 | 43 | >Para rodar utilizando Fibers é necessário utilizar o PHP 8.1 44 | 45 | ## Pontos a melhorar 46 | Preciso dockerizar o projeto para o docker limitar a memória, para o teste alterei a memória do php no `php.ini` 47 | --------------------------------------------------------------------------------