Redis
 sql >> Teknologi Basis Data >  >> NoSQL >> Redis

Mengoptimalkan Permintaan ImageMagick bersamaan menggunakan redis/php-resque

Perintah Anda sebenarnya bermuara pada ini:

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

Pikiran saya adalah sebagai berikut:

Titik 1:

-composite pertama ke kanvas kosong tampaknya tidak ada gunanya - mungkin 1.png adalah PNG 600x400 dengan transparansi, sehingga baris pertama Anda dapat menghindari operasi pengomposisian dan menghemat 16% waktu pemrosesan dengan mengubah ke:

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

Titik 2

Saya menempatkan yang setara dengan perintah Anda ke dalam satu lingkaran dan melakukan 100 iterasi dan itu membutuhkan waktu 15 detik. Saya kemudian mengubah semua pembacaan file PNG Anda menjadi pembacaan MPC file - atau file Magick Pixel Cache. Itu mengurangi waktu pemrosesan menjadi hanya di bawah 10 detik, yaitu sebesar 33%. Magic Pixel Cache hanyalah file pra-dekompresi, pra-dekode yang dapat dibaca langsung ke memori tanpa upaya CPU. Anda dapat membuatnya terlebih dahulu setiap kali katalog Anda berubah dan menyimpannya di samping file PNG. Untuk membuatnya Anda lakukan

convert image.png image.mpc

dan Anda akan keluar image.mpc dan image.cache . Kemudian Anda cukup mengubah kode Anda menjadi seperti ini:

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

Titik 3

Sayangnya Anda belum menjawab pertanyaan saya, tetapi jika katalog aset Anda tidak terlalu besar, Anda dapat meletakkannya (atau MPC yang setara di atas) ke disk RAM saat sistem dinyalakan.

Titik 4

Anda pasti harus berlari secara paralel - itu akan menghasilkan keuntungan terbesar dari semuanya. Ini sangat sederhana dengan GNU Parallel - contohnya di sini.

Jika Anda menggunakan REDIS, sebenarnya lebih mudah dari itu. Cukup LPUSH gambar yang dikodekan MIME Anda ke dalam daftar REDIS seperti ini:

#!/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);

lalu jalankan beberapa pekerja yang semuanya duduk di sana melakukan BLPOP pekerjaan yang harus dilakukan

#!/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);

Jika saya menjalankan satu proses generator seperti di atas dan membuatnya menghasilkan 100.000 gambar masing-masing 200kB, dan membacanya dengan 4 proses pekerja di iMac spesifikasi wajar saya, dibutuhkan 59 detik, atau sekitar 1.700 gambar/dtk dapat melewati REDIS.



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Apa perbedaan mendasar antara pilih, epoll, kqueue, dan evport?

  2. Bagaimana cara berkomunikasi dynos Web dan Worker dengan Node.js di Heroku?

  3. Cara menganalisis dan mengoptimalkan penggunaan memori di Redis

  4. Antrian pekerjaan dengan redis menggunakan BLPOP

  5. Apakah setiap panggilan dalam panggilan multi() di phpredis menghasilkan perjalanan pulang pergi jaringan baru ke redis?