Ваша команда на самом деле сводится к следующему:
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
представляет собой PNG 600x400 с прозрачностью, поэтому ваша первая линия может избежать операции компоновки и сэкономить 16% времени обработки, изменив ее на:
convert -background none 1.png -fill ... -colorize 100% \
\(2.png ..
\(3.png ...
Пункт 2
Я поставил эквивалент вашей команды в петлю и сделал 100 итераций и она занимает 15 секунд. Затем я изменил все ваши чтения PNG-файлов на файлы MPC
- или файлы Magix Pixel Cache. Это сократило время обработки до чуть менее 10 секунд, то есть на 33%. Magic Pixel Cache - это всего лишь предварительно распакованный, предварительно декодированный файл, который можно читать непосредственно в память без какого-либо усилия процессора. Вы можете предварительно создать их, когда ваш каталог изменится и сохранит их вместе с файлами 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
Вы определенно должны работать параллельно - что даст наибольшие выгоды всех. Это очень просто с GNU Parallel - example here.
Если вы используете 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);
, а затем запустить несколько рабочих, которые все сидят там делают 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);
Если я запустить один процесс Парогенератора выше, и заставить его генерировать 100 000 изображений по 200 кбайт каждый, и читать их с 4 рабочими процессами на моей разумной спецификации iMac, это занимает 59 секунд, или около 1700 изображений/с могут проходить через REDIS.
Каковы размеры пикселей «активы/изображения/базы/base_image_69509021433289153_8_0.png'? И размер файла? Каковы спецификации процессора и оперативной памяти сервера? Сколько базовых изображений у вас есть вообще? –