Fórum Root.cz
Hlavní témata => Vývoj => Téma založeno: beer 21. 02. 2018, 12:32:59
-
Ahoj, vytvořil jsem si soubor pro optimalizaci obrázků na web serveru. Konfigurační příklady, které jsem na webu našel, byly velmi neefektivní, protože jedou jen v jednom vlákně a zkouší i soubory, které již byly optimalizovány.
Napadlo mne, že by bylo efektivnější obrázky nejprve seřadit dle velikosti a zařadit do fronty. To mi jakžtakž funguje, ale jen na jednom stroji s debianem 9, na ubuntu 17.10 mám chybové hlášky o tom, že to někde nemá ve složce přístup (zkoušel jsem do /tmp přesunout pár obrázků a zkoušel to tam), obrázky se ale v /tmp neoptimalizovali, přitom jsem použil stejný postup jako na web serveru mujscript.sh /tmp/.
Koukal jsem na nějaké příklady paralelního zpracování, ale moc se v tom neorientuji. Koukal jsem i na program Parallel, ale ne že bych z toho byl zrovna moudrý.
Zde je můj současný skript:
#!/bin/bash
target="$1"
jpgfronta="$(mktemp)"
pngfronta="$(mktemp)"
find "${target}/" -type f -iname *.jp*g -exec du -a {} + | sort -n -r | cut -f 2 >"$jpgfronta"
find "${target}/" -type f -iname *.png -exec du -a {} + | sort -n -r | cut -f 2 >"$pngfronta"
while read line
do
printf "%s\n" "$line"
jpeg-recompress -q medium -l 128 -a -c -m smallfry "$(printf "%s\n" "$line")" "$(printf "%s\n" "$line")"
done < "$jpgfronta" &
while read line
do
printf "%s\n" "$line"
optipng -quiet -o7 "$(printf "%s\n" "$line")"
done < "$pngfronta" &
rm "$jpgfronta"
rm "$pngfronta"
exit
Myslím, že by bylo efektivnější, kdyby se zpracovávali najednou soubory dle počtu jader, jedno jádro by se nechalo nevyužité. Ve frontě jsou názvy souborů pro zpracování, v jednom sloupci. Možná by bylo jednodušší soubor rozdělit do sloupců dle počtu jader -1 a zpracovávat po řádku. Na to jsem nějaký skript na webu viděl, ale nevím jak na to. Nebo prostřednictvím toho paralelu nebo xargs.
Poradí někdo, jak docílit paralelního zpracování s větší prioritou zpracování pro velké soubory?
-
ja bych se s tim vubec tak slozite nesral.
udelej si vypis (obrazkovych) souboru s vystupem do textoveho souboru: ls *.jpg > soubory,txt
soubor.txt rucne rozsekej na x kusu, podle toho kolik mas jader na tolik souboru: soubor1.txt, soubor2.txt.....souborX.txt
udelej si shel skript, ktery projizdi textovy soubor a z nazvu souboru (obrazku) v souborN.txt projedes fajly a zpracujes obrazky.
spustis skript x-krat:
./zpracovani soubor1.txt &> /dev/null &
./zpracovani soubor2.txt &> /dev/null &
./zpracovani souborX.txt &> /dev/null &
a nemusim vymyslet paralelni kraviny.
na prioritizaci kdyz zpracovavat male nebo velke obrazky se taky vyprdni. az ty skripty dojedou, tak dojedou.
-
ja jsem si takhle jednoduse kdysi v praveku na pocitacovem clusteru graboval cd a wav do mp3.
-
Udělal bych to pomocí nástroje
make
. Příkladů musí být na internetu tuny, umí i paralelní zpracování.
Předpokladem je, že optimalizované verze budou v jiném adresáři (nebo budou odlišené názvem).
-
Udělal bych to pomocí nástroje make
. Příkladů musí být na internetu tuny, umí i paralelní zpracování.
Předpokladem je, že optimalizované verze budou v jiném adresáři (nebo budou odlišené názvem).
Ten předpoklad na mém malém web serveru nelze splnit. Uživatel nahraje obrázek, wordpress z toho obrázku udělá x dalších obrázků - například:
uživatel nahraje
centruminvestic.cz/wp-content/uploads/2018/02/electrum-ltc.jpg (http://centruminvestic.cz/wp-content/uploads/2018/02/electrum-ltc.jpg)
a wordpress udělá:
(http://centruminvestic.cz/wp-content/uploads/2018/02/electrum-ltc-150x107.jpg)
(http://centruminvestic.cz/wp-content/uploads/2018/02/electrum-ltc-230x230.jpg)
(http://centruminvestic.cz/wp-content/uploads/2018/02/electrum-ltc-270x270.jpg)
(http://centruminvestic.cz/wp-content/uploads/2018/02/electrum-ltc-300x214.jpg)
(http://centruminvestic.cz/wp-content/uploads/2018/02/electrum-ltc-606x300.jpg)
(http://centruminvestic.cz/wp-content/uploads/2018/02/electrum-ltc-606x350.jpg)
(http://centruminvestic.cz/wp-content/uploads/2018/02/electrum-ltc.jpg)
Navíc kdyby se optimalizovalo do jiné složky, nezobrazoval by se na webu optimalizovaný obrázek. Rovněž je potřeba na serveru šetřit místem.
ja bych se s tim vubec tak slozite nesral.
udelej si vypis (obrazkovych) souboru s vystupem do textoveho souboru: ls *.jpg > soubory,txt
soubor.txt rucne rozsekej na x kusu, podle toho kolik mas jader na tolik souboru: soubor1.txt, soubor2.txt.....souborX.txt
udelej si shel skript, ktery projizdi textovy soubor a z nazvu souboru (obrazku) v souborN.txt projedes fajly a zpracujes obrazky.
spustis skript x-krat:
./zpracovani soubor1.txt &> /dev/null &
./zpracovani soubor2.txt &> /dev/null &
./zpracovani souborX.txt &> /dev/null &
a nemusim vymyslet paralelni kraviny.
na prioritizaci kdyz zpracovavat male nebo velke obrazky se taky vyprdni. az ty skripty dojedou, tak dojedou.
Je to na webserveru, kde to script spouštím cronem. To ruční rozsekání je pro mne problém. Dejme tomu, že tam mám 4 jádra a chtěl bych tedy vždy spouštět 3x.
-
Udělal bych to pomocí nástroje make
. Příkladů musí být na internetu tuny, umí i paralelní zpracování.
Předpokladem je, že optimalizované verze budou v jiném adresáři (nebo budou odlišené názvem).
Mrknu na to, není to ale kanón na vrabce? A makem lze soubor po řádcích rozdělit na stejně velké části?
-
Skus pozriet aj https://ninja-build.org/
Na tej stranke je aj zoznam generatorov konfigurakov (napr. kniznica pre python).
Cize napises subor build.ninja, kde budu napisane pravidla ako sa optimalizuju obrazky, a zoznam obrazkov,
a on ti to pospusta paralelne (bud mu povies kolko jadier alebo si tipne sam).
-
Vypadá to zajímavě, ale asi další kanón na vrabce. Ono se ti to řekne jednoduše, napíšeš si soubor build.ninja :-).
Rád bych šel cestou vrstvení standardních jednoúčelových nástrojů, aby to bylo čitelné pro mne i pro ostatní. Spočítání řádků přes wc, spočítání kolik odříznout kam přes dc, a pak případně použít head, tail či sed na vytvoření 3 různých front a & je hodit na pozadí.
Zkusím metodou pokus omyl :-).
-
Nejjednodušší by bylo asi použití xargs, ale neumím to
zkusil jsem nahradit
while read line
do
printf "%s\n" "$line"
jpeg-recompress -q medium -l 128 -a -c -m smallfry "$(printf "%s\n" "$line")" "$(printf "%s\n" "$line")"
done < "$jpgfronta" &
tímto:
while read line
do
printf "%s\n" "$line"
"$(printf "%s\n" "$line")" "$(printf "%s\n" "$line")" | xargs --max-args=1 --max-procs=3 jpeg-recompress -q medium -l 128 -a -c -m smallfry
done < "$jpgfronta"
Ale mám tam nějakou chybu, obrázky to spouští jako spustitelné soubory a nepředává to cesty.
-
A co třeba jen tevřít obrázky (případně přes search parametricky najít/filtrovat) v xnview a dát hromadnou konverzi?Mám ocit, že program nevyužívá jádra CPU. Případně Zoner Photo studio, zdarma
ja jsem si takhle jednoduse kdysi v praveku na pocitacovem clusteru graboval cd a wav do mp3.
Jakože jednotlivé thready ripovaly jednotlivé skladby?
-
A co třeba jen tevřít obrázky (případně přes search parametricky najít/filtrovat) v xnview a dát hromadnou konverzi?Mám ocit, že program nevyužívá jádra CPU. Případně Zoner Photo studio, zdarma
Používám Debian a Ubuntu. Na serveru nemám grafické prostředí.
ja jsem si takhle jednoduse kdysi v praveku na pocitacovem clusteru graboval cd a wav do mp3.
Jakože jednotlivé thready ripovaly jednotlivé skladby?
Nemůžu mluvit za adsfasdfasdfasd, ale řekl bych, že určitě takhle ne, laser bývá v mechanikách jen jeden. Spíše rippování do wavu v jednom vláknu a paralelní konverze všech wavů potom do komprimovaného formátu.
-
Nejjednodušší by bylo asi použití xargs, ale neumím to
zkusil jsem nahradit
while read line
do
printf "%s\n" "$line"
jpeg-recompress -q medium -l 128 -a -c -m smallfry "$(printf "%s\n" "$line")" "$(printf "%s\n" "$line")"
done < "$jpgfronta" &
tímto:
while read line
do
printf "%s\n" "$line"
"$(printf "%s\n" "$line")" "$(printf "%s\n" "$line")" | xargs --max-args=1 --max-procs=3 jpeg-recompress -q medium -l 128 -a -c -m smallfry
done < "$jpgfronta"
Ale mám tam nějakou chybu, obrázky to spouští jako spustitelné soubory a nepředává to cesty.
ten jpeg-recompress žere dva stejný argumenty?
přes rouru pošleš jen jeden a pak xargs -I{} a použiješ {} tam, kde chceš ty argumenty
další možnost je gnu parallel, ale xargs toto zvládne dobře a je všude
-
žere, jsou povinné, zdrojový a cílový soubor. Když je to stejné, tak se optimalizuje soubor za běhu a zapíše se změna jen v případě, že soubor nebyl již optimalizovaný předtím, jpeg-recompress to řeší přidáním poznámky do metadat a při dalším spuštění nad stejným souborem soubor jednoduše přeskočí. Na rozdíl od optipng, to je hrozná brzda, která se snaží optimalizovat již optimalizované.
Vyzkouším, díky
-
a co kdybys proste misto GD pouzil ve WP imagick pro generovani nahledu a dal mu patricne parametry?
-
Udělal bych to pomocí nástroje make
. Příkladů musí být na internetu tuny, umí i paralelní zpracování.
Předpokladem je, že optimalizované verze budou v jiném adresáři (nebo budou odlišené názvem).
Ten předpoklad na mém malém web serveru nelze splnit. Uživatel nahraje obrázek, wordpress z toho obrázku udělá x dalších obrázků - například:
Můžete udělat nějaký „značkovací“ soubor. Dejme tomu, že obrázek bude třeba IMG_001.JPG, vy ho zoptimalizujete a uděláte soubor např. IMG_001.DONE, podle kterého pak make sám pozná, že už nemá na IMG_001.JPG sahat, pokud není JPG novější než DONE.
Kanón na vrabce to asi není, make je přesně ten jednoúčelový nástroj, který dělá dobře, co má:
# Makefile:
SRCDIR := .
SRCFILES := $(wildcard $(SRCDIR)/*.jpg)
TRGFILES := $(patsubst $(SRCDIR)/%.jpg,$(SRCDIR)/%.done,$(SRCFILES))
all: $(SRCFILES) $(TRGFILES)
# @echo "Make $@: from: $?";
%.done : %.jpg
@echo "Make: $@ from: $?";
@echo "*** Here you should optimalize: $? ***"
@touch $@;
clean:
@rm -vf $(TRGFILES);
#eof
Použití:
make clean # odstranit .done soubory
make all # zpracovat obrázky
make all -j 3 # toto by mělo spustit 3 paralelní úlohy
-
Tak snad vyřešeno. S tím xargem mi to nešlo, parallel vypadá jednodušeji.
Aktuální verze skriptu:
#!/bin/bash
target="$1"
jpgfronta="$(mktemp)"
pngfronta="$(mktemp)"
find "$target" -type f -iname *.jp*g -exec du -a {} + | sort -n -r | cut -f 2 >"$jpgfronta"
find "$target" -type f -iname *.png -exec du -a {} + | sort -n -r | cut -f 2 >"$pngfronta"
cat "$jpgfronta" | parallel jpeg-recompress -q medium -l 128 -a -c -m smallfry \{} \{}
cat "$pngfronta" | parallel optipng -o7 \{} \{}
rm "$jpgfronta"
rm "$pngfronta"
exit
Funguje to pěkně rychle. Narozdíl od doplňků je to univerzální, nasadím to i na databázi fotek, protože opticky nepoznám rozdíl v kvalitě. A proč používám jpeg-recompress? Je to založené na mozjpeg od mozilly a asi nic efektivnějšího aktuálně není. Google má tuším něco podobného, ale to jsem nezkoušel.
-
Tak funguje to napůl. Na debianu 9 bez problémů, na destkopu s ubuntu to taky dokáže vytížit na 100 % všechna jádra, ale bez jakéhokoliv výpisu a výsledek nikde. I když odstraním ty zpětná lomítka. V htopu vidím, že to něco dělá, ale žádný výstup a pořád nad stejnými soubory.
-
Ale když to pustíte znovu, bude to opět zpracovávat stejné soubory, ne? Takže když tam přibudou nějaké nové soubory, budete je zpracovávat zase všechny?
-
Když zakomentuji png, tak to projde jen od největších jpg a vyčte si to z poznámky, že ten daný soubor to již zpracovávalo a dál ho nezpracovává.
Tak funguje to i na desktopu s Ubuntu, ale protože tam mám hodně velké soubory - obrázky, které mají poměrně dost megabajt, tak se zdá, jako kdyby to pořád pracovalo a nic se neděje. Ale pak už je to lepší. Nejhorší je to u skenů, u klasické fotky cca 5 MB trvá optimalizace pár minut.
Horší je, že narozdíl od severu na desktopu někdy stroj zamrzne, když se na něm dělá něco jiného. Přece jen je desktop starší a má jen dvě jádra. Kdybych odstranil -l 128 tak by to bylo mnohem mnohem rychlejší, ale ne s tak dobrými výsledky.
-
Když zakomentuji png, tak to projde jen od největších jpg a vyčte si to z poznámky, že ten daný soubor to již zpracovávalo a dál ho nezpracovává.
Tuhle funkcionalitu ve Vašem skriptu nevidím, podle mě to zpracovává znovu všechno. A to seřazení podle velikosti je k čemu?
-
To je interní funkcionalita jpeg-recommpress, bohužel optipng to nemá.
optimages2.sh Obrázky/
File already processed by jpeg-recompress!
Metadata size is 15kb
smallfry at q=67 (40 - 95): 97.331100
smallfry at q=81 (68 - 95): 99.249321
smallfry at q=88 (82 - 95): 100.479576
smallfry at q=92 (89 - 95): 101.507240
smallfry at q=94 (93 - 95): 102.012131
smallfry at q=95 (95 - 95): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
Final optimized smallfry at q=95: 102.355392
New size is 58% of original (saved 1891 kb)
Metadata size is 15kb