Wygenerowane w pamięci podręcznej generowane przez PHP Miniatury ładują się powoli

179

Pytanie Część A ▉ (100 nagród, przyznane)
Głównym pytaniem było, jak sprawić, by ta strona ładowała się szybciej. Najpierw musieliśmy przeczytać te wodospady. Dziękujemy wszystkim za sugestie dotyczące analizy odczytu wodospadu. Widoczne na różnych pokazanych tutaj wykresach wodospadu jest główne wąskie gardło: miniatury generowane przez PHP. Załadowanie nagród z CDN bez protokołu, zalecane przez Davida, przyniosło mi nagrodę, chociaż ogólnie moja strona była tylko o 3% szybsza i nie odpowiadała na główne wąskie gardło strony. Czas na wyjaśnienie mojego pytania i kolejna nagroda:

Pytanie Część B ▉ (100 nagród, przyznane)
Teraz skupiono się na rozwiązaniu problemu, jaki miał 6 obrazów jpg, które powodują największe opóźnienie ładowania. Te obrazy są PHP 6 generowane miniatury, malutkie i tylko 3 ~ 5 kb, ale ładowanie stosunkowo bardzo powoli. Zwróć uwagę na „ czas do pierwszego bajtu ” na różnych wykresach. Problem pozostał nierozwiązany, ale nagrodę otrzymał James, który naprawił błąd nagłówka, który podkreślił RedBot : „Warunkowe żądanie If-Modified-Since zwróciło pełną treść bez zmian”. .

Pytanie Część C my (moja ostatnia nagroda: 250 punktów)
Niestety, nawet po naprawieniu błędu nagłówka REdbot.org opóźnienie spowodowane przez obrazy generowane przez PHP pozostało nietknięte. Co, u licha, myślą te małe, wątłe miniatury 3 ~ 5Kb? Wszystkie te informacje w nagłówku mogą wysłać rakietę na Księżyc iz powrotem. Wszelkie sugestie dotyczące tego wąskiego gardła są bardzo mile widziane i traktowane jako możliwa odpowiedź, ponieważ utknąłem w tym wąskim gardle już od siedmiu miesięcy. Z góry dziękuję.

[Kilka podstawowych informacji na mojej stronie: CSS jest na górze. JS na dole (Jquery, JQuery UI, kupione menu awm / menu.js silniki, tabs js silnik, wideo swfobject.js) Czarne linie na drugim obrazie pokazują, co inicjuje, co załadować. Wściekły robot to moje zwierzę domowe „ZAM”. Jest nieszkodliwy i często szczęśliwszy.]


Załaduj Wodospad: Chronologiczny | http://webpagetest.org wprowadź opis zdjęcia tutaj


Domeny równoległe zgrupowane | http://webpagetest.org wprowadź opis zdjęcia tutaj


Site-Perf Waterfall | http://site-perf.com wprowadź opis zdjęcia tutaj


Pingdom Tools Wodospad | http://tools.pingdom.com

wprowadź opis zdjęcia tutaj


GTmetrix Waterfall | http://gtmetrix.com

wprowadź opis zdjęcia tutaj


Sam
źródło
11
Myślę, że większość przeglądarek tworzy tylko 20 połączeń na raz, więc po 20 pierwsza musi zakończyć się przed następnym uruchomieniem, stąd spowolnienie po 20
1
Myślę, że zapomniałeś zredagować pierwszą instancję swojej domeny. Przynajmniej masz resztę: D
trzydziesty
2
Nie możesz połączyć niektórych z tych obrazów w duszki?
Marcel Korpel
1
@Dagon, pamiętaj, że HTTP 1.1 RFC prosi ( SHOULD), aby klienci HTTP 1.1 korzystali z maksymalnie 2 połączeń z serwerami HTTP 1.1; HTTP 1.0 jest oczywiście znacznie bardziej otwarty.
sarnold 30.01.11
1
Przeglądarki @Dagon nawiążą także tylko 2 jednoczesne połączenia z dowolną domeną.
Endofag

Odpowiedzi:

61

Po pierwsze, korzystanie z tych wielu domen wymaga kilku wyszukiwań DNS. Lepiej byłoby połączyć wiele z tych obrazów w duszka zamiast rozprowadzać prośby.

Po drugie, kiedy ładuję twoją stronę, widzę większość blokowania (~ 1,25s) na all.js. Widzę, że zaczyna się od (starej wersji) jQuery. Powinieneś odwołać się do tego z Google CDN, aby nie tylko skrócić czas ładowania , ale potencjalnie całkowicie uniknąć żądania HTTP .

W szczególności najbardziej aktualne biblioteki interfejsu użytkownika jQuery i jQuery można znaleźć pod tymi adresami URL (zobacz ten post, jeśli jesteś zainteresowany, dlaczego pominąłem http:):

//ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js

//ajax.googleapis.com/ajax/libs/jqueryui/1.8.9/jquery-ui.min.js

Jeśli używasz jednego z domyślnych motywów interfejsu użytkownika jQuery, możesz również pobrać jego CSS i obrazy z CDN Google .

Z jQuery hosting zoptymalizowane, należy również łączyć awmlib2.jsi tooltiplib.jsdo jednego pliku.

Jeśli zajmiesz się tymi sprawami, powinieneś zauważyć znaczną poprawę.

Dave Ward
źródło
1
Znakomity komentarz Dave! stary 1.3 JQuery był znacznie mniejszy, więc pomyślałem, że podczas pracy może być szybszy. Ale podoba mi się twoje rekomendacje: Które z linków CDN google sugerujesz, żebym użył go jako mojego Jqyuery? Czy mogę używać tego samego sposobu javascript dla interfejsu użytkownika JQ? +1 bardzo dziękuję
Sam
2
Zdecydowanie polecam korzystanie z najnowszej wersji jQuery (obecnie 1.4.4). Po zminimalizowaniu i zgzipowaniu różnica między nimi jest tylko kilka bajtów. Zaktualizowałem odpowiedź kilkoma linkami do najnowszych wersji interfejsu użytkownika jQuery i jQuery w sieci CDN Google, których polecam użyć.
Dave Ward
1
Dobra wskazówka dotycząca ikonki, która powinna zmniejszyć liczbę otwartych połączeń z serwerem
JamesHalsall
obecnie pracuje nad zmniejszeniem otwartych połączeń (przeszedł z 40 orso do teraz 30 orso ... ostateczny push jest najtrudniejszy, ponieważ niektóre obrazy powtarzają tła i nie mogą przejść do duszka (lub ???)
Sam
Aktualizacja prędkości strony: (96%) Stopień niskiej prędkości: (90%) ... a mimo to miniatury są takie same jak zawsze!
Sam
17

Miałem podobny problem kilka dni temu i znalazłem head.js . Jest to wtyczka Javascript, która pozwala załadować wszystkie pliki JS równolegle. Mam nadzieję, że to pomaga.

000
źródło
Niesamowite! Jak mogłem to przeoczyć? +1 Idę teraz do testowania tego. Pachnie owocną nocą. Dzięki Schattenbaum!
Sam
1
Czy mogę zapytać, czy jesteś Schattenbaum ze schattenbaum.net?
Pekka
12

Jestem daleki od eksperta, ale ...

W związku z tym: „Warunkowe żądanie If-Modified-Since zwróciło pełną treść bez zmian”. i moje komentarze.

Kod użyty do wygenerowania miniaturek powinien sprawdzać, czy:

  1. Czy istnieje wersja miniatury w pamięci podręcznej?
  2. Czy wersja z pamięci podręcznej jest nowsza niż oryginalny obraz.

Jeśli którykolwiek z nich jest fałszywy, miniatura powinna zostać wygenerowana i zwrócona bez względu na wszystko. Jeśli oba są prawdziwe, należy wykonać następujące sprawdzenie:

  1. Czy istnieje nagłówek HTTP_IF_MODIFIED_SINCE
  2. Czy czas ostatniej modyfikacji wersji buforowanej jest taki sam jak HTTP_IF_MODIFIED_SINCE

Jeśli którakolwiek z tych wartości jest fałszywa, należy zwrócić miniaturę z pamięci podręcznej.

Jeśli oba są prawdziwe, należy zwrócić status 304 http. Nie jestem pewien, czy jest to wymagane, ale osobiście zwracam również nagłówki Cache-Control, Expires i Last-Modified wraz z 304.

W odniesieniu do GZipping zostałem poinformowany, że nie ma potrzeby używania obrazów GZip, więc zignoruj ​​tę część mojego komentarza.

Edycja: Nie zauważyłem twojego dodania do twojego postu.

session_cache_limiter('public');
header("Content-type: " . $this->_mime);
header("Expires: " . gmdate("D, d M Y H:i:s", time() + 2419200) . " GMT");
// I'm sure Last-Modified should be a static value. not dynamic as you have it here.
header("Last-Modified: " . gmdate("D, d M Y H:i:s",time() - 404800000) . " GMT");

Jestem również pewien, że Twój kod musi sprawdzić nagłówek HTTP_IF_MODIFIED_SINCE i zareagować na to. Samo ustawienie tych nagłówków i pliku .htaccess nie zapewni wymaganego rezultatu.

Myślę, że potrzebujesz czegoś takiego:

$date = 'D, d M Y H:i:s T'; // DATE_RFC850
$modified = filemtime($filename);
$expires = strtotime('1 year'); // 1 Year

header(sprintf('Cache-Control: %s, max-age=%s', 'public', $expires - time()));
header(sprintf('Expires: %s', date($date, $expires)));
header(sprintf('Last-Modified: %s', date($date, $modified)));
header(sprintf('Content-Type: %s', $mime));

if(isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
    if(strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) === $modified) {
        header('HTTP/1.1 304 Not Modified', true, 304);
        // Should have been an exit not a return. After sending the not modified http
        // code, the script should end and return no content.
        exit();
    }
}
// Render image data
James
źródło
James, przybrałeś istotę problemu po edycji w swojej odpowiedzi! If Modified Sinceproblem wydaje się działać teraz! Jednak długie nagłówki / czas oczekiwania na maleńkie kciuki nie zostały jeszcze rozwiązane ...
Sam
@James PS REdbot.org mówi, że nagłówek Expires ma niepoprawną wartość. Myślę, że to musi być GMT, a nie CET?
Sam
@Sam Niestety mój serwer jest w Wielkiej Brytanii, więc automatycznie generuje daty GMT. Wystarczy użyć funkcji PHP gmdate zamiast date. To powinno wygenerować datę GMT względem czasu twojego serwera.
James
1
@Sam, Twój czas oczekiwania to czas wykonania skryptu. Przejście kodu do momentu wysłania nagłówków lub odejście po wysłaniu nagłówków zajmuje dużo czasu.
James
@James, rozumiem ... Ale oprócz tego generatora miniatur php, istnieje wiele innych równorzędnych skryptów, które robią różne inne rzeczy (tłumaczenia, ładowanie menu itp.) W ułamku czasu ... ONI nie wydają się być wąskie gardła ... czy to kieruje problem, a TYLKO do generatora miniatur php?
Sam
6

Wow, trudno jest wyjaśnić rzeczy za pomocą tego obrazu. Ale tutaj niektóre próby:

  • pliki 33-36 ładują się tak późno, ponieważ są dynamicznie ładowane w swf, a swf (25) jest ładowany najpierw całkowicie przed załadowaniem jakiejkolwiek dodatkowej zawartości
  • pliki 20 i 21 są może (nie wiem, bo nie znam twojego kodu) bibliotekami ładowanymi przez all.js (11), ale do wykonania 11 czeka on całą stronę (i zasoby) załadować (powinieneś zmienić to na domready)
  • pliki 22-32 są ładowane przez te dwie biblioteki, ponownie po ich całkowitym załadowaniu
szturchać
źródło
Ciekawy punkt Domyślam się, że nie ma nic wokół SWF ... Jak mogę zmienić na domena? Mam przeczucie, co masz na myśli. Chodzi o to, kiedy javascript jest gotowy i mówi na dokumencie, czy to czy tamto? czy ten dokument. należy zastąpić przez dom.ready?
Sam
@Sam, jeśli używasz buforowania po stronie klienta (i powinieneś tak być), możesz załadować zasoby używane przez SWF do js lub ukrytych div na swojej stronie, aby kiedy SWF o nie poprosił, były już przy kliencie.
Endofag
4

Po prostu zgadnij, ponieważ tego rodzaju analiza wymaga wielu testów A / B: domena .ch wydaje się trudna do osiągnięcia (długie, zielone pasma przed nadejściem pierwszego bajtu).

Oznaczałoby to, że witryna .ch jest źle hostowana lub że twój dostawca usług internetowych nie ma dobrej drogi do nich.

Biorąc pod uwagę diagramy, może to wyjaśniać duży hit wydajności.

Na marginesie, nie jest to fajne narzędzie cuzillion które mogłyby pomóc uporządkować rzeczy w zależności od uporządkowania ressource załadunku.

Jerome WAGNER
źródło
4

Spróbuj uruchomić testy Y! Slow i Page Speed ​​na swojej stronie / stronie i postępuj zgodnie ze wskazówkami, aby rozwiązać ewentualne wąskie gardła w wydajności. Powinieneś uzyskać ogromny wzrost wydajności, gdy uzyskasz wyższy wynik w Y! Slow lub Page Speed.

Te testy pokażą ci, co jest nie tak i co zmienić.

Livingston Samuel
źródło
Dzięki! wyniki to: 92 na Page Speed ​​i 93 na Ylow. Brakuje: KEEP ALIVE = wyłączony i nieużywający CDN.
Sam
AKTUALIZACJA: odpowiednio 96 i 90 obecnie
Sam
4

Więc skrypt PHP generuje miniatury przy każdym ładowaniu strony? Po pierwsze, jeśli miniaturki obrazów nie zmieniają się tak często, czy możesz ustawić pamięć podręczną tak, aby nie musiała być analizowana przy każdym ładowaniu strony? Po drugie, czy twój skrypt PHP używa czegoś takiego jak imagecopyresampled()tworzenie miniatur? To nie jest trywialne próbkowanie i skrypt PHP nic nie zwróci, dopóki nie zakończy zmniejszania. Za pomocąimagecopymerged() zamiast tego obniży jakość obrazu, ale przyspieszy proces. A ile robisz redukcji? Czy te miniatury są o 5% większe od oryginalnego obrazu, czy o 50%? Większy rozmiar oryginalnego obrazu prawdopodobnie prowadzi do spowolnienia, ponieważ skrypt PHP musi pobrać oryginalny obraz do pamięci, zanim będzie mógł go zmniejszyć i wygenerować mniejszą miniaturę.

Midnight Lightning
źródło
Dzięki Midnight Lightning! Istnieje folder pamięci podręcznej, w którym miniatury JPG są tworzone i ponownie używane, chociaż mam wrażenie, że w tym tkwi problem skryptu, który kupiłem (i wydaje się, że działa dobrze dla innych)
Sam
2
Jeśli miniatury są buforowane, upewnij się, że skrypt pobierający je z pamięci podręcznej używa echa, readfile()a nie file_get_contents()echa, które czeka na wyjście, aż cały plik zostanie przeniesiony do pamięci skryptu PHP.
MidnightLightning
Jeszcze lepiej - jeśli pliki są buforowane, wygeneruj kod HTML w taki sposób, aby bezpośrednio pobierał buforowany obraz z dysku bez przechodzenia przez PHP. Tak właśnie robię w moich skryptach dla videodb.net
andig
„Istnieje folder pamięci podręcznej, w którym ...” i jak szybko są one usuwane z listy? Czy Twój adres URL wskazuje bezpośrednio buforowany plik lub skrypt PHP? Czy przekierowujesz lub używasz readfile ()? Czy ten sam skrypt PHP zawiera kod generowania miniatur - czy odkładasz ładowanie dużej części kodu za pomocą opcji włącz / usuń?
symcbean
4

Znalazłem adres URL twojej witryny i sprawdziłem pojedynczy plik jpg ze strony głównej. Chociaż czas ładowania jest teraz rozsądny (161 ms), czeka on na 126 ms, co jest zdecydowanie za dużo.

Twoje ostatnio zmodyfikowane nagłówki są ustawione na Sat, 01 stycznia 2011 12:00:00 GMT, co wydaje się zbyt „okrągłe”, aby być prawdziwą datą generacji ;-)

Ponieważ kontrola pamięci podręcznej ma wartość „public, max-age = 14515200”, dowolne nagłówki ostatniej modyfikacji mogą powodować problemy po 168 dniach.

W każdym razie nie jest to prawdziwy powód opóźnień.

Musisz sprawdzić, co robi generator miniatur, gdy miniatura już istnieje i co może zająć tyle czasu na sprawdzenie i dostarczenie obrazu.

Możesz zainstalować xdebug, aby profilować skrypt i sprawdzać, gdzie są wąskie gardła.

Być może cała ta rzecz korzysta z frameworka lub łączy się z jakąś bazą danych za darmo. Widziałem bardzo powolną mysql_connect () na niektórych serwerach, głównie dlatego, że łączyły się one za pomocą TCP, a nie gniazda, czasem z pewnymi problemami z DNS.

Rozumiem, że nie możesz opublikować tutaj swojego płatnego generatora, ale obawiam się, że istnieje zbyt wiele możliwych problemów ...

Kapsuła
źródło
Dzięki za detektywa i miejsce na wskazówki Capsule! Po pierwsze: nie ma bazy danych. Twoje odkrycia są takie same jak moje: czeka 90% czasu? Szalone małe kciuki. Interesujące przemyślenia na temat ostatnio modyfikowanych nagłówków, ponieważ zgodnie z postem Jamesa tutaj musiałem ustawić te ostatnie modyfikowane nagłówki na czas STATIC (stały), a nie dynamiczny / zawsze zmieniający się czas ustawiony przez generatory php gmdate. A może masz na myśli coś jeszcze? (Nominacja za nagrodę)
Sam
1
Aby być idealną, powinna odzwierciedlać rzeczywistą datę wygenerowania, na przykład poprzez uzyskanie pliku filemtime () miniatury w pamięci podręcznej. Ciekawe do przetestowania jest uzyskanie dostępu do pustego pliku PHP lub pliku PHP po prostu odbijającego „test” i zobacz, ile czekasz na ten plik. Może cały serwer działa powoli i wpływa na każdy skrypt PHP, cokolwiek robi.
Kapsułka
1
Widzę też stosunkowo duże opóźnienie w przypadku czystych plików statycznych (na przykład obrazów połączonych z kciukami), na przykład 36 ms. Na jednym z administrowanych przeze mnie serwerów (co nie jest bestią ... dwurdzeniową z 2 Gb RAL), otrzymuję prawie połowę tego, jak 20 ms na plikach statycznych.
Kapsułka
Ciekawe ... 1. jakiego oprogramowania / narzędzia online używasz do pomiaru? 2. Czy twoje szybsze pomiary o 20 ms są spójne (ile ± xx%) uważasz, że wyniki są różne? W moim przypadku jest bardzo różnie w zależności od używanego narzędzia testowego. niektóre są bardzo spójne ( gtmetrix.com ) niektóre są bardzo różne ( pingdom.com ) i trudno podać czasy w XX ms, ponieważ zmieniają się za każdym razem ...
Sam
Korzystam z karty NET Firebuga. 20ms to najszybszy czas jaki otrzymuję. Różni się od 20 do 28. Oczywiście najszybszy był również pomiar 36 ms, który zmierzyłem na twoim serwerze.
Kapsuła
4

Jeśli nie ma naprawdę dobrego powodu (zwykle nie ma), twoje obrazy nie powinny wywoływać interpretera PHP.

Utwórz regułę przepisywania dla swojego serwera WWW, który bezpośrednio obsługuje obraz, jeśli zostanie on znaleziony w systemie plików. Jeśli nie, przekieruj do skryptu PHP, aby wygenerować obraz. Podczas edycji obrazu zmień nazwę pliku obrazów, aby zmusić użytkowników posiadających wersję z pamięci podręcznej do pobrania nowo edytowanego obrazu.

Jeśli to nie zadziała przynajmniej teraz, to nie ma to nic wspólnego ze sposobem tworzenia i sprawdzania obrazów.

Goran Jurić
źródło
Dzięki Goran, nie jest to jednak eleganckie rozwiązanie, o którym marzę: myślę, że w moim przypadku jest coś podejrzanego, i że normalnie tak długo nie trwa tak długo, aby skrypt php wiedział, że przekazuje nagłówek 304 lub upiec obraz itp. i tak dzięki za sugestię, ponieważ kieruje problem z zupełnie nowej perspektywy! Co samo w sobie jest cenne +1
Sam
3

Zbadaj wykorzystanie danych sesji przez PHP. Być może (tylko być może) skrypt PHP generujący obraz czeka na zablokowanie danych sesji, które są blokowane przez wciąż wyświetlaną stronę główną lub inne skrypty renderowania obrazu. To spowodowałoby, że wszystkie optymalizacje JavaScript / przeglądarki byłyby prawie nieistotne, ponieważ przeglądarka czeka na serwer.

PHP blokuje dane sesji dla każdego uruchomionego skryptu, od momentu rozpoczęcia obsługi sesji, do momentu zakończenia skryptu lub wywołania session_write_close (). To skutecznie serializuje rzeczy. Sprawdź stronę PHP na temat sesji, zwłaszcza komentarzy, takich jak ta .

Ricardo Pardini
źródło
Dzięki za sugestie Ricardo! Wygląda na to, że Alix sugeruje to samo co ty (prawda?). W praktyce, co sugerujesz, żebym umieścił / usunął z kodu, a następnie ponownie przetestował wykresy i zgłosił? Bardzo mile widziane.
Sam
1
Tak myślę. Sugeruję zmianę skryptów generujących obrazy, aby nie były zależne od danych $ _SESSION lub podobnych (być może już nie). Następnie skorzystaj z session_write_close () tak szybko, jak to możliwe , a nawet lepiej unikaj używania sesji na tych skryptach. Sprawdź php.net/manual/en/function.session-write-close.php
Ricardo Pardini
3

To tylko dzikie przypuszczenie, ponieważ nie spojrzałem na twój kod, ale podejrzewam, że sesje mogą tutaj odgrywać pewną rolę, poniższe informacje pochodzą z wpisu w PHP Manual na session_write_close():

Dane sesji są zwykle przechowywane po zakończeniu skryptu bez potrzeby wywoływania session_write_close (), ale ponieważ dane sesji są zablokowane, aby zapobiec równoczesnym zapisom, tylko jeden skrypt może działać w sesji w dowolnym momencie. Podczas korzystania z zestawów ramek w połączeniu z sesjami będziesz doświadczać ładowania ramek jeden po drugim z powodu tego blokowania. Możesz skrócić czas potrzebny do załadowania wszystkich ramek, kończąc sesję, gdy tylko zostaną zmienione wszystkie zmienne sesji.

Tak jak powiedziałem, nie wiem, co robi twój kod, ale te wykresy wydają się dziwnie podejrzane. Miałem podobny problem, gdy kodowałem funkcję wyświetlania plików wieloczęściowych i miałem ten sam problem. Podczas serwowania dużego pliku nie mogłem uruchomić funkcji wieloczęściowej ani nie mogłem otworzyć innej strony, dopóki pobieranie nie zostanie zakończone. Dzwonienie session_write_close()naprawiło oba moje problemy.

Alix Axel
źródło
Dzięki Alix za twoją sugestię. Pytanie: czy exit();funkcja ma podobne linie jak session_write_close();? obecnie oryginalny autor kodu bada ten problem, ale wydaje się, że jest on również trochę w ciemności, ponieważ jego hojna aktualizacja kodu z lepszą obsługą If-Modified-Since wydaje się mieć takie same opóźnienia (nowy wodospad wykresy tworzyły te same wykresy, chociaż rzeczywiste wyniki worl wyglądały / odczuwały szybsze ładowanie! To bardzo dziwny problem ...
Sam
1
@Sam: Nie mogę teraz podać żadnych źródeł, ale sądzę, że exit () najpierw wywołuje wszelkie niszczyciele i / lub funkcje zarejestrowane do zamknięcia, a dopiero potem sesja jest zamykana. W każdym razie założę się, że Twój problem prawdopodobnie leży przed wywołaniem exit (). Zobacz także: stackoverflow.com/questions/1674314/…
Alix Axel
2

Czy próbowałeś zastąpić thumnails generowane przez php zwykłymi obrazami, aby zobaczyć, czy jest jakaś różnica? Problem może być związany z - błąd w kodzie php prowadzący do regeneracji miniatury przy każdym wywołaniu serwera - opóźnienie w kodzie (uśpienie ()?) Związane z problemem z zegarem - problem z dyskiem twardym powodujący bardzo zły stan wyścigu ponieważ wszystkie miniatury są ładowane / generowane jednocześnie.

Jerome WAGNER
źródło
Coś, co kiedyś myślałem, dając +1 do przeczytania moich myśli i ujawnienia pierwszego rozwiązania, które już zrobiłem. Miałem nadzieję, że normalne obrazy będą ładować się powoli, ale może to być prędkość pobierania lub coś fizycznie ograniczającego, ale zamiast tego odkryłem, że normalne zrzuty statyczne (zapisałem wygenerowane kciuki i załadowałem jako statyczne) te załadowane Ekstremalnie szybko. Więc to musi zrobić z tym, co php generator miniatur!
Sam
2

Myślę, że zamiast używać tego skryptu generującego miniatury , musisz dać TinySRC szansę na szybkie, szybkie generowanie miniaturek w chmurze. Ma bardzo prosty i łatwy w użyciu interfejs API, z którego można korzystać w następujący sposób: -

http://i.tinysrc.mobi/ [wysokość] / [szerokość] /http://domain.tld/path_to_img.jpg

[szerokość] (opcjonalnie): - Jest to szerokość w pikselach (która przesłania wielkość adaptacyjną lub rodzinną). Jeśli poprzedza je „-” lub „x”, odejmie lub zmniejszy się do procentu określonego rozmiaru.

[wysokość] (opcjonalnie): - Jest to wysokość w pikselach, jeśli występuje również szerokość. Zastępuje także dostosowywanie lub rozmiar rodziny i może być poprzedzone znakiem „-” lub „x”.

Można sprawdzić podsumowanie API tutaj


FAQ

Ile kosztuje maleSrc?

Nic.

Kiedy mogę zacząć korzystać z tinySrc?

Teraz.

Jak niezawodna jest usługa?

Nie udzielamy żadnych gwarancji dotyczących usługi tinySrc. Działa jednak na dużej rozproszonej infrastrukturze chmurowej , dzięki czemu zapewnia wysoką dostępność na całym świecie. To powinno wystarczyć na wszystkie Twoje potrzeby.

Jak szybko to jest

tinySrc buforuje obrazy o zmienionym rozmiarze w pamięci i naszym magazynie danych przez maksymalnie 24 godziny i za każdym razem nie pobierze oryginalnego obrazu. To sprawia, że ​​usługi są niezwykle szybkie z perspektywy użytkownika. (I zmniejsza obciążenie serwera jako miły efekt uboczny.)


Powodzenia. Tylko sugestia, ponieważ nie wyświetlasz nam kodu: p

Salman von Abbas
źródło
2

Ponieważ niektóre przeglądarki pobierają tylko 2 równoległe pliki do pobrania na domenę, nie możesz dodać dodatkowych domen, aby oddzielić żądania od dwóch do trzech różnych nazw hostów. np. 1.imagecdn.com 2.imagecdn.com

Tomek
źródło
+1 za twoją sugestię: dziękuję, ale jeśli przyjrzysz się bliżej mojej (przyznaje się: bardzo chaotycznym rysunkom), zobaczysz, że niektóre przedmioty pochodzą z ....... niektóre pochodzą z ........ com ... ALE de, ale może to nie działa tak dobrze, jak twoja sugestia? (Widzę, że sugerujesz poddomeny zamiast tylko innych domen).
Sam
1

Po pierwsze, musisz obsługiwać If-Modified-Sincewnioski i tak odpowiednio, jak powiedział James. Ten błąd stwierdza, że: „Kiedy pytam twój serwer, czy ten obraz został zmodyfikowany od ostatniego razu, wysyła cały obraz zamiast zwykłego tak / nie”.

Czas między połączeniem a pierwszym bajtem to na ogół czas potrzebny na uruchomienie skryptu PHP. Oczywiste jest, że coś się dzieje, gdy skrypt zaczyna działać.

  1. Czy zastanawiałeś się nad jego profilowaniem? Może to mieć pewne problemy.
  2. W połączeniu z powyższym problemem skrypt może być uruchamiany wiele razy więcej niż to konieczne. Idealnie byłoby generować kciuki tylko wtedy, gdy oryginalny obraz został zmodyfikowany i wysyłać kciuki z pamięci podręcznej dla każdego innego żądania. Czy sprawdziłeś, że skrypt generuje niepotrzebnie obrazy (np. Dla każdego żądania)?

Generowanie odpowiednich nagłówków za pomocą aplikacji jest nieco trudne, a ponadto mogą zostać zastąpione przez serwer. I jesteś narażony na nadużycia, ponieważ każdy, kto wysyła nagłówki żądań bez pamięci podręcznej, spowoduje, że generator miniatur będzie działał nieprzerwanie (i zwiększy obciążenia). Jeśli to możliwe, spróbuj zapisać wygenerowane kciuki, wywołać zapisane obrazy bezpośrednio ze swoich stron i zarządzać nagłówkami .htaccess. W takim przypadku nie potrzebujesz niczego w .htaccessswoim serwerze, jeśli Twój serwer jest odpowiednio skonfigurowany.

Inne niż te, możesz zastosować niektóre z pomysłów na optymalizację z części wydajnościowych tego ogólnego miłego SO pytania o to, jak robić strony internetowe we właściwy sposób , np. Dzielenie zasobów na bezdechowe subdomeny itp. Ale w każdym razie obraz 3k ładowanie nie powinno zająć sekundy, jest to widoczne w porównaniu z innymi elementami na wykresach. Powinieneś spróbować znaleźć problem przed optymalizacją.

Halil Özgür
źródło
-1: W odpowiedzi na żądanie warunkowe z komunikatem „Niezmodyfikowane” i brakiem poprawionego czasu wygaśnięcia spowoduje spowolnienie witryny w 99,9% przypadków (BTW, AFAIK, nie ma sposobu, aby Apache wydał poprawione informacje o buforowaniu z odpowiedzią 304)
symcbean
A co to ma wspólnego z moją odpowiedzią?
Halil Özgür,
1

Czy próbowałeś skonfigurować kilka subdomen pod serwerem NGINX specjalnie do obsługi danych statycznych, takich jak obrazy i arkusze stylów? W tym temacie można już znaleźć coś pomocnego .

nefo_x
źródło
Dzięki! Po przeprowadzeniu niektórych badań wydaje się jednak, że skonfigurowanie subdomen do statycznych plików cookie serwera sprawia, że ​​witryna jest szybsza tylko wtedy, gdy jest wiele obrazów, co wiąże się z niewielkim dodatkowym kosztem. W moim przypadku założę się, że 6 obrazów nie będzie ładować się szybciej niż narzuty sub / dodatkowych domen. Dobrze?
Sam
1
NGinx obsługuje syscall sendfile, który może wysyłać pliki bezpośrednio z dysku twardego. proszę zapoznać się z następującym dokumentem wiki.nginx.org/HttpCoreModule na temat dyrektyw „sendfile”, „aio”. Ten serwer obsługuje pliki statyczne, takie jak obrazy, znacznie szybciej niż apache.
nefo_x
ciekawe ... Nie wiedziałem, że może być coś lepszego niż Apache. Nawiasem mówiąc, co masz na myśli straight from hdd. masz na myśli zamiast tego straight from DDR3 RAM/ straight from Solid State Diskwiem, że dyski twarde, w przeciwieństwie do pamięci RAM DDR3 lub dysków SSD, mają bardzo wolny czas dostępu. Ale wydaje mi się, że to nie jest wąskie gardło ...
Sam
1
Chodzi o to, że nginx nie buforuje statycznych danych wyjściowych, tak jak apache.
nefo_x
1

Jeśli chodzi o opóźnione miniatury, spróbuj wywołać funkcję flush () natychmiast po ostatnim wywołaniu funkcji header () w skrypcie generowania miniatur. Po zakończeniu zregeneruj wykres wodospadu i sprawdź, czy opóźnienie występuje teraz na ciele zamiast na nagłówkach. Jeśli tak, musisz rzucić okiem na logikę, która generuje i / lub wyprowadza dane obrazu.

Skrypt, który obsługuje miniatury powinien, mam nadzieję, użyć pewnego rodzaju buforowania, aby wszelkie działania podejmowane na obrazach, które wyświetlasz, miały miejsce tylko wtedy, gdy jest to absolutnie konieczne. Wygląda na to, że za każdym razem, gdy wyświetlasz miniatury, odbywa się kosztowna operacja, która opóźnia jakiekolwiek wyjście (w tym nagłówki) ze skryptu.

AR Younce
źródło
+1 Ekscytujące przypuszczenie, że spróbujesz teraz! zdam relację, gdy zacznę płynąć nowy wodospad ...
Sam
Niestety, po dodaniu flush();tuż po nagłówkach wydaje się, że nic się nie zmienia! Co to może znaczyć?
Sam
Niepewny. Czy możesz w jakiś sposób połączyć nas z danym skryptem PHP? Wiem, że zapłaciłeś za to, ale niezwykle trudno jest powiedzieć, co może być przyczyną tego zachowania, nie będąc w stanie zobaczyć, co robi.
AR Younce
Czy miniatury są przywoływane w CSS czy w tagach <img>?
AR Younce
Co rozumiesz przez odniesienie w css? są po stronie html ciała i wyglądają następująco: <img src="thumbprocessor.php?src=/folder/image.jpg&w=100&h=200" id="thumbnail"/>
Sam
1

Większość powolnych problemów to zbyt wysoki czas TTFB (czas do pierwszego bajtu). Jest to trudna do rozwiązania bez intymności z plikami konfiguracyjnymi serwera, kodem i sprzętem bazowym, ale widzę, że rozprzestrzenia się przy każdym żądaniu. Masz za dużo zielonych pasków (źle) i bardzo mało niebieskich pasków (dobrze). Możesz na chwilę przestać optymalizować frontend, ponieważ uważam, że wiele zrobiłeś w tej dziedzinie. Pomimo powiedzenia, że ​​„ 80% -90% czasu reakcji użytkownika końcowego jest spędzane na interfejsie użytkownika ”, uważam, że twój występuje w interfejsie użytkownika .

TTFB to backend, serwer, przetwarzanie wstępne przed wyjściem i uzgadnianie.

Czas na wykonanie kodu, aby znaleźć wolne rzeczy, takie jak powolne zapytania do bazy danych, czas wchodzenia i wychodzenia z funkcji / metod, aby znaleźć wolne funkcje. Jeśli używasz php, spróbuj Firephp . Czasami podczas uruchamiania lub inicjowania uruchamiane jest jedno lub dwa wolne zapytania, takie jak pobieranie informacji o sesji lub sprawdzanie autentyczności, a co nie. Optymalizacja zapytań może prowadzić do dobrych zysków. Czasami kod jest uruchamiany przy użyciu php prepend lub spl autoload, aby działały na wszystkim. Innym razem może to być źle skonfigurowana konfiguracja i modyfikacja apache, która oszczędza dzień.

Poszukaj nieefektywnych pętli. Szukaj powolnego pobierania wywołań pamięci podręcznej lub powolnych operacji we / wy spowodowanych przez wadliwe napędy dysków lub duże wykorzystanie miejsca na dysku. Poszukaj zastosowań pamięci, co jest używane i gdzie. Uruchom powtarzany test 10 stron na jednym obrazie lub pliku, używając tylko pierwszego widoku z różnych lokalizacji na całym świecie, a nie z tej samej lokalizacji. I czytaj swoje dzienniki dostępu i błędów, zbyt wielu programistów je ignoruje i polega wyłącznie na wynikowych błędach ekranowych. Jeśli Twój hosting ma wsparcie, poproś go o pomoc, jeśli i tak może grzecznie nie poprosi o pomoc, to nie zaszkodzi.

Możesz spróbować pobrać wstępnie DNS, aby zwalczyć wiele domen i zasobów, http://html5boilerplate.com/docs/DNS-Prefetching/

Czy serwer jest twoim własnym / dobrym serwerem? Czasami lepszy serwer może rozwiązać wiele problemów. Jestem fanem mentalności „ sprzęt jest tani, programiści są kosztowni ”, jeśli masz szansę i pieniądze na ulepszenie serwera. I / lub użyj CDN, takiego jak maxcdn lub cloudflare lub podobny.

Powodzenia!

(ps, nie pracuję dla żadnej z tych firm. Również powyższy link cloudflare będzie argumentował, że TTFB nie jest aż tak ważny, wrzuciłem to tam, abyś mógł wziąć jeszcze jedno.)

Anthony Hatzopoulos
źródło
Drogi Anthony, bardzo dziękuję za tę wnikliwą wiedzę „w tle”. Zgadzam się, że czasami sprzęt stanowi wąskie gardło i jest to mniej oczywiste, co można zmierzyć, zwłaszcza gdy firma hostingowa hostuje część serwerową we współdzielonym środowisku hostingowym. Myślę, że cloudflare to dobra opcja do wypróbowania w połączeniu z optymalizacją konfiguracji apache. Pozdrowienia!
Sam
-1

Przykro mi to mówić, podajesz niewiele danych. I masz już kilka dobrych sugestii.

Jak serwujesz te obrazy? Jeśli przesyłasz strumieniowo te przez PHP, robisz bardzo złe rzeczy, nawet jeśli są już wygenerowane.

NIGDY NIE PRZESYŁAJ OBRAZÓW Z PHP. Spowolni twój serwer, bez względu na sposób korzystania z niego.

Umieść je w dostępnym folderze z sensownym identyfikatorem URI. Następnie zadzwoń do nich bezpośrednio z ich prawdziwym identyfikatorem URI. Jeśli potrzebujesz w locie, powinieneś umieścić .htaccess w katalogu images, który przekierowuje do skryptu php generatora tylko wtedy, gdy brakuje obrazu żądania. (nazywa się to strategią buforowania na żądanie).

Spowoduje to naprawienie sesji php, proxy przeglądarki, buforowania, ETAGS, cokolwiek naraz.

WP-Supercache korzysta z tej strategii, jeśli jest poprawnie skonfigurowana.

Napisałem to jakiś czas temu ( http://code.google.com/p/cache-on-request/source/detail?r=8 ), ostatnie poprawki są zepsute, ale wydaje mi się, że 8 lub mniej powinno działać i możesz skorzystaj z .htaccess jako przykładu, aby przetestować różne rzeczy (chociaż istnieją lepsze sposoby konfiguracji .htaccess niż to, co kiedyś).

Opisałem tę strategię w tym poście na blogu ( http://www.stefanoforenza.com/need-for-cache/ ). Prawdopodobnie jest źle napisany, ale może pomóc w wyjaśnieniu.

Dalsza lektura: http://meta.wikimedia.org/wiki/404_handler_caching

tacone
źródło
Pamiętaj, ErrorDocument nie jest najlepszą rzeczą, jaką możesz zrobić, ponieważ generował wpisy w dzienniku błędów Apache, przekierowanie -f byłoby lepsze.
tacone
Dzięki za tacone wejściowe. Czy mówisz, że bez względu na to, jak dobry będzie skrypt php, spowolni serwer, lub jak powiedziałeś w swoim poście „Zabije twój serwer, bez względu na wszystko”.
Sam
spowolni serwer bez względu na to, jak dobry jest skrypt. Dla każdego obrazu serwer będzie musiał załadować php i przesyłać strumieniowo obraz bajt po bajcie. Pozwól, by apache wykonał zadanie, nawet nie przechodząc obok interpretera php. W wyniku tego automatycznie można uniknąć wielu innych błędów, takich jak sesje, długość treści, buforowanie, mime / type itp. GDY wydajność jest krytyczna, nie należy nawet ładować php (ale w czasie generowania).
tacone
Głosuj na downers, czy mógłbyś wyjaśnić dlaczego?
tacone