sql >> データベース >  >> NoSQL >> Redis

redis/php-resqueを使用した同時ImageMagickリクエストの最適化

    あなたのコマンドは実際にはこれに要約されます:

    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
    

    私の考えは次のとおりです:

    ポイント1:

    最初の-composite 空白のキャンバスに置くのは無意味に思えます-おそらく1.png は透明度のある600x400PNGであるため、最初の行で合成操作を回避し、次のように変更することで処理時間を16%節約できます。

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

    ポイント2

    私はあなたのコマンドに相当するものをループに入れ、100回の反復を行いました。15秒かかります。次に、PNGファイルのすべての読み取りをMPCの読み取りに変更しました ファイル-またはMagickPixelCacheファイル。これにより、処理時間が10秒弱、つまり33%短縮されました。 Magic Pixel Cacheは、事前に解凍され、事前にデコードされたファイルであり、CPUの負担なしにメモリに直接読み取ることができます。カタログが変更されるたびにそれらを事前に作成し、PNGファイルと一緒に保存することができます。あなたがするものを作るために

    convert image.png image.mpc
    

    image.mpcが表示されます およびimage.cache 。次に、コードを次のように変更するだけです。

    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
    

    ポイント3

    残念ながら、あなたはまだ私の質問に答えていませんが、アセットカタログが大きすぎない場合は、システムの起動時にそれ(または上記のMPC同等物)をRAMディスクに置くことができます。

    ポイント4

    あなたは間違いなく並行して実行する必要があります-それはすべての中で最大の利益をもたらすでしょう。 GNUParallelを使用すると非常に簡単です-ここに例があります。

    REDISを使用している場合は、実際にはそれよりも簡単です。 LPUSHだけ MIMEでエンコードされた画像を次のようにREDISリストに追加します:

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

    次に、そこに座ってBLPOPの仕事をしている複数のワーカーを実行します

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

    上記のように1つのジェネレータープロセスを実行し、それぞれ200kBの100,000の画像を生成し、妥当な仕様のiMacで4つのワーカープロセスでそれらを読み取ると、59秒かかります。つまり、約1,700画像/秒でREDISを通過できます。



    1. 集約されたカタログツリー検索結果をRedisに保存する方法

    2. SQLを使用したMongoDB結合のリンクと作成:パート3

    3. spring-data-mongodbをマルチテナントにする

    4. MongoError:タイプ:ポイントのオブジェクトからジオキーを抽出できません