복붙노트

[REDIS] 레디 스를 사용하여 동시 ImageMagick이 요청을 최적화 / PHP-resque

REDIS

레디 스를 사용하여 동시 ImageMagick이 요청을 최적화 / PHP-resque

나는 이미지를 생성하는 ImageMagick를 사용하는 사이트에 일하고 있습니다. 이 사이트는 요청 수백에게 매 순간을 얻을이 충돌 할 수있는 사이트를 야기 할 ImageMagick를를 사용하는 것입니다.

우리는 별도의 서버에서 백그라운드에서 ImageMagick를 생성 할 레디 스와 PHP-resque을 구현 그래서 그것은 우리의 주요 하나를 충돌하지 않도록. 문제는 정지 영상을 끝내야하는 데 시간이 오래 복용한다는 것입니다. 서버가 이러한 이미지를 처리하는 바쁜 때문에 사용자는 이미지 요청 2-3 분까지 기다려야 할 것으로 예상 할 수 있습니다.

난 당신을 줄 정보가 무엇인지 잘 모르겠지만, 나는 더 많은 조언을 찾고 있어요. 우리는 우리가 처리 할 수있는 이미지의 양까지 분명히 그런 다음, ImageMagick이 요청이 의지 도움이 속도를 초기 처리 시간을 줄일 수 있는지 생각합니다.

다음은 우리가 사용하는 ImageMagick이 스크립트의 예입니다 :

convert -size 600x400 xc:none \( ".$path."assets/images/bases/base_image_69509021433289153_8_0.png -fill rgb\(255,15,127\) -colorize 100% \) -composite \( ".$path."assets/images/bases/eye_image_60444011438514404_8_0.png -fill rgb\(15,107,255\) -colorize 100% \) -composite \( ".$path."assets/images/markings/marking_clan_8_marking_10_1433289499.png -fill rgb\(255,79,79\) -colorize 100% \) -composite \( ".$path."assets/images/bases/shading_image_893252771433289153_8_0.png -fill rgb\(135,159,255\) -colorize 100% \) -compose Multiply -composite \( ".$path."assets/images/highlight_image_629750231433289153_8_0.png -fill rgb\(27,35,36\) -colorize 100% \) -compose Overlay -composite \( ".$path."assets/images/lineart_image_433715161433289153_8_0.png -fill rgb\(0,0,0\) -colorize 100% \) -compose Over -composite ".$path."assets/generated/queue/tempt_preview_27992_userid_0_".$filename."_file.png

내 이론이 꽤 오랜 시간이 걸리는 이유 때문에 이미지를 채색하는 과정을 것입니다. 모두에서이 프로세스를 최적화 할 수있는 방법이 있습니까?

ImageMagick이 프로세스의 무거운 부하를 처리하는 몇 가지 경험을 가지고 또는 우리의 요청을 최적화 할 수있는 몇 가지 눈부시게 쉬운 방법을 볼 수있는 사람은, 나는 매우 greatful 것.

감사합니다 :)

해결법

  1. ==============================

    1.귀하의 명령은 실제로 아래로 비등 :

    귀하의 명령은 실제로 아래로 비등 :

    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 무의미한 것 - 당신의 첫 번째 줄에 변경하여 합성 작업과 처리 시간의 16 % 할인율을 피할 수 있도록 아마도 1.png가 투명성과 600x400 PNG입니다 :

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

    포인트 2

    나는 루프에 명령에 해당 넣어 100 반복을했고, 그것은 15 초 정도 걸립니다. 또는 마법 (magick) 픽셀 캐시 파일 - 나는 다음은 MPC 파일의 읽기로 PNG 파일의 읽고 모든 변경. 즉, 33 % 미만 단지 10 초, 즉 행의 처리 시간을 감소시켰다. 마법의 픽셀 캐시는 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

    불행하게도 아직 내 질문에 대한 답변하지 않은,하지만 당신의 자산 카탈로그가 너무 큰되지 않은 경우, 당신은 시스템 시작시 RAM 디스크에 그 (위 또는 MPC 등가물)을 넣을 수 있습니다.

    포인트 4

    당신은 확실히 병렬로 실행해야합니다 - 모두의 가장 큰 이익을 얻을 것이다. 여기 예 - 그것은 GNU 병렬 매우 간단합니다.

    당신은 레디 스를 사용하는 경우보다 실제로 더 쉽다. 그냥 LPUSH 당신과 같은 레디 스 목록에 이미지를 MIME 인코딩 :

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

    다음 모든 앉아 할 수있는 작업의 BLPOPs이 일을하는 것이 다수의 근로자를 실행

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

    내가 위에서 하나 개 생성 프로세스를 실행하고있는 경우가 200KB 각각 10 만 개 이미지를 생성하고, 내 합리적인 사양 아이맥 4 개 작업자 프로세스와이를 판독이 59 초 또는 약 1,700 이미지를 소요 / S는 레디 스를 통해 전달할 수 있습니다.

  2. ==============================

    2.큐는 한 번에 하나씩 처리되는? 당신이 그런 경우 한 번에 두 개 이상의 요소를 작동 그래서 병렬로 계속 실행됩니다, 동시 작업을 만들려고 있나요?

    큐는 한 번에 하나씩 처리되는? 당신이 그런 경우 한 번에 두 개 이상의 요소를 작동 그래서 병렬로 계속 실행됩니다, 동시 작업을 만들려고 있나요?

  3. from https://stackoverflow.com/questions/32256831/optimising-concurrent-imagemagick-requests-using-redis-php-resque by cc-by-sa and MIT license