Las miniaturas en caché generadas por PHP se cargan lentamente

179

Pregunta Parte A ▉ (100 recompensas, otorgadas)
La pregunta principal fue cómo hacer que este sitio se cargue más rápido. Primero necesitábamos leer estas cascadas. Gracias a todos por sus sugerencias sobre el análisis de lectura en cascada. De los diversos gráficos en cascada que se muestran aquí se evidencia el principal cuello de botella: las miniaturas generadas por PHP. La carga de jquery sin protocolo de CDN aconsejada por David obtuvo mi recompensa, aunque hizo que mi sitio solo fuera un 3% más rápido en general, y sin responder el cuello de botella principal del sitio. Tiempo para aclarar mi pregunta y otra recompensa:

Pregunta Parte B ▉ (100 recompensas, otorgado)
El nuevo enfoque ahora era resolver el problema que tenían las 6 imágenes jpg, que están causando la mayor parte del retraso de carga. Estas 6 imágenes son miniaturas generadas por PHP, pequeñas y de solo 3 ~ 5 kb, pero cargando relativamente muy lentamente. Observe el " tiempo hasta el primer byte " en los diversos gráficos. El problema permaneció sin resolver, pero James recibió una recompensa, que corrigió el error de encabezado que RedBot subrayó : "Una solicitud condicional If-Modified-Since devolvió el contenido completo sin cambios". .

Pregunta Parte C ▉ (mi última recompensa: 250 puntos)
Desafortunadamente, incluso después de que se solucionó el error de encabezado REdbot.org, el retraso causado por las imágenes generadas por PHP permaneció intacto. ¿En qué demonios están pensando estas minúsculas miniaturas de 3 ~ 5Kb? Toda esa información de encabezado puede enviar un cohete a la luna y viceversa. Cualquier sugerencia sobre este cuello de botella es muy apreciada y tratada como una posible respuesta, ya que estoy atrapado en este problema de cuello de botella desde hace ya siete meses. Gracias de antemano.

[Alguna información de fondo en mi sitio: CSS está en la parte superior. JS en la parte inferior (Jquery, JQuery UI, compró menú awm / menu.js motores, pestañas js motor, video swfobject.js) Las líneas negras en la segunda imagen muestran qué está iniciando qué cargar. El robot enojado es mi mascota "ZAM". Es inofensivo y, a menudo, más feliz.]


Cascada de carga: cronológica | http://webpagetest.org ingrese la descripción de la imagen aquí


Dominios Paralelos Agrupados | http://webpagetest.org ingrese la descripción de la imagen aquí


Site-Perf Waterfall | http://site-perf.com ingrese la descripción de la imagen aquí


Pingdom Herramientas Cascada | http://tools.pingdom.com

ingrese la descripción de la imagen aquí


Cascada GTmetrix | http://gtmetrix.com

ingrese la descripción de la imagen aquí


Sam
fuente
11
Creo que la mayoría de los navegadores solo hacen 20 conexiones a la vez, por lo que después de 20 el primero debe terminar antes de que comience el siguiente, de ahí la desaceleración después de 20
1
Creo que olvidó redactar la primera instancia de su dominio. Al menos tienes el resto de ellos: D
thirtydot
2
¿No puedes combinar algunas de esas imágenes en sprites?
Marcel Korpel
1
@Dagon, tenga en cuenta que HTTP 1.1 RFC solicita ( SHOULD) que los clientes HTTP 1.1 usen como máximo 2 conexiones a servidores HTTP 1.1; HTTP 1.0, por supuesto, es mucho más abierto.
sarnold
1
Los navegadores @Dagon también solo realizarán 2 conexiones simultáneas a cualquier dominio dado.
Endophage

Respuestas:

61

Primero, el uso de esos dominios múltiples requiere varias búsquedas de DNS. Sería mejor combinar muchas de esas imágenes en un sprite en lugar de difundir las solicitudes.

En segundo lugar, cuando cargo su página, veo la mayoría del bloqueo (~ 1.25s) en all.js. Veo que comienza con (una versión anterior de) jQuery. Debe hacer referencia a eso desde Google CDN, no solo para disminuir el tiempo de carga , sino también para evitar una solicitud HTTP por completo.

Específicamente, se puede hacer referencia a las bibliotecas jQuery y jQuery UI más recientes en estas URL (consulte esta publicación si le interesa por qué omití 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

Si está utilizando uno de los temas predeterminados de jQuery UI, también puede extraer su CSS e imágenes del Google CDN .

Con el hospedaje de jQuery optimizado, también se debe combinar awmlib2.jsy tooltiplib.jsen un solo archivo.

Si aborda esas cosas, debería ver una mejora significativa.

Dave Ward
fuente
1
Excelente comentario Dave! el antiguo 1.3 JQuery era mucho más pequeño, así que pensé que mientras funcionaba, podría ser más rápido. Pero me gustan sus recomendaciones: ¿Cuál de los enlaces de Google CDN me sugiere que use como mi Jqyuery? ¿Puedo usar la misma manera JQ UI javascript? +1 muchas gracias
Sam
2
Definitivamente recomiendo usar la última versión de jQuery (1.4.4 actualmente). Cuando se minimiza y se comprime, solo hay una pequeña diferencia de bytes entre ellos. He actualizado la respuesta con un par de enlaces a las últimas versiones de jQuery y jQuery UI en Google CDN, que recomendaría usar.
Dave Ward,
1
Buen consejo con el sprite, eso debería reducir el número de conexiones abiertas al servidor
JamesHalsall
actualmente trabajando en la reducción de las conexiones abiertas (pasó de 40 orso a ahora 30 orso ... el empuje final es el más difícil ya que algunas de las imágenes son fondos de repweating y no pueden entrar en un sprite (o ???)
Sam
Actualizar el grado de velocidad de la página: (96%) Grado YSlow: (90%) ... ¡y las miniaturas siguen igual de lentas que nunca!
Sam
17

He tenido un problema similar hace unos días y me encontré con head.js . Es un complemento de Javascript que le permite cargar todos los archivos JS en paralelo. Espero que ayude.

000
fuente
¡Increíble! ¿Cómo puedo haber pasado por alto eso? +1 Voy a probar ahora este. Huele a una noche fructífera. ¡Gracias Schattenbaum!
Sam
1
¿Puedo preguntar si eres el Schattenbaum de schattenbaum.net?
Pekka
12

Estoy lejos de ser un experto pero ...

Con respecto a esto: "Una solicitud condicional If-Modified-Since devolvió el contenido completo sin cambios". y mis comentarios

El código utilizado para generar las Miniaturas debe verificar lo siguiente:

  1. ¿Existe una versión en caché de la miniatura?
  2. Es la versión en caché más nueva que la imagen original.

Si alguno de estos es falso, la miniatura debe generarse y devolverse sin importar qué. Si ambas son ciertas, entonces se debe hacer la siguiente verificación:

  1. ¿Hay un encabezado HTTP_IF_MODIFIED_SINCE
  2. ¿La última hora modificada de la versión en caché es la misma que HTTP_IF_MODIFIED_SINCE

Si alguno de estos es falso, se debe devolver la miniatura en caché.

Si ambos son ciertos, se debe devolver un estado 304 http. No estoy seguro de si es necesario, pero también devuelvo personalmente los encabezados Cache-Control, Expires y Last-Modified junto con el 304.

En cuanto a GZipping, me han informado que no hay necesidad de GZip, así que ignore esa parte de mi comentario.

Editar: no noté tu adición a tu publicación.

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");

También estoy seguro de que su código debe verificar el encabezado HTTP_IF_MODIFIED_SINCE y reaccionar ante él. Simplemente configurando estos encabezados y su archivo .htaccess no proporcionará el resultado requerido.

Creo que necesitas algo como esto:

$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
fuente
¡James, has clavado la esencia del problema después de tu edición en tu respuesta! ¡El If Modified Sinceproblema parece funcionar ahora! Sin embargo, los largos encabezados / tiempo de espera para los pequeños pulgares aún no se han resuelto ...
Sam
@ James PS REdbot.org dice que su encabezado Expires tiene un valor incorrecto. Creo que tiene que ser GMT y no CET?
Sam
@Sam Lo siento, mi servidor está en el Reino Unido, por lo que genera fechas GMT automáticamente. Simplemente use la función PHP gmdate en su lugar if date. Esto debería producir una fecha GMT relativa a la hora de su servidor.
James
1
@ Sam, su tiempo de espera es el tiempo de ejecución del script. Está tardando mucho tiempo en pasar su código hasta el punto de enviar sus encabezados o no salir después de haber enviado sus encabezados.
James
@James, ya veo ... Pero aparte de ese generador de miniaturas php, hay muchos otros scripts equitativamente largos que hacen varias otras cosas (traducciones, carga de menús, etc.) en una fracción de tiempo ... ELLOS no parece tener un cuello de botella en absoluto ... ¿eso dirige el problema solo al generador de miniaturas php SOLAMENTE?
Sam
6

Wow, es difícil explicar las cosas usando esa imagen ... Pero aquí, algunos intentos:

  • los archivos 33-36 se cargan tan tarde, porque se cargan dinámicamente dentro del swf, y el swf (25) se carga primero por completo antes de cargar cualquier contenido adicional
  • los archivos 20 y 21 son tal vez (no sé, porque no conozco su código) bibliotecas cargadas por all.js (11), pero para que 11 se ejecute, espera la página completa (y los activos) cargar (debe cambiar eso a domready)
  • los archivos 22-32 son cargados por esas dos bibliotecas, nuevamente después de que están completamente cargadas
dar un toque
fuente
Punto interesante Supongo que no hay nada alrededor del swf ... ¿Cómo puedo cambiar lo que debo preparar? Tengo el presentimiento de lo que quieres decir. Se trata de cuando el Javascript está listo y dice en el documento listo esto o aquello? ¿debería ese documento.ready ser reemplazado por dom.ready?
Sam
@Sam si está usando el almacenamiento en caché del lado del cliente (y debería hacerlo), puede cargar los recursos utilizados por el swf en js o divs ocultos en su página para que cuando el swf los solicite, ya estén en el cliente.
Endophage
4

Solo una suposición simple porque este tipo de análisis requiere muchas pruebas A / B: su dominio .ch parece ser difícil de alcanzar (largas bandas verdes antes de que llegue el primer byte).

Esto significaría que el sitio web .ch está mal alojado o que su ISP no tiene una buena ruta hacia ellos.

Dados los diagramas, esto podría explicar un gran éxito en el rendimiento.

En una nota al margen, existe esta herramienta genial que podría ayudarlo a resolver las cosas dependiendo de su pedido de carga de recursos.

Jerome WAGNER
fuente
4

Intente ejecutar las pruebas Y! Slow y Page Speed ​​en su sitio / página, y siga las pautas para solucionar posibles cuellos de botella de rendimiento. Debería obtener enormes ganancias de rendimiento una vez que obtenga una puntuación más alta en Y! Slow o Page Speed

Estas pruebas le dirán qué está mal y qué cambiar.

Livingston Samuel
fuente
¡Gracias! los puntajes son: 92 en Page Speed ​​y 93 en Ylow. Lo que falta son: MANTENER VIVO = apagado y sin usar CDN.
Sam
ACTUALIZACIÓN: 96 y 90 respectivamente actualmente
Sam
4

¿Entonces su script PHP está generando las miniaturas en cada carga de página? En primer lugar, si las imágenes que se muestran en miniatura no cambian con tanta frecuencia, ¿podría configurar un caché para que no tengan que analizarse cada vez que se carga la página? En segundo lugar, ¿su script PHP está usando algo como imagecopyresampled()crear las miniaturas? Esa es una disminución no trivial y el script PHP no devolverá nada hasta que termine de reducir las cosas. En imagecopymerged()cambio, usar reducirá la calidad de la imagen, pero acelerará el proceso. ¿Y cuánta reducción estás haciendo? ¿Estas miniaturas son del 5% del tamaño de la imagen original o del 50%? Es probable que un mayor tamaño de la imagen original conduzca a una desaceleración ya que el script PHP tiene que guardar la imagen original en la memoria antes de que pueda reducirla y generar una miniatura más pequeña.

Medianoche
fuente
Gracias MidnightLightning! Hay una carpeta de caché donde se crean y reutilizan los JPG en miniatura, aunque tengo la sensación de que aquí está el problema del script que he comprado (y parece funcionar bien para otros)
Sam
2
Si las miniaturas están almacenadas en caché, asegúrese de que el script que las extrae de la caché esté usando en readfile()lugar de file_get_contents()seguido de un eco, que espera emitir cualquier cosa hasta que todo el archivo se mueva a la memoria del script PHP.
MidnightLightning
Mejor aún: si los archivos están en caché, genere el HTML de una manera que extraiga directamente la imagen en caché del disco sin pasar por PHP. Eso es lo que hago en mis guiones para videodb.net
andig
"Hay una carpeta de caché donde ..." y ¿con qué rapidez se desreferencian? ¿Su URL apunta directamente al archivo en caché o un script PHP? ¿Redirige o usa readfile ()? ¿El mismo script PHP contiene el código de generación de miniaturas, o aplazas la carga de la mayor parte del código usando include / erquire?
symcbean
4

Encontré la URL de su sitio web y verifiqué un archivo jpg individual desde la página de inicio. Si bien el tiempo de carga es razonable ahora (161 ms), está esperando 126 ms, que es demasiado.

Sus últimos encabezados modificados están configurados para el sábado, 01 de enero de 2011 a las 12:00:00 GMT, que parece demasiado "redondo" para ser la fecha real de generación ;-)

Dado que el control de caché es "public, max-age = 14515200", los encabezados arbitrarios de última modificación podrían causar problemas después de 168 días.

De todos modos, esta no es la verdadera razón de los retrasos.

Debe verificar qué hace su generador de miniaturas cuando la miniatura ya existe y qué podría consumir tanto tiempo revisando y entregando la imagen.

Puede instalar xdebug para perfilar el script y ver dónde están los cuellos de botella.

Tal vez todo usa un marco o se conecta a alguna base de datos por nada. He visto mysql_connect () muy lento en algunos servidores, principalmente porque se conectaban usando TCP y no socket, a veces con algunos problemas de DNS.

Entiendo que no puede publicar su generador de pago aquí, pero me temo que hay demasiados problemas posibles ...

Cápsula
fuente
¡Gracias por tu detective y detectar pistas Capsule! Primero lo primero: no hay base de datos. Sus hallazgos son iguales a los míos: ¿está esperando el 90% del tiempo? Pequeños pulgares locos. Pensamientos interesantes sobre los últimos encabezados modificados, porque según la publicación de James aquí, tuve que establecer esos encabezados de Última modificación en un tiempo ESTÁTICO (fijo), no dinámico / siempre cambiando el tiempo establecido por los generadores de php gmdate. ¿O tal vez te refieres a algo más aquí? (Nominado a recompensa)
Sam
1
Para ser perfecto, debe reflejar la fecha de generación real, por ejemplo, obteniendo el tiempo de archivo () de la miniatura en caché. Lo que sería interesante probar es acceder a un archivo PHP vacío, o un archivo PHP que simplemente haga eco de "prueba" y vea cuánta espera tiene en este. Tal vez todo el servidor es lento e impacta cada script PHP, haga lo que haga.
Cápsula
1
También veo un retraso relativamente largo en los archivos estáticos puros (por ejemplo, las imágenes vinculadas a los pulgares), como 36 ms. En uno de los servidores que estoy administrando (que no es una bestia ... doble núcleo con 2 Gb de RAL), obtengo casi la mitad de esto, como 20 ms en archivos estáticos.
Cápsula
Interesante ... 1. ¿Qué software / herramienta en línea utilizas para medir? 2. ¿son consistentes sus mediciones más rápidas de 20 ms (cuántos ± xx%) considera que sus resultados varían? En mi caso, varía mucho dependiendo de la herramienta de prueba que use. algunos son muy consistentes ( gtmetrix.com ) algunos son muy variables ( pingdom.com ) y es difícil dar tiempos en XX ms ya que cambian cada vez ...
Sam
Estoy usando la pestaña NET de Firebug. 20 ms es el tiempo más rápido que obtengo. Varía entre 20 y 28. Por supuesto, los 36 ms que medí en su servidor también fueron los más rápidos.
Cápsula
4

Si no hay una buena razón (generalmente no la hay), sus imágenes no deberían invocar al intérprete PHP.

Cree una regla de reescritura para su servidor web que sirva la imagen directamente si se encuentra en el sistema de archivos. Si no es así, redirige a tu script PHP para generar la imagen. Cuando edite la imagen, cambie el nombre del archivo de las imágenes para obligar a los usuarios que tienen una versión en caché a buscar la imagen recién editada.

Si no funciona al menos, ahora no tendrá nada que ver con la forma en que se crean y verifican las imágenes.

Goran Jurić
fuente
Gracias Goran, sin embargo, esta no es la solución elegante que deseo: creo que hay algo sospechoso en mi caso, y que normalmente no toma mucho tiempo para que un script php sepa si pasar un encabezado 304 o hornear el imagen, etc. de todos modos, gracias por su sugerencia, ya que dirige el problema desde una perspectiva completamente nueva. Lo cual es valioso por sí solo +1
Sam
3

Investigue el uso de PHP de datos de sesión. Tal vez (solo tal vez), el script PHP generador de imágenes está esperando obtener un bloqueo en los datos de la sesión, que está bloqueado por la página principal de representación fija u otros scripts de representación de imágenes. Esto haría que todas las optimizaciones de JavaScript / navegador sean casi irrelevantes, ya que el navegador está esperando al servidor.

PHP bloquea los datos de sesión para cada script que se ejecuta, desde el momento en que comienza el manejo de la sesión, hasta el momento en que finaliza el script, o cuando se llama a session_write_close (). Esto efectivamente serializa las cosas. Echa un vistazo a la página PHP sobre sesiones, especialmente los comentarios, como este .

Ricardo Pardini
fuente
Gracias por la sugerencia Ricardo! Parece que Alix sugiere lo mismo que tú (¿verdad?). En términos prácticos, ¿qué me sugiere que coloque / elimine del código, luego vuelva a probar los gráficos y luego informe? Muy apreciado.
Sam
1
Sí, eso creo. Le sugiero que cambie los scripts de generación de imágenes para que no dependan de datos de $ _SESSION o similares (tal vez ya no lo hagan). Luego use session_write_close () lo antes posible , o, mejor aún, evite usar sesiones en esos scripts. Visite php.net/manual/en/function.session-write-close.php
Ricardo Pardini el
3

Esto es una suposición descabellada ya que no he visto su código, pero sospecho que las sesiones pueden estar jugando un papel aquí, lo siguiente es de la entrada del Manual PHP en session_write_close():

Los datos de la sesión generalmente se almacenan después de que su script finalizó sin la necesidad de llamar a session_write_close (), pero como los datos de la sesión están bloqueados para evitar escrituras concurrentes, solo un script puede operar en una sesión en cualquier momento. Cuando use conjuntos de marcos junto con sesiones, experimentará que los marcos se carguen uno por uno debido a este bloqueo. Puede reducir el tiempo necesario para cargar todos los cuadros finalizando la sesión tan pronto como se realicen todos los cambios en las variables de sesión.

Como dije, no sé qué está haciendo su código, pero esos gráficos parecen extrañamente sospechosos. Tuve un problema similar cuando codifiqué una función de servicio de archivos multiparte y tuve el mismo problema. Al servir un archivo de gran tamaño, no pude hacer que funcionara la funcionalidad multiparte ni abrí otra página hasta que se completó la descarga. Llamar session_write_close()solucionó mis dos problemas.

Alix Axel
fuente
Gracias Alix por tu sugerencia. Una pregunta: ¿la exit();función está en líneas similares a la session_write_close();? Actualmente, el escritor original del código está investigando el problema, pero helas parece que también está un poco a oscuras, ya que es una actualización generosa del código con un mejor manejo If-Modified-Since parece tener los mismos retrasos (nueva cascada ¡los gráficos produjeron los mismos gráficos, aunque los resultados reales del mundo parecían / ​​se cargaban más rápido! Es un problema muy extraño ...
Sam
1
@Sam: No puedo darle ninguna fuente en este momento, pero creo que exit () primero llama a los destructores y / o funciones registradas para el cierre y solo luego se cierra la sesión. De todos modos, apuesto a que su problema probablemente yace antes de su llamada de salida (). Ver también: stackoverflow.com/questions/1674314/…
Alix Axel
2

¿Has intentado reemplazar las thumnails generadas por php por imágenes regulares para ver si hay alguna diferencia? El problema podría estar relacionado: un error en su código php que conduce a una regeneración de la miniatura en cada invocación del servidor, un retraso en su código (¿dormir ()?) Asociado con un problema de reloj, un problema de disco duro que causa una muy mala condición de carrera ya que todas las miniaturas se cargan / generan al mismo tiempo.

Jerome WAGNER
fuente
Algo que en algún momento pensé en probar +1 para leer mis pensamientos y revelar la primera solución que ya hice. Lo que esperaba era encontrar que las imágenes normales también se cargarían lentamente, por lo que podría ser la velocidad de descarga de la banda o algo físicamente limitante, pero descubrí que las imágenes de volcado estático normales (guardé los pulgares generados y subí como estático) estas cargadas Extremadamente rápido. ¡Entonces tiene que ver con lo que el generador de miniaturas php!
Sam
2

Creo que en lugar de usar ese script generador de miniaturas debes dar TinySRC probar para una generación de miniaturas rápida, rápida y alojada en la nube. Tiene una API muy simple y fácil de usar, puede usar como: -

http://i.tinysrc.mobi/ [altura] / [ancho] /http://domain.tld/path_to_img.jpg

[anchura] (opcional): - Este es un ancho en píxeles (que anula el tamaño adaptable o familiar). Si tiene el prefijo '-' o 'x', se restará o reducirá a un porcentaje del tamaño determinado.

[altura] (opcional): - Esta es una altura en píxeles, si el ancho también está presente. También anula el tamaño adaptativo o familiar y puede tener como prefijo '-' o 'x'.

Puedes consultar el resumen de la API aquí


Preguntas más frecuentes

¿Cuánto me cuesta tinySrc?

Nada.

¿Cuándo puedo comenzar a usar tinySrc?

Ahora.

¿Qué tan confiable es el servicio?

No garantizamos el servicio tinySrc. Sin embargo, se ejecuta en una importante infraestructura de nube distribuida , por lo que ofrece alta disponibilidad en todo el mundo. Debería ser suficiente para todas sus necesidades.

Que tan rapido es

tinySrc almacena en caché las imágenes redimensionadas en la memoria y en nuestro almacén de datos por hasta 24 horas , y no recuperará su imagen original cada vez. Esto hace que los servicios sean increíblemente rápidos desde la perspectiva del usuario. (Y reduce la carga de su servidor como un agradable efecto secundario).


Buena suerte. Solo una sugerencia, ya que no nos está mostrando el código: p

Salman von Abbas
fuente
2

Como algunos navegadores solo descargan 2 descargas paralelas por dominio, ¿no podría agregar dominios adicionales para compartir las solicitudes en dos o tres nombres de host diferentes? por ejemplo, 1.imagecdn.com 2.imagecdn.com

Tom
fuente
+1 por su sugerencia: gracias, pero si mira más de cerca mi (admitido: dibujos muy caóticos) verá que algunos elementos provienen de ....... es algunos provienen de ........ com .......... de PERO, ¿tal vez eso no funciona tan bien como su sugerencia? (Veo que sugieres subdominios, en lugar de solo dominios diferentes.)
Sam
1

En primer lugar, debe manejar las If-Modified-Sincesolicitudes y de manera adecuada, como dijo James. Ese error indica que: "Cuando le pregunto a su servidor si esa imagen se modificó desde la última vez, envía la imagen completa en lugar de un simple sí / no".

El tiempo entre la conexión y el primer byte es generalmente el tiempo que tarda su script PHP en ejecutarse. Es evidente que algo está sucediendo cuando ese script comienza a ejecutarse.

  1. ¿Has considerado perfilarlo? Puede tener algunos problemas.
  2. En combinación con el problema anterior, su script puede ejecutarse muchas más veces de las necesarias. Idealmente, debería generar pulgares solo si la imagen original se modifica y enviar pulgares en caché para cualquier otra solicitud. ¿Ha verificado que el script genera las imágenes innecesariamente (por ejemplo, para cada solicitud)?

Generar encabezados adecuados a través de la aplicación es un poco complicado, además el servidor puede sobrescribirlos. Y está expuesto al abuso, ya que cualquiera que envíe algunos encabezados de solicitud sin caché hará que su generador de miniaturas se ejecute continuamente (y aumente las cargas). Entonces, si es posible, intente guardar los pulgares generados, llame a las imágenes guardadas directamente desde sus páginas y administre los encabezados desde .htaccess. En este caso, ni siquiera necesitarías nada .htaccesssi tu servidor está configurado correctamente.

Aparte de estos, puede aplicar algunas de las brillantes ideas de optimización de las partes de rendimiento de esta pregunta SO general sobre cómo hacer sitios web de la manera correcta , como dividir sus recursos en subdominios sin cookies, etc. Pero, en cualquier caso, una imagen de 3k No debería tomar un segundo para cargar, esto es evidente en comparación con otros elementos en los gráficos. Debe intentar detectar el problema antes de optimizar.

Halil Özgür
fuente
-1: responder a una solicitud condicional con 'No modificado' y sin tiempo de vencimiento revisado hará que su sitio sea más lento en el 99.9% de los casos (BTW, AFAIK, no hay forma de que Apache emita información de almacenamiento en caché revisada con una respuesta 304)
symcbean
¿Y qué tiene que ver eso con mi respuesta?
Halil Özgür
1

¿Ha intentado configurar varios subdominios en el servidor web NGINX especialmente para servir datos estáticos como imágenes y hojas de estilo? Algo útil ya podría encontrarse en este tema .

nefo_x
fuente
¡Gracias! Sin embargo, después de investigar un poco, parece que configurar subdominios para las cookies estáticas del servidor solo hace que un sitio sea más rápido, cuando hay muchas imágenes, a un costo de un poco de sobrecarga adicional. En mi caso, apuesto a que las 6 imágenes no se cargarán más rápido que la sobrecarga del dominio sub / extra. ¿Correcto?
Sam
1
NGinx es compatible con syscall sendfile, que podría enviar archivos directamente desde el disco duro. consulte el siguiente documento wiki.nginx.org/HttpCoreModule sobre las directivas 'sendfile', 'aio'. Este servidor web sirve archivos estáticos como imágenes mucho más rápido que apache.
nefo_x
interesante ... No sabía que puede haber algo mejor que Apache. Por cierto, ¿qué quieres decir con straight from hdd? ¿quiere decir en cambio? straight from DDR3 RAM/ straight from Solid State DiskSé que los discos duros, a diferencia de DDR3 ram o discos de estado sólido, tienen un tiempo de acceso muy lento. Pero siento que este no es el cuello de botella aquí ...
Sam
1
el punto es que nginx no almacena la salida de datos estáticos, como lo hace apache.
nefo_x
1

Con respecto a las miniaturas retrasadas, intente poner una llamada a flush () inmediatamente después de la última llamada al encabezado () en su script de generación de miniaturas. Una vez hecho esto, regenere su gráfico de cascada y vea si el retraso está ahora en el cuerpo en lugar de los encabezados. Si es así, debe analizar detenidamente la lógica que genera y / o genera los datos de la imagen.

Con suerte, el script que maneja las miniaturas debería usar algún tipo de almacenamiento en caché para que cualquier acción que tome en las imágenes que está publicando solo ocurra cuando sea absolutamente necesario. Parece que se está llevando a cabo una operación costosa cada vez que sirve las miniaturas, lo que retrasa cualquier salida (incluidos los encabezados) del script.

AR Younce
fuente
¡+1 emocionante conjetura que lo probaré ahora! informará cuando tenga la nueva cascada fluyendo ...
Sam
Desafortunadamente, después de agregar flush();justo después de los encabezados, ¡parece que no hay ningún cambio! ¿Qué podría significar eso?
Sam
No estoy seguro. ¿Hay alguna manera de vincularnos al script PHP en cuestión? Sé que lo pagaste, pero es increíblemente difícil decir qué podría estar causando el comportamiento sin poder ver lo que está haciendo.
AR Younce
¿Se hace referencia a las miniaturas en CSS o en etiquetas <img>?
AR Younce
¿Qué quieres decir con referencia en CSS? están al costado del cuerpo html y de la siguiente manera: <img src="thumbprocessor.php?src=/folder/image.jpg&w=100&h=200" id="thumbnail"/>
Sam
1

La mayor parte del problema lento es que su TTFB (Tiempo hasta el primer byte) es demasiado alto. Es difícil de abordar sin tener que familiarizarse con los archivos de configuración de su servidor, el código y el hardware subyacente, pero puedo ver que es rampante en cada solicitud. Tienes demasiadas barras verdes (malas) y muy pocas barras azules (buenas). Es posible que desee dejar de optimizar la interfaz por un tiempo, ya que creo que ha hecho mucho en esa área. A pesar del adagio de que "el 80% -90% del tiempo de respuesta del usuario final se gasta en la interfaz ", creo que el suyo está ocurriendo en el back-end.

TTFB es material de back-end, material de servidor, preprocesamiento previo a la salida y protocolo de enlace.

Mida el tiempo de ejecución de su código para encontrar cosas lentas, como consultas lentas de bases de datos, funciones / métodos de entrada y salida de tiempo para encontrar funciones lentas. Si usas php, prueba Firephp . A veces, se ejecutan una o dos consultas lentas durante el inicio o la inicialización, como extraer información de la sesión o verificar la autenticación y otras cosas. La optimización de consultas puede conducir a algunas buenas ganancias de rendimiento. A veces, el código se ejecuta usando php prepend o spl autoload para que se ejecuten en todo. Otras veces puede ser mal configurado apache conf y ajustes que salvan el día.

Busque bucles ineficientes. Busque llamadas de almacenamiento en caché lentas u operaciones de E / S lentas causadas por unidades de disco defectuosas o uso elevado de espacio en disco. Busque usos de memoria y qué se está utilizando y dónde. Ejecute una prueba repetida de prueba de página web de 10 ejecuciones en una sola imagen o archivo utilizando solo la primera vista desde diferentes ubicaciones en todo el mundo y no la misma ubicación. Y lea sus registros de acceso y error, demasiados desarrolladores los ignoran y solo confían en los errores que aparecen en la pantalla. Si su proveedor de alojamiento web tiene soporte, pídales ayuda, si de todos modos no le piden ayuda cortésmente, no le hará daño.

Puede probar la captación previa de DNS para combatir los numerosos dominios y recursos, http://html5boilerplate.com/docs/DNS-Prefetching/

¿Es el servidor suyo un servidor bueno / decente? A veces, un mejor servidor puede resolver muchos problemas. Soy fanático de la mentalidad de "el hardware es barato, los programadores son caros ", si tienes la oportunidad y el dinero actualiza un servidor. Y / o use un CDN como maxcdn o cloudflare o similar.

¡Buena suerte!

(PD, no trabajo para ninguna de estas empresas. Además, el enlace de Cloudflare anterior argumentará que TTFB no es tan importante, lo tiré allí para que pueda obtener otra toma).

Anthony Hatzopoulos
fuente
Estimado Anthony, muchas gracias por este perspicaz conocimiento de "antecedentes". Estoy de acuerdo en que a veces el hardware es el cuello de botella y que es menos obvio medirlo especialmente cuando la empresa de alojamiento aloja el servidor en un entorno de alojamiento compartido. Creo que cloudflare es una buena opción para probar en combinación con la optimización de configuración de apache. ¡Saludos!
Sam
-1

Lamento decir que proporcionas pocos datos. Y ya tenías algunas buenas sugerencias.

¿Cómo estás sirviendo esas imágenes? Si los está transmitiendo a través de PHP, está haciendo algo muy malo, incluso si ya están generados.

NUNCA TRANSMITIR IMÁGENES CON PHP. Disminuirá la velocidad de su servidor, sin importar la forma en que lo use.

Póngalos en una carpeta accesible, con un URI significativo. Luego llámalos directamente con su URI real. Si necesita la generación sobre la marcha, debe colocar un .htaccess en el directorio de imágenes que redirige a un script php generador solo si falta la imagen de solicitud. (Esto se llama estrategia de caché bajo solicitud).

Hacer eso arreglará la sesión de php, el proxy del navegador, el almacenamiento en caché, ETAGS, lo que sea todo a la vez.

WP-Supercache utiliza esta estrategia, si está configurada correctamente.

Escribí esto hace algún tiempo ( http://code.google.com/p/cache-on-request/source/detail?r=8 ), las últimas revisiones están rotas, pero supongo que 8 o menos deberían funcionar y puedes tome el .htaccess como ejemplo solo para probar las cosas (aunque hay mejores formas de configurar el .htaccess que de la forma en que solía hacerlo).

Describí esa estrategia en esta publicación de blog ( http://www.stefanoforenza.com/need-for-cache/ ). Probablemente esté mal escrito, pero puede ayudar a aclarar las cosas.

Lectura adicional: http://meta.wikimedia.org/wiki/404_handler_caching

tacone
fuente
Recuerde, ErrorDocument no es realmente lo mejor que puede hacer, ya que generó entradas en el registro de errores de apache, una redirección -f sería mejor.
tacone
Gracias por tu aportación tacone. ¿Estás diciendo que no importa cuán bueno sea el script php, ralentizará el servidor o, como dijiste en tu publicación, "matará a tu servidor, pase lo que pase".
Sam
ralentizará el servidor sin importar cuán bueno sea el script. Para cada imagen, el servidor tendrá que cargar php y hacer que transmita la imagen byte por byte. Deje que apache haga el trabajo sin siquiera pasar por el intérprete de php. Como resultado secundario, se evitarán automáticamente muchos otros posibles errores, como sesiones, longitud de contenido, almacenamiento en caché, mime / type, etc. CUANDO el rendimiento es crítico, ni siquiera debe cargar php (sino en tiempo de generación).
tacone
Votantes, ¿podría explicar por qué?
tacone