Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> czy da sie przyspieszyć copy()?, optymalizacja skryptu
siutek
post 3.03.2011, 12:30:56
Post #1





Grupa: Zarejestrowani
Postów: 173
Pomógł: 1
Dołączył: 26.10.2005
Skąd: Toruń

Ostrzeżenie: (0%)
-----


Witam,
Przygotowuję małą aplikację generującą miniaturki aukcji allegro (w oparciu o Allegro WebApi).
Założenie jest takie, że co 15 minut program sprawdza czy pojawily się nowe oferty w aukcjach, czy zmienila się cena, itp itd. Przy okazji kopiuje miniaturke zdjecia z serwerow alllegro, wczesniej jednak sprawdzam czy nie mam już tego zdjęcia na swoim serwerze, bo po co kopiowac kilka razy to samo?

No i problem z jakim przyszlo mi się zmierzyc, to problem wydajnośći, czasu wykonywania.
- W najgorszym wypadku, aby wygenerować 6 miniaturek, skrypt potrzebuje prawie 8 sekund.
- W najlepszym, gdy nie musze kopiować żadnych miniaturek z zewnatrz wygenerowanie tych 6 grafik trwa okolo 2,5 sekundy

wyliczylem sobie, że samo kopiowanie miniaturki trwa ok 0,8 sekundy.

Jesli używam tego skryptu sam - problemu nie ma.
Jednak chce to udostepnic wiekszej rzeszy ludzi - komercyjnie.

w momencie gdy z systemu zacznie korzystac juz ponad setka ludzi (co wydaje mi sie liczbą śmiesznie małą) czas wykonywania calego skryptu zbliza sie do magicznej granicy 15 minut!! a przecież Cron ma za zadanie co 15 minut odpalac skrypt by zaktualizowac miniaturki.

poniżej wrzucam kod, może ktoś coś z niego wyczyta...

ktoś ma pomysł jak to poprawić? a może należałoby wykorzystać tu inną technologięquestionmark.gif Czekam na jakieś sugestie...

  1. <?php
  2. //error_reporting(E_ALL);
  3. function getmicrotime(){
  4. list($usec, $sec) = explode(" ",microtime());
  5. return ((float)$usec + (float)$sec);
  6. }
  7. $timeStart = getmicrotime();
  8. require_once('/home/siutek/mojaStrona.pl/config.php');
  9. require_once('/home/siutek/mojaStrona.pl/lib/nusoap.php');
  10. $client = new soapclient('http://webapi.allegro.pl/uploader.php?wsdl', true);
  11. $client->decode_utf8 = false;
  12.  
  13. $panele = getList("panels",array("act"=>1));
  14. if(is_array($panele)){
  15. foreach($panele as $p){
  16.  
  17. $userItems = $client->call("doGetUserItems",array("user-id"=>$p["usrAllId"],"webapi-key"=>$configWebApi["apiKey"],"country-id"=>$configWebApi["country"],"limit"=>100));
  18.  
  19. $user = getRecord("users",$p["usrId"]);
  20. if(!file_exists("/home/siutek/mojaStrona.pl/userFiles/".$user["login"]."/panelImg/")) @mkdir("/home/siutek/mojaStrona.pl/usersFiles/".$user["login"]."/panelImg/",0755);
  21.  
  22. if(is_array($userItems["user-item-list"]) && count($userItems["user-item-list"])>0){
  23. $userItemsArr = Array();
  24. shuffle($userItems["user-item-list"]);
  25. $r=1;
  26. $timeForStart = getmicrotime();
  27. foreach($userItems["user-item-list"] as $uI){
  28.  
  29. $newImgName = substr($uI["it-thumb-url"],(strrpos($uI["it-thumb-url"],"/")+1));
  30. if(!file_exists("/home/siutek/mojaStrona.pl/usersFiles/".$user["login"]."/panelImg/".$newImgName.".jpg")) {
  31. copy($uI["it-thumb-url"],"/home/siutek/mojaStrona.pl/usersFiles/".$user["login"]."/panelImg/".$newImgName.".jpg");
  32. $copyImg = " (skopiowano) ";
  33. } else {
  34. $copyImg = " (nie skopiowano) ";
  35. }
  36.  
  37. if($r<=($p["columns"]*$p["rows"])) {
  38. $hSize=200;
  39. $xSize=180;
  40.  
  41. $img = ImageCreateTrueColor($xSize, $hSize);
  42. $img2 = ImageCreateFromJpeg("/home/siutek/mojaStrona.pl/usersFiles/".$user["login"]."/panelImg/".$newImgName.".jpg");
  43.  
  44. $white = ImageColorAllocate($img, 255, 255, 255);
  45. $grey = imagecolorallocate($img, 230, 230, 230);
  46. $black = imagecolorallocate($img, 0, 0, 0);
  47. $red = imagecolorallocate($img, 255, 0, 0);
  48.  
  49. ImageFill($img, 0, 0, $white);
  50. ImageFilledRectangle($img, 0, 0, 180, 16, $grey);
  51. ImageFilledRectangle($img, 0, 113, 180, 164, $grey);
  52.  
  53. imagecopy($img,$img2,26,17,0,0,128,96);
  54.  
  55.  
  56. $size = 8;
  57. $fontB = "/home/siutek/mojaStrona.pl/font/verdanab.ttf";
  58. $fontR = "/home/siutek/mojaStrona.pl/font/verdana.ttf";
  59.  
  60. if(($uI["it-time-left"]<3600) && $uI["it-time-left"]>60) {
  61.  
  62. $leftTimeVal = floor($uI["it-time-left"]/60)." min";
  63.  
  64. } elseif ($uI["it-time-left"]<60) {
  65.  
  66. $leftTimeVal = "poniżej minuty";
  67.  
  68. } elseif (($uI["it-time-left"]>3600) && ($uI["it-time-left"]<86400)) {
  69.  
  70. $leftTimeVal = floor($uI["it-time-left"]/3600)." godz.";
  71.  
  72. } else {
  73. $leftTimeVal = floor($uI["it-time-left"]/86400);
  74. if ($leftTimeVal==1) $leftTimeVal.=" dzień";
  75. else $leftTimeVal.=" dni";
  76. }
  77.  
  78. $timeLeftBox2 = imagettfbbox($size, 0, $fontB, $leftTimeVal);
  79. $tlbX = $timeLeftBox2[2]-$timeLeftBox2[0];
  80. imagettftext($img, $size, 0, (175-$tlbX), 12, $black, $fontB, $leftTimeVal);
  81.  
  82. $timeLeftBox1 = imagettfbbox($size, 0, $fontR, "do końca ");
  83. $tlbX = 180-($timeLeftBox1[2]-$timeLeftBox1[0])-$tlbX;
  84. imagettftext($img, $size, 0, $tlbX-5, 12, $black, $fontR, "do końca ");
  85.  
  86. if($uI["it-bid-count"]>0){
  87. imagettftext($img, $size, 0, 5, 12, $red, $fontR, "Ofert: ".$uI["it-bid-count"]);
  88. }
  89. if($uI["it-buy-now-price"]==0){
  90. $price = imagettfbbox(10, 0, $fontB, "Cena: ".number_format($uI["it-price"], 2,","," ")."zł");
  91. $priceX = (180-($price[2]-$price[0]))/2;
  92. imagettftext($img, 10, 0, $priceX, 186, $black, $fontB, "Cena: ".number_format($uI["it-price"], 2,","," ")."zł");
  93. } else {
  94. $price = imagettfbbox(10, 0, $fontB, "Kup teraz: ".number_format($uI["it-buy-now-price"], 2,","," ")."zł");
  95. $priceX = (180-($price[2]-$price[0]))/2;
  96. imagettftext($img, 10, 0, $priceX, 186, $black, $fontB, "Kup teraz: ".number_format($uI["it-buy-now-price"], 2,","," ")."zł");
  97. }
  98.  
  99. $itemNameArr = explode(" ",$uI["it-name"]);
  100.  
  101. writeTextImg($itemNameArr,130,1);
  102. if(is_array($itemNameArr)) writeTextImg($itemNameArr,144,2);
  103. if(is_array($itemNameArr)) writeTextImg($itemNameArr,158,2);
  104. imagejpeg($img, "/home/siutek/mojaStrona.pl/usersFiles/".$user["login"]."/panelImg/".$r.".jpg");
  105. imagedestroy($img);
  106.  
  107. $userItemsArr[$r]=$uI["it-id"];
  108.  
  109. if($_SERVER["SERVER_ADDR"]=="127.0.0.1") echo "<a href='./link.php?panel=".base64_encode($p["id"])."&item=".$r."'><img src='./usersFiles/".$user["login"]."/panelImg/".$r.".jpg' style='border:0px;'></a><br>".$uI["it-id"]."<br>";
  110.  
  111. echo "wygenerowano ".$r.".jpg ".$copyImg." po ".(getmicrotime()-$timeForStart)." od rozpoczecia petli\n";
  112. $r++;
  113. unset($leftTimeVal);
  114.  
  115. } else {
  116. break;
  117. }
  118. unset($newImgName);
  119. }
  120. updateData("panels",array("items"=>serialize($userItemsArr),"id"=>$p["id"]));
  121. } else {
  122. for($r=1;$r<=($p["columns"]*$p["rows"]);$r++) {
  123. copy("/home/siutek/mojaStrona.pl/pix/itemPanelEmpty.jpg","/home/siutek/mojaStrona.pl/usersFiles/".$user["login"]."/panelImg/".$r.".jpg");
  124. }
  125. updateData("panels",array("items"=>"","id"=>$p["id"]));
  126. }
  127. }
  128. $timeEnd = getmicrotime();
  129.  
  130. echo "Czas wykonywania: ".($timeEnd-$timeStart);
  131. }
  132. ?>
Go to the top of the page
+Quote Post
 
Start new topic
Odpowiedzi (1 - 4)
kiler129
post 5.03.2011, 02:40:44
Post #2





Grupa: Zarejestrowani
Postów: 566
Pomógł: 35
Dołączył: 21.06.2006

Ostrzeżenie: (0%)
-----


Ma być szybciej? Użyj imagemagic zamiast gd2 to po pierwsze.
Po 2 sprawdź jak z tym kopiowaniem ... może zwyczajnie dysk na serwerze jest powolny (masz shared host czy dedyka?).

Kolejna sprawa - workery na prawdę warto przepisać do jakiegoś kompilowanego języka. Nie chce tutaj wywołać wojny kolejnej ale php nigdy demonem szybkości w takich operacjach nie był - tak prosty kod możesz z powodzeniem przepisać do C++, lub chcoiaż jego "najcięższą" część.


--------------------
flexiCMS v2 [|||||||+--] 75% done
Go to the top of the page
+Quote Post
wNogachSpisz
post 5.03.2011, 03:27:34
Post #3





Grupa: Zarejestrowani
Postów: 1 233
Pomógł: 87
Dołączył: 6.03.2009

Ostrzeżenie: (40%)
XX---


Format JPEG pozwala na przechowanie miniaturki w metadanych.
Oznacza to, że gotowa miniaturka jest ukryta wewnątrz oryginalnego obrazka.
Do "wyciągnięcia" takiej miniaturki służy funkcja exif_thumbnail.
Oczywiście nie każdy JPEG będzie ją miał, to zależy generalnie od tago jakim algorytmem kompresującym grafika była ostatnio dręczona.
Nie wnikałem które programy zostawiają te dane a które usuwają,
nie wiem też jak sprawa wygląda w przypadku allegro, trzeba by poświęcić te 15 minut i sprawdzić.

Nie widzę abyś używał funkcji imagecopyresampled
za to widzę że stosujesz imagecopy i w rezultacie i zamiast ładnej miniaturki dostajesz przewlekłą kwadratoliozę sierpowatą.

Tak czy inaczej..
Optymalizowanie skryptów przetwarzających obrazki to rozległy temat.
Próba wykonania tu dobrej roboty bez wiedzy jak działają algorytmy GD2 przypomina błądzenie w ciemnościach.
Pozostaje metoda prób i błędow, przyda się tez odrobina zdrowego rozsądku..

Moje dobre rady, będące jednocześnie strzałami na ślepo:
- Zmniejsz wielkości oryginalnego obrazka, przypuszczalnie skrypt będzie działał szybciej kiedy przyjdzie mu wygenerować miniaturkę z grafiki o mnieszym rozmiarze..
- Ustal czy ImagesMagic nie radzi sobie lepiej z tworzeniem thumbinali..
- Generuj "na szybko" miniaturke o gorszych parametrach i kolejkuj generowanie miniaturki o parametrach docelowych aby uniknąć chwilowych przeciążeń serwera.


Powodzenia!

Ten post edytował wNogachSpisz 5.03.2011, 03:29:44
Go to the top of the page
+Quote Post
siutek
post 7.03.2011, 08:52:25
Post #4





Grupa: Zarejestrowani
Postów: 173
Pomógł: 1
Dołączył: 26.10.2005
Skąd: Toruń

Ostrzeżenie: (0%)
-----


jak narazie korzystam z serwera wirtualnego (DreamHost), ale mysle ze gdy przyjdzie krytyczny moment, bedzie mnie stac na serwer dedykowany.
Jednak nie wiem na ile to pomoze, bo nie o predkosc wykonywania nowej grafiki w chwili obecnej chodzi, a o predkosc kopiowania jej pierwowzoru...

z serwerow allegro kopiuje naprawde małe pliki: 128x96px, wiec nie mam sie co bawic w wyciaganie danych EXIF.
Myslalem tez o ImageMagic, i w sumie bede musial spróbowac, ale mysle ze zyskam stosunkowo nie wiele.
Dlatego po glowie chodzi mi juz wykorzystanie innej technologii, ale nie wiem jakiej... poza tym nie znam innej niz PHP - ale jesli bedzie trzeba to sie naucze tongue.gif
Go to the top of the page
+Quote Post
zegarek84
post 7.03.2011, 10:24:21
Post #5





Grupa: Zarejestrowani
Postów: 1 332
Pomógł: 294
Dołączył: 12.10.2008
Skąd: Olkusz

Ostrzeżenie: (0%)
-----


nie analizowałem dokładnie skryptu ale wygląda na to, że najwęższym gardłem są synchroniczne połączenia z netem po zapytania i soap i obrazki...

skoro łączysz się aż tyle razy (z twoich wyliczeń i różnicy wynika, że za każdym razem średnio pobierasz 5-6 minaturek + połączenie jeszcze z samą stroną przez SOAP) wykonujesz około 500 połączeń dla 100 userów na same obrazki i to liniowo - skrypt jest wstrzymywany do czasu pobrania poprzedniego - rozwiązaniem może być połączenie asynchroniczne lub chociaż podczymanie połączenia jeśli serwer allegro to wspiera 'keep-alive'... obrazki pobrać możesz asynchronicznie za pomocą curl_multi lub socketów:
http://wezfurlong.org/blog/2005/may/guru-multiplexing
oczywiście wtedy logikę wykonywania pewnych czynności pasuje przerzucić na zdarzeniówkę...

możesz jeszcze spróbować porozbijać skrypt na osobne wykonywanie procesu w tle dla danego usera - ale wyrzucenie wszystkich 100 na konkurujące procesy nie będzie też najlepszym pomysłem:
http://robert.accettura.com/blog/2006/09/1...ssing-with-php/


--------------------
Jeśli twoja ręka rusza do przodu powstrzymaj swój gniew; gdy wyprzedza cię twój gniew - wycofaj rękę.

Go to the top of the page
+Quote Post

Reply to this topicStart new topic
1 Użytkowników czyta ten temat (1 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Wersja Lo-Fi Aktualny czas: 25.07.2025 - 10:48