SlideShare uma empresa Scribd logo
1 de 30
Iterators & Generators
Practical Uses in Memory Management
Reach out
● Software Engineer
● Systems Administrator
● All around nerd
@aramonc
Memory Management in PHP
● Garbage collected
○ Reference counts
○ Happens after variable is unset, leave function
scope, or script ends, GC buffer is full
● All values are stored in hash tables of ZVAL structs
● Arrays are dynamically allocated by doubling the
size
● Much better in PHP 7 than 5.6
What are Iterators and Generators
Iterators are:
● An object that can be iterated over using a loop
● PHP has several built in the SPL
● Can create additional ones
● Special ones are the recursive & filter iterators
Generators are:
● A special kind of custom iterator
● Keywords & interfaces that allow you to define an
Iterator without having to create a class that
implements the interface
https://github.com/aramonc/ig_talk
Generating many values: The object
<?php
namespace ArcIgTalk;
class User
{
public $_id;
public $firstName;
public $lastName;
public $email;
public $password;
public $phoneNumber;
}
Generating many values: Generate some values
<?php
...
for ($i = 0; $i < 1000000; $i++) {
$user = new User();
$user->_id = new ObjectID();
$user->email = $faker->email;
$user->password = $faker->password(12, 32);
$user->firstName = $faker->firstName();
$user->lastName = $faker->lastName;
$user->phoneNumber = $faker->phoneNumber;
$users[] = $user;
if ($i % 5000 === 0) {
$collection->insertMany($users);
$users = [];
}
}
Generating many values: Generate some values
Processing values: Paginated Provider
<?php
namespace ArcIgTalk;
class Provider
{
public function getPagedList(int $page = 0, int $limit = 100): array
{
$cursor = $this->collection->find([],['limit' => $limit,'skip' => $page * $limit]);
$users = [];
foreach ($cursor as $data) {
$users[] = $this->createUserEntity($data->getArrayCopy());
}
return $users;
}
}
Processing values: Paginated Provider
<?php
namespace ArcIgTalk;
class Provider
{
public function getPagedList(int $page = 0, int $limit = 100): array
{
$cursor = $this->collection->find([],['limit' => $limit,'skip' => $page * $limit]);
$users = [];
foreach ($cursor as $data) {
$users[] = $this->createUserEntity($data->getArrayCopy());
}
return $users;
}
}
Processing values: Simple approach
<?php
$provider = new Provider(new Client("mongodb://datastore:27017"));
$emailLogPath = __DIR__ . '/../data/user.txt';
$emailLog = fopen($emailLogPath, 'w+');
for ($up = 0; $up < 10000; $up++) {
foreach ($provider->getPagedList($up) as $user) {
fwrite($emailLog, $user->email . "n");
}
}
fclose($emailLog);
Processing values: Simple approach
<?php
$provider = new Provider(new Client("mongodb://datastore:27017"));
$emailLogPath = __DIR__ . '/../data/user.txt';
$emailLog = fopen($emailLogPath, 'w+');
for ($up = 0; $up < 10000; $up++) {
foreach ($provider->getPagedList($up) as $user) {
fwrite($emailLog, $user->email . "n");
}
}
fclose($emailLog);
Processing values: Simple approach
Processing values: Why does it take so long?
● 3 nested loops
○ for ($up = 0; $up < 10000; $up++)
○ foreach ($provider->getPagedList($up) as $user)
○ foreach ($cursor as $data)
● O(n^3) or n*m*p
Processing values: What is going on?
<?php
namespace ArcIgTalk;
class Provider
{
public function getPagedList(int $page = 0, int $limit = 100): array
{
$cursor = $this->collection->find([],['limit' => $limit,'skip' => $page * $limit]);
$users = [];
foreach ($cursor as $data) {
$users[] = $this->createUserEntity($data->getArrayCopy());
}
return $users;
}
}
Processing values: What is going on?
<?php
$provider = new Provider(new Client("mongodb://datastore:27017"));
$emailLogPath = __DIR__ . '/../data/user.txt';
$emailLog = fopen($emailLogPath, 'w+');
for ($up = 0; $up < 10000; $up++) {
foreach ($provider->getPagedList($up) as $user) {
fwrite($emailLog, $user->email . "n");
}
}
fclose($emailLog);
Processing values: Make it faster
<?php
$provider = new Provider(new Client("mongodb://datastore:27017"));
$emailLogPath = __DIR__ . '/../data/user.txt';
$emailLog = fopen($emailLogPath, 'w+');
for ($up = 0; $up < 1000; $up++) {
foreach ($provider->getPagedList($up, 1000) as $user) {
fwrite($emailLog, $user->email . "n");
}
}
fclose($emailLog);
Processing values: Make it faster
Processing values: What is going on?
<?php
$provider = new Provider(new Client("mongodb://datastore:27017"));
$emailLogPath = __DIR__ . '/../data/user.txt';
$emailLog = fopen($emailLogPath, 'w+');
for ($up = 0; $up < 1000; $up++) {
foreach ($provider->getPagedList($up, 1000) as $user) {
fwrite($emailLog, $user->email . "n");
}
}
fclose($emailLog);
Processing values: Make it faster
<?php
$provider = new Provider(new Client("mongodb://datastore:27017"));
$emailLogPath = __DIR__ . '/../data/user.txt';
$emailLog = fopen($emailLogPath, 'w+');
for ($up = 0; $up < 100; $up++) {
foreach ($provider->getPagedList($up, 10000) as $user) {
fwrite($emailLog, $user->email . "n");
}
}
fclose($emailLog);
Processing values: Make it faster
Processing values: Make it better
<?php
namespace ArcIgTalk;
class Provider
{
public function getPagedList(int $page = 0, int $limit = 100): Generator
{
$cursor = $this->collection->find([],[ 'limit' => $limit,'skip' => $page * $limit]);
foreach ($cursor as $data) {
/** @var $data BSONDocument */
yield $this->createUserEntity($data->getArrayCopy());
}
}
}
Processing values: Make it better
Processing values: It’s a bit slower
● 3 nested loops
○ for ($up = 0; $up < 10000; $up++)
○ foreach ($provider->getPagedList($up) as $user)
○ foreach ($cursor as $data)
● Effectively only 2
● O(n^2) or n*m
● Extra time for YIELD to go back & forth
We can do more! Let’s filter the list!
Filter values: Abstract the pagination
<?php
namespace ArcIgTalk;
class Service
{
const LIMIT = 100000;
public function getList(int $limit): Generator
{
$pages = ceil($limit / self::LIMIT);
$innerLimit = $pages > 1 ? self::LIMIT : $limit;
for ($page = 0; $page < $pages; $page++) {
foreach ($this->provider->getPagedList($page, $innerLimit) as $user) {
yield $user;
}
}
}
}
Filter values: The filter
<?php
...
function filterGmailUsers(User $user): bool
{
$emailParts = explode('@', $user->email);
return $emailParts[1] === 'gmail.com';
}
$filtered = new CallbackFilterIterator(
$service->getList(1000000),
'filterGmailUsers'
);
foreach ($filtered as $user) {
fwrite($emailLog, $user->email . "n");
}
Filter values: The filter
http://bit.ly/2tgw6z7
Questions?

Mais conteĂșdo relacionado

Mais procurados

Working with web_services
Working with web_servicesWorking with web_services
Working with web_services
Lorna Mitchell
 
J querypractice
J querypracticeJ querypractice
J querypractice
Inbal Geffen
 
Jqeury ajax plugins
Jqeury ajax pluginsJqeury ajax plugins
Jqeury ajax plugins
Inbal Geffen
 

Mais procurados (20)

Working with web_services
Working with web_servicesWorking with web_services
Working with web_services
 
Hacking hhvm
Hacking hhvmHacking hhvm
Hacking hhvm
 
Connecting Content Silos: One CMS, Many Sites With The WordPress REST API
 Connecting Content Silos: One CMS, Many Sites With The WordPress REST API Connecting Content Silos: One CMS, Many Sites With The WordPress REST API
Connecting Content Silos: One CMS, Many Sites With The WordPress REST API
 
Javascript
JavascriptJavascript
Javascript
 
Models and Service Layers, Hemoglobin and Hobgoblins
Models and Service Layers, Hemoglobin and HobgoblinsModels and Service Layers, Hemoglobin and Hobgoblins
Models and Service Layers, Hemoglobin and Hobgoblins
 
Web Apps in Perl - HTTP 101
Web Apps in Perl - HTTP 101Web Apps in Perl - HTTP 101
Web Apps in Perl - HTTP 101
 
J querypractice
J querypracticeJ querypractice
J querypractice
 
jQuery in 15 minutes
jQuery in 15 minutesjQuery in 15 minutes
jQuery in 15 minutes
 
Jqeury ajax plugins
Jqeury ajax pluginsJqeury ajax plugins
Jqeury ajax plugins
 
The promise of asynchronous php
The promise of asynchronous phpThe promise of asynchronous php
The promise of asynchronous php
 
PHP 5.3 and Lithium: the most rad php framework
PHP 5.3 and Lithium: the most rad php frameworkPHP 5.3 and Lithium: the most rad php framework
PHP 5.3 and Lithium: the most rad php framework
 
jQuery
jQueryjQuery
jQuery
 
Rails GUI Development with Ext JS
Rails GUI Development with Ext JSRails GUI Development with Ext JS
Rails GUI Development with Ext JS
 
Developing applications for performance
Developing applications for performanceDeveloping applications for performance
Developing applications for performance
 
Learning jQuery in 30 minutes
Learning jQuery in 30 minutesLearning jQuery in 30 minutes
Learning jQuery in 30 minutes
 
Eve - REST API for Humansℱ
Eve - REST API for HumansℱEve - REST API for Humansℱ
Eve - REST API for Humansℱ
 
Php summary
Php summaryPhp summary
Php summary
 
Play ĂĄ la Rails
Play ĂĄ la RailsPlay ĂĄ la Rails
Play ĂĄ la Rails
 
JQuery introduction
JQuery introductionJQuery introduction
JQuery introduction
 
jQuery from the very beginning
jQuery from the very beginningjQuery from the very beginning
jQuery from the very beginning
 

Semelhante a Iterators & generators: practical uses in memory management

How to Create Login and Registration API in PHP.pdf
How to Create Login and Registration API in PHP.pdfHow to Create Login and Registration API in PHP.pdf
How to Create Login and Registration API in PHP.pdf
Appweb Coders
 
RESTful web services
RESTful web servicesRESTful web services
RESTful web services
Tudor Constantin
 
PHP 5.3 Overview
PHP 5.3 OverviewPHP 5.3 Overview
PHP 5.3 Overview
jsmith92
 
Web Scraping with PHP
Web Scraping with PHPWeb Scraping with PHP
Web Scraping with PHP
Matthew Turland
 

Semelhante a Iterators & generators: practical uses in memory management (20)

Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For Beginners
 
é–ąè„żPHPć‹‰ćŒ·äŒš php5.4ă€ăŸăżăă„
é–ąè„żPHPć‹‰ćŒ·äŒš php5.4ă€ăŸăżăă„é–ąè„żPHPć‹‰ćŒ·äŒš php5.4ă€ăŸăżăă„
é–ąè„żPHPć‹‰ćŒ·äŒš php5.4ă€ăŸăżăă„
 
Electrify your code with PHP Generators
Electrify your code with PHP GeneratorsElectrify your code with PHP Generators
Electrify your code with PHP Generators
 
PHP POWERPOINT SLIDES
PHP POWERPOINT SLIDESPHP POWERPOINT SLIDES
PHP POWERPOINT SLIDES
 
Mojolicious
MojoliciousMojolicious
Mojolicious
 
How to Create Login and Registration API in PHP.pdf
How to Create Login and Registration API in PHP.pdfHow to Create Login and Registration API in PHP.pdf
How to Create Login and Registration API in PHP.pdf
 
RESTful web services
RESTful web servicesRESTful web services
RESTful web services
 
Ruby/Rails
Ruby/RailsRuby/Rails
Ruby/Rails
 
Php update and delet operation
Php update and delet operationPhp update and delet operation
Php update and delet operation
 
Zend Framework Study@Tokyo #2
Zend Framework Study@Tokyo #2Zend Framework Study@Tokyo #2
Zend Framework Study@Tokyo #2
 
PHP 5.3 Overview
PHP 5.3 OverviewPHP 5.3 Overview
PHP 5.3 Overview
 
Framework
FrameworkFramework
Framework
 
Drupal 8 migrate!
Drupal 8 migrate!Drupal 8 migrate!
Drupal 8 migrate!
 
Quality assurance for php projects with PHPStorm
Quality assurance for php projects with PHPStormQuality assurance for php projects with PHPStorm
Quality assurance for php projects with PHPStorm
 
4. Php MongoDB view_data
4. Php MongoDB view_data4. Php MongoDB view_data
4. Php MongoDB view_data
 
Php
PhpPhp
Php
 
The Zen of Lithium
The Zen of LithiumThe Zen of Lithium
The Zen of Lithium
 
Mojolicious
MojoliciousMojolicious
Mojolicious
 
Web Scraping with PHP
Web Scraping with PHPWeb Scraping with PHP
Web Scraping with PHP
 
Advanced Php - Macq Electronique 2010
Advanced Php - Macq Electronique 2010Advanced Php - Macq Electronique 2010
Advanced Php - Macq Electronique 2010
 

Mais de Adrian Cardenas

Mais de Adrian Cardenas (7)

Http/2 lightning
Http/2   lightningHttp/2   lightning
Http/2 lightning
 
Http/2
Http/2Http/2
Http/2
 
Creating a phar
Creating a pharCreating a phar
Creating a phar
 
First there was the command line
First there was the command lineFirst there was the command line
First there was the command line
 
Learning the command line
Learning the command lineLearning the command line
Learning the command line
 
Conquering the Command Line
Conquering the Command LineConquering the Command Line
Conquering the Command Line
 
Communicating on the web
Communicating on the webCommunicating on the web
Communicating on the web
 

Último

%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
masabamasaba
 
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
masabamasaba
 
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
VictoriaMetrics
 
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
masabamasaba
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
9953056974 Low Rate Call Girls In Saket, Delhi NCR
 
The title is not connected to what is inside
The title is not connected to what is insideThe title is not connected to what is inside
The title is not connected to what is inside
shinachiaurasa2
 
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Bert Jan Schrijver
 

Último (20)

%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
 
call girls in Vaishali (Ghaziabad) 🔝 >àŒ’8448380779 🔝 genuine Escort Service đŸ”âœ”ïžâœ”ïž
call girls in Vaishali (Ghaziabad) 🔝 >àŒ’8448380779 🔝 genuine Escort Service đŸ”âœ”ïžâœ”ïžcall girls in Vaishali (Ghaziabad) 🔝 >àŒ’8448380779 🔝 genuine Escort Service đŸ”âœ”ïžâœ”ïž
call girls in Vaishali (Ghaziabad) 🔝 >àŒ’8448380779 🔝 genuine Escort Service đŸ”âœ”ïžâœ”ïž
 
WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?
 
Announcing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK SoftwareAnnouncing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK Software
 
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
 
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
 
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
 
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
 
%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto
 
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
 
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
 
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park %in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial Goals
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
 
The title is not connected to what is inside
The title is not connected to what is insideThe title is not connected to what is inside
The title is not connected to what is inside
 
WSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
WSO2Con2024 - Enabling Transactional System's Exponential Growth With SimplicityWSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
WSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
 
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
 
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
 

Iterators & generators: practical uses in memory management

  • 1. Iterators & Generators Practical Uses in Memory Management
  • 2. Reach out ● Software Engineer ● Systems Administrator ● All around nerd @aramonc
  • 3. Memory Management in PHP ● Garbage collected ○ Reference counts ○ Happens after variable is unset, leave function scope, or script ends, GC buffer is full ● All values are stored in hash tables of ZVAL structs ● Arrays are dynamically allocated by doubling the size ● Much better in PHP 7 than 5.6
  • 4. What are Iterators and Generators Iterators are: ● An object that can be iterated over using a loop ● PHP has several built in the SPL ● Can create additional ones ● Special ones are the recursive & filter iterators Generators are: ● A special kind of custom iterator ● Keywords & interfaces that allow you to define an Iterator without having to create a class that implements the interface
  • 6. Generating many values: The object <?php namespace ArcIgTalk; class User { public $_id; public $firstName; public $lastName; public $email; public $password; public $phoneNumber; }
  • 7. Generating many values: Generate some values <?php ... for ($i = 0; $i < 1000000; $i++) { $user = new User(); $user->_id = new ObjectID(); $user->email = $faker->email; $user->password = $faker->password(12, 32); $user->firstName = $faker->firstName(); $user->lastName = $faker->lastName; $user->phoneNumber = $faker->phoneNumber; $users[] = $user; if ($i % 5000 === 0) { $collection->insertMany($users); $users = []; } }
  • 8. Generating many values: Generate some values
  • 9. Processing values: Paginated Provider <?php namespace ArcIgTalk; class Provider { public function getPagedList(int $page = 0, int $limit = 100): array { $cursor = $this->collection->find([],['limit' => $limit,'skip' => $page * $limit]); $users = []; foreach ($cursor as $data) { $users[] = $this->createUserEntity($data->getArrayCopy()); } return $users; } }
  • 10. Processing values: Paginated Provider <?php namespace ArcIgTalk; class Provider { public function getPagedList(int $page = 0, int $limit = 100): array { $cursor = $this->collection->find([],['limit' => $limit,'skip' => $page * $limit]); $users = []; foreach ($cursor as $data) { $users[] = $this->createUserEntity($data->getArrayCopy()); } return $users; } }
  • 11. Processing values: Simple approach <?php $provider = new Provider(new Client("mongodb://datastore:27017")); $emailLogPath = __DIR__ . '/../data/user.txt'; $emailLog = fopen($emailLogPath, 'w+'); for ($up = 0; $up < 10000; $up++) { foreach ($provider->getPagedList($up) as $user) { fwrite($emailLog, $user->email . "n"); } } fclose($emailLog);
  • 12. Processing values: Simple approach <?php $provider = new Provider(new Client("mongodb://datastore:27017")); $emailLogPath = __DIR__ . '/../data/user.txt'; $emailLog = fopen($emailLogPath, 'w+'); for ($up = 0; $up < 10000; $up++) { foreach ($provider->getPagedList($up) as $user) { fwrite($emailLog, $user->email . "n"); } } fclose($emailLog);
  • 14. Processing values: Why does it take so long? ● 3 nested loops ○ for ($up = 0; $up < 10000; $up++) ○ foreach ($provider->getPagedList($up) as $user) ○ foreach ($cursor as $data) ● O(n^3) or n*m*p
  • 15. Processing values: What is going on? <?php namespace ArcIgTalk; class Provider { public function getPagedList(int $page = 0, int $limit = 100): array { $cursor = $this->collection->find([],['limit' => $limit,'skip' => $page * $limit]); $users = []; foreach ($cursor as $data) { $users[] = $this->createUserEntity($data->getArrayCopy()); } return $users; } }
  • 16. Processing values: What is going on? <?php $provider = new Provider(new Client("mongodb://datastore:27017")); $emailLogPath = __DIR__ . '/../data/user.txt'; $emailLog = fopen($emailLogPath, 'w+'); for ($up = 0; $up < 10000; $up++) { foreach ($provider->getPagedList($up) as $user) { fwrite($emailLog, $user->email . "n"); } } fclose($emailLog);
  • 17. Processing values: Make it faster <?php $provider = new Provider(new Client("mongodb://datastore:27017")); $emailLogPath = __DIR__ . '/../data/user.txt'; $emailLog = fopen($emailLogPath, 'w+'); for ($up = 0; $up < 1000; $up++) { foreach ($provider->getPagedList($up, 1000) as $user) { fwrite($emailLog, $user->email . "n"); } } fclose($emailLog);
  • 19. Processing values: What is going on? <?php $provider = new Provider(new Client("mongodb://datastore:27017")); $emailLogPath = __DIR__ . '/../data/user.txt'; $emailLog = fopen($emailLogPath, 'w+'); for ($up = 0; $up < 1000; $up++) { foreach ($provider->getPagedList($up, 1000) as $user) { fwrite($emailLog, $user->email . "n"); } } fclose($emailLog);
  • 20. Processing values: Make it faster <?php $provider = new Provider(new Client("mongodb://datastore:27017")); $emailLogPath = __DIR__ . '/../data/user.txt'; $emailLog = fopen($emailLogPath, 'w+'); for ($up = 0; $up < 100; $up++) { foreach ($provider->getPagedList($up, 10000) as $user) { fwrite($emailLog, $user->email . "n"); } } fclose($emailLog);
  • 22. Processing values: Make it better <?php namespace ArcIgTalk; class Provider { public function getPagedList(int $page = 0, int $limit = 100): Generator { $cursor = $this->collection->find([],[ 'limit' => $limit,'skip' => $page * $limit]); foreach ($cursor as $data) { /** @var $data BSONDocument */ yield $this->createUserEntity($data->getArrayCopy()); } } }
  • 24. Processing values: It’s a bit slower ● 3 nested loops ○ for ($up = 0; $up < 10000; $up++) ○ foreach ($provider->getPagedList($up) as $user) ○ foreach ($cursor as $data) ● Effectively only 2 ● O(n^2) or n*m ● Extra time for YIELD to go back & forth
  • 25. We can do more! Let’s filter the list!
  • 26. Filter values: Abstract the pagination <?php namespace ArcIgTalk; class Service { const LIMIT = 100000; public function getList(int $limit): Generator { $pages = ceil($limit / self::LIMIT); $innerLimit = $pages > 1 ? self::LIMIT : $limit; for ($page = 0; $page < $pages; $page++) { foreach ($this->provider->getPagedList($page, $innerLimit) as $user) { yield $user; } } } }
  • 27. Filter values: The filter <?php ... function filterGmailUsers(User $user): bool { $emailParts = explode('@', $user->email); return $emailParts[1] === 'gmail.com'; } $filtered = new CallbackFilterIterator( $service->getList(1000000), 'filterGmailUsers' ); foreach ($filtered as $user) { fwrite($emailLog, $user->email . "n"); }