sql >> Databáze >  >> NoSQL >> Redis

Optimalizace souběžných požadavků ImageMagick pomocí redis/php-resque

Váš příkaz se ve skutečnosti scvrkává na toto:

convert -size 600x400 xc:none                                 \
    \( 1.png -fill rgb\(x,y,z\) -colorize 100% \) -composite  \
    \( 2.png -fill rgb\(x,y,z\) -colorize 100% \) -composite  \
    \( 3.png -fill rgb\(x,y,z\) -colorize 100% \) -composite  \
    \( 4.png -fill rgb\(x,y,z\) -colorize 100% \) -composite  \
    \( 5.png -fill rgb\(x,y,z\) -colorize 100% \) -composite  \
    \( 6.png -fill rgb\(x,y,z\) -colorize 100% \) -composite  \
    result.png

Moje myšlenky jsou následující:

Bod 1:

První -composite na prázdné plátno se zdá zbytečné - pravděpodobně 1.png je 600x400 PNG s průhledností, takže váš první řádek se může vyhnout operaci skládání a ušetřit 16 % času zpracování změnou na:

convert -background none 1.png -fill ... -colorize 100% \
   \( 2.png ..
   \( 3.png ...

Bod 2

Vložil jsem ekvivalent vašeho příkazu do smyčky a provedl 100 iterací a trvá to 15 sekund. Poté jsem změnil všechna vaše čtení souborů PNG na čtení MPC soubory - nebo soubory Magick Pixel Cache. To zkrátilo dobu zpracování na necelých 10 sekund, tedy o 33 %. Magic Pixel Cache je pouze předem dekomprimovaný, předem dekódovaný soubor, který lze načíst přímo do paměti bez jakékoli námahy CPU. Můžete je předem vytvořit, kdykoli se váš katalog změní, a uložit je vedle souborů PNG. Chcete-li takový udělat

convert image.png image.mpc

a dostanete se z image.mpc a image.cache . Pak byste jednoduše změnili svůj kód, aby vypadal takto:

convert -size 600x400 xc:none                                 \
    \( 1.mpc -fill rgb\(x,y,z\) -colorize 100% \) -composite  \
    \( 2.mpc -fill rgb\(x,y,z\) -colorize 100% \) -composite  \
    \( 3.mpc -fill rgb\(x,y,z\) -colorize 100% \) -composite  \
    \( 4.mpc -fill rgb\(x,y,z\) -colorize 100% \) -composite  \
    \( 5.mpc -fill rgb\(x,y,z\) -colorize 100% \) -composite  \
    \( 6.mpc -fill rgb\(x,y,z\) -colorize 100% \) -composite  \
    result.png

Bod 3

Bohužel jste ještě neodpověděli na mé otázky, ale pokud váš katalog aktiv není příliš velký, můžete jej (nebo výše uvedené ekvivalenty MPC) uložit na disk RAM při startu systému.

Bod 4

Rozhodně byste měli běžet paralelně – to přinese největší zisky ze všech. S GNU Parallel je to velmi jednoduché – příklad zde.

Pokud používáte REDIS, je to ve skutečnosti jednodušší. Stačí LPUSH vaše obrázky zakódované v MIME do seznamu REDIS, jako je tento:

#!/usr/bin/perl
################################################################################
# generator.pl <number of images> <image size in bytes>
# Mark Setchell
# Base64 encodes and sends "images" of specified size to REDIS
################################################################################
use strict;
use warnings FATAL => 'all';
use Redis;
use MIME::Base64;
use Time::HiRes qw(time);

my $Debug=0;    # set to 1 for debug messages

my $nargs = $#ARGV + 1;
if ($nargs != 2) {
    print "Usage: generator.pl <number of images> <image size in bytes>\n";
    exit 1;
}

my $nimages=$ARGV[0];
my $imsize=$ARGV[1];

# Our "image"
my $image="x"x$imsize;

printf "DEBUG($$): images: $nimages, size: $imsize\n" if $Debug;

# Connection to REDIS
my $redis = Redis->new;
my $start=time;

for(my $i=0;$i<$nimages;$i++){
   my $encoded=encode_base64($image,'');
   $redis->rpush('images'=>$encoded);
   print "DEBUG($$): Sending image $i\n" if $Debug;
}
my $elapsed=time-$start;
printf "DEBUG($$): Sent $nimages images of $imsize bytes in %.3f seconds, %d images/s\n",$elapsed,int($nimages/$elapsed);

a pak spustit několik pracovníků, kteří tam všichni sedí a dělají BLPOP úlohy

#!/usr/bin/perl
################################################################################
# worker.pl
# Mark Setchell
# Reads "images" from REDIS and uudecodes them as fast as possible
################################################################################
use strict;
use warnings FATAL => 'all';
use Redis;
use MIME::Base64;
use Time::HiRes qw(time);

my $Debug=0;    # set to 1 for debug messages
my $timeout=1;  # number of seconds to wait for an image
my $i=0;

# Connection to REDIS
my $redis = Redis->new;

my $start=time;

while(1){
   #my $encoded=encode_base64($image,'');
   my (undef,$encoded)=$redis->blpop('images',$timeout);
   last if !defined $encoded;
   my $image=decode_base64($encoded);
   my $l=length($image);
   $i++; 
   print "DEBUG($$): Received image:$i, $l bytes\n" if $Debug;
}

my $elapsed=time-$start-$timeout; # since we waited that long for the last one
printf "DEBUG($$): Received $i images in %.3f seconds, %d images/s\n",$elapsed,int($i/$elapsed);

Pokud spustím jeden generátorový proces, jak je uvedeno výše, a nechám jej vygenerovat 100 000 obrázků o velikosti 200 kB a načtu je pomocí 4 pracovních procesů na mém iMacu s rozumnou specifikací, trvá to 59 sekund, neboli kolem 1 700 obrázků/s může projít přes REDIS.



  1. Nainstalujte MongoDB na Mac

  2. redis-cli přesměrován na 127.0.0.1

  3. Mongodb Healthcheck krok za krokem

  4. Django Celery nemůže dotazovat postgres db uvnitř úlohy