Asynchronous programming FTW!

37
ASYNCHRONOUS PROGRAMMING FTW! (SAWYER X)

description

These are the slides for the talk I gave at YAPC::EU 2012 called Asynchronous Programming FTW! It tries to explain what async programming is with examples of a few Perl async frameworks.

Transcript of Asynchronous programming FTW!

Page 1: Asynchronous programming FTW!

ASYNCHRONOUSPROGRAMMING

FTW!(SAWYER X)

Page 2: Asynchronous programming FTW!

DOES THIS SOUND FAMILIAR?"Hi"

"Hi, dad"

"Got a minute?"

"Yes"

"I'm looking for a movieWhere do I start?"

"Go to the cinema website"

"What's the address?"

"www.whatchamacallit.whatever"

"Just a sec..."

Page 3: Asynchronous programming FTW!

...

...

...

...

Page 4: Asynchronous programming FTW!

"Well?"

"Ah! It loaded! What now?"

"Click on new movies"

"OK..."

........

"Well?"

"Loading"

*sounds of clicks*

Page 5: Asynchronous programming FTW!

"OK, now what?"

"Find a movie you want"

"Then what?"

"Click on it, you'll have instructions"

* eternity passes by *

"WELL?!?"

"Just a sec... it's loading..."

/me shoots myself

Page 6: Asynchronous programming FTW!

ILLUSTRATED(USING WWW::MECHANIZE)

$mech­>get($cinema_url);if ( $mech­>success ) $mech­>click('New Movies'); if ( $mech­>success ) my @movies = $mech­>find_inputs(...)

Page 7: Asynchronous programming FTW!

LET'S TRY THIS AGAIN..."Hi"

"Hi, dad"

"Got a minute?"

"Yes"

"I'm looking for a movieWhat should I do?"

"Go to this website, click on new moviesThen pick a movie, and click on it"

"Thank you"

"You're welcome"

Page 8: Asynchronous programming FTW!

GREAT SUCCESS!

Page 9: Asynchronous programming FTW!

CALLBACKSReference to a codePassed as an argumentCan be called by some other code

sub try_something my $input = shift; my $cb = shift; my $result = some_operation($input);

if ( $result­>'status' eq 'OK' ) $cb­>( $result­>'content' );

try_something( "some random input", sub my $content = shift; say "Successful request says $content!"; );

Page 10: Asynchronous programming FTW!

ILLUSTRATED, ASYNC(USING WWW::MECHANIZE)

$mech­>get( $cinema_url, sub $mech­>click( 'New Movies', sub $mech­>find_inputs( ..., sub my @movies = @_ ) ); );

Page 11: Asynchronous programming FTW!

WHY IS THIS USEFUL?Allow others to decide if something is good or not

Page 12: Asynchronous programming FTW!

my $juno = Juno­>new( hosts => [qw<1.1.1.1 2.2.2.2>], checks => FPing => on_success => sub my ( $juno, $host, $data ) = @_; my ( $ip, $loss, $avg ) = $juno­>analyze_ping_result( $data­>'stderr', );

$self­>set_host( $host, $avg ); ,

on_fail => sub my ( $juno, $host ) = @_;

$self­>delete_host($host); , );

Page 13: Asynchronous programming FTW!

WHY IS THIS USEFUL?Allow others to decide if something is good or notAllow easy stepping

Page 14: Asynchronous programming FTW!

Algorithm::Diff::Callbackuse Algorithm::Diff::Callback qw<diff_arrays diff_hashes>;

diff_arrays( \@old_family_members, \@new_family_members, sub print 'Happy to hear about ', shift , sub print 'Sorry to hear about ', shift ,);

diff_hashes( \%old_details, \%new_details, sub say 'Lost ', shift , sub say 'Gained ', shift , sub my ( $key, $before, $after ) = @_; say "$key changed from $before to $after"; ,);

Page 15: Asynchronous programming FTW!

WHY IS THIS USEFUL?Allow others to decide if something is good or notAllow easy steppingAllow control by other process (a type of IOC)Allow asynchronous code

Page 16: Asynchronous programming FTW!

THE EVENT LOOPCreate loopRegister eventsRun themLet the user keep registering new events

Page 17: Asynchronous programming FTW!

my %events = (...);

while (1) foreach my $event ( keys %events ) $event­>();

Page 18: Asynchronous programming FTW!

my %events; %events = (...);

while (1) foreach my $event ( keys %events ) $event­>();

while (1) foreach my $event ( keys %events ) if ( $events$event'time' <= time ) $events$event'code'­>();

sub add_event my ( $time, $code ) = @_; $events$id'time' = $time; $events$id'code' = $code; $id++;

Page 19: Asynchronous programming FTW!

EVENT TYPESTimers (one-time, recurring, sleep replacement)I/O (input output, including networking)

Page 20: Asynchronous programming FTW!

FUCK TALKLET'S GO PROGRAMMING

Page 21: Asynchronous programming FTW!

IO::ASYNCLoop interface: IO::Async::LoopYou can connect to hosts using itYou can add listeners to it (handles, sockets, etc.)Explicitly call "run" when ready

Page 22: Asynchronous programming FTW!

use IO::Async::Stream;use IO::Async::Loop; my $loop = IO::Async::Loop­>new;

$loop­>connect( host => "some.other.host", service => 12345, socktype => 'stream', on_stream => sub ... , on_resolve_error => sub die "Cannot resolve ­ $_[­1]" ,

on_connect_error => sub die "Cannot connect ­ $_[0] failed $_[­1]" ,);

$loop­>run;

Page 23: Asynchronous programming FTW!

on_stream => sub my ( $stream ) = @_;

$stream­>configure( on_read => sub my ( $self, $buffref, $eof ) = @_;

while( $$buffref =~ s/(.*\n)// ) say "Received a line $1";

return 0; );

$stream­>write('An initial line here');

$loop­>add($stream);

Page 24: Asynchronous programming FTW!

ANOTHER EXAMPLE

Oh hai parallel HTTP GET!

$ perl ­MIO::Async ­MNet::Async::HTTP ­E ' IO::Async­>add( my $http = Net::Async::HTTP­>new ); say for IO::Async­>await_all( map $http­>get($_) )' > list­of­URLs.txt

Page 25: Asynchronous programming FTW!

POELoop interface: POE::KernelRuns "sessions" (POE::Session)Each session is a context of eventsEach session has an ID and heapCall events in a current or different sessionExplicitly call POE::Kernel->run when ready

Page 26: Asynchronous programming FTW!

POEuse POE; # Auto­includes POE::Kernel and POE::Session.

# ... define callbacks subs (next slide) ...

for (1..10) POE::Session­>create( inline_states => _start => \&handler_start, increment => \&handler_increment, _stop => \&handler_stop, );

POE::Kernel­>run();

Page 27: Asynchronous programming FTW!

sub handler_start my ( $kernel, $heap, $session ) = @_[ KERNEL, HEAP, SESSION ]; say "Session ", $session­>ID, " has started"; $heap­>'count' = 0; $kernel­>yield('increment');

sub handler_increment my ( $kernel, $heap, $session ) = @_[ KERNEL, HEAP, SESSION ]; say "Session ", $session­>ID, " counted to ", ++$heap­>'count'; $kernel­>yield('increment') if $heap­>'count' < 10;

sub handler_stop say "Session ", $_[SESSION]­>ID, " has stopped";

Page 28: Asynchronous programming FTW!

sub handler_start my ( $kernel, $heap, $session ) = @_[ KERNEL, HEAP, SESSION ]; say "Session ", $session­>ID, " has started"; $heap­>'count' = 0; $kernel­>yield('increment');sub handler_increment my ( $kernel, $heap, $session ) = @_[ KERNEL, HEAP, SESSION ]; say "Session ", $session­>ID, " counted to ", ++$heap­>'count'; $kernel­>yield('increment') if $heap­>'count' < 10;sub handler_stop say "Session ", $_[SESSION]­>ID, " has stopped.\n";for (1..10) POE::Session­>create( inline_states => _start => \&handler_start, increment => \&handler_increment, _stop => \&handler_stop, );POE::Kernel­>run();

Page 29: Asynchronous programming FTW!

MORE CONDENSEDuse POE;

for (1..10) my $count = 0;

POE::Session­>create( inline_states => _start => sub say "Session ", $_[SESSION]­>ID, " has started"; POE::Kernel­>yield('increment'); , increment => sub POE::Kernel­>yield('increment') if ++$count < 10; say "Session ", $_[SESSION]­>ID, " counted to $count"; , _stop => sub say "Session ", $_[SESSION]­>ID, " has stopped"; , );

POE::Kernel­>run();

Page 30: Asynchronous programming FTW!

REFLEXWritten by author of POE"How POE would be written if I had Moose back then"Stresses composability, reusabilityIncludes plenty of additional roles

Page 31: Asynchronous programming FTW!

USING MOOSE package App; use Moose; extends 'Reflex::Base'; use Reflex::Interval; use Reflex::Trait::Watched 'watches'; watches ticker => ( isa => 'Reflex::Interval', setup => interval => 1, auto_repeat => 1 , ); sub on_ticker_tick say 'tick at ', scalar(localtime), '...'; exit App­>new()­>run_all();

Page 32: Asynchronous programming FTW!

COMPLEX? TRY THIS...use Reflex::Interval; my $t = Reflex::Interval­>new( interval => 1, auto_repeat => 1, on_tick => sub say 'timer ticked' ,); $t­>run_all();

Page 33: Asynchronous programming FTW!

ANYEVENTAnyEvent is very thin and very fastWas written to support as many loops as possible... that conform to the author's rules of compatibilityDoes not use a loop handler, simply runsDoes use conditional variablesHas AE for faster performance

Page 34: Asynchronous programming FTW!

use AnyEvent;my $count = 0;my $cv = AnyEvent­>condvar;my $t = AnyEvent­>timer( after => 2, interval => 0.6, cb => sub say 'The time is now: ', AnyEvent­>now; ++$count == 10 and $cv­>send; ,);

$cv­>recv;

Page 35: Asynchronous programming FTW!

my $w; $w = AnyEvent­>io( fh => \*STDIN, poll => 'r', cb => sub chomp ( my $input = ); say "read: $input"; undef $w; ,);

Page 36: Asynchronous programming FTW!

USAGES OF ASYNCHRONOUS CODEGUIServices (HTTP/SMTP/etc.)PerformanceOff-loading tasks

Page 37: Asynchronous programming FTW!

THANK YOU