Refactorización de Wordpress para mejorar el rendimiento de la memoria [cerrado]

63

Observé de cerca el consumo de memoria de Wordpress. En mi sitio, parece que por cada golpe de página se asignan 20 MB de RAM, solo para preparar un entorno cómodo para que se ejecuten todos los complementos. Lo tracé así:

No hay un solo lugar para optimizar, ningún malo que se coma la mayor parte de la memoria. El consumo se extiende por muchos, muchos, muchos módulos php.

¿Cómo podemos hacer que Wordpress inicialice su entorno en la memoria solo una vez, y luego reutilizarlo muchas veces para cada golpe? No quiero que PHP lento coma 20 MB con cada clic de usuario; incluso en un servidor con mucha memoria, lleva segundos realizar todo ese trabajo. Básicamente, necesitaría fragmentos de memoria de solo lectura que se puedan reutilizar.

Además ... ¿por qué 20MB? ¿Alguien puede proporcionar información sobre esto?

Editar: Aquí está la salida de WinCacheGrind en Wordpress ejecutándose en mi máquina de desarrollo (mucho más rápido que el alojamiento compartido). Como puede ver, toma más de un segundo de procesamiento solo para producir el HTML de la página principal. Disminuya la velocidad con alojamiento compartido y tendrá una receta para los problemas. Elegí el método que lleva la mayor parte del tiempo. ¿Cómo harías para optimizar esto?

Editar: Aquí hay estadísticas de consultas de esta fantástica herramienta de creación de perfiles functions.php .

Carga: 12 consultas - 532 ms - 19,1 MB - 43 aciertos de caché / 53
Consulta: 15 consultas - 563ms - 19.0MB - 72 aciertos de caché / 86
Pantalla: 21 consultas - 705 ms - 19,2 MB - 234 aciertos de caché / 257

Editar: ¿Quieres ver algo garantizado que te asuste? Inserte estas líneas al final de index.php:


echo "<pre>\n";
print_r(get_defined_vars());
echo "</pre>\n";

Traté de contar cuántas veces se almacena el cuerpo de la publicación actual en la memoria. Conté 20 instancias. Luego me di cuenta de que PHP tiene un recuento de referencias, por lo que la cantidad de copias se redujo a solo tres: dos parecen estar en WP_Query, una en la caché de objetos. Estoy investigando más a fondo.

Es por eso que creo que WordPress necesita una refactorización dirigida a los problemas de memoria. Ya no puede culpar a su consumo de memoria de la complejidad de lo que hace. Simplemente hace un montón de cosas mal .

Editar: Después de un día de tratar de resolver esto, aquí están mis hallazgos:

1) El 88% de toda la memoria proviene del tipo de llamadas require o include o include_once:

2) El archivo php incluye suceder principalmente durante la primera parte de servir una solicitud (no es sorprendente), que también es donde se consume toda la memoria:

3) Es bastante interesante trazar todas las funciones que se ejecutan durante una solicitud. Hay más de 12000 llamadas en total. Los jitteé para hacerlo más visible (el eje Level es básicamente la profundidad de la pila):

4) La única forma de avanzar que se me ocurre es minimizar la cantidad de archivos .php incluidos. Si divido las funciones por archivo de donde provienen, puede ver que muchos archivos se golpean una o dos veces como máximo. Necesitamos una forma de omitirlos cuando no son necesarios. Por ejemplo, mi complemento de copia de seguridad de la base de datos remota se carga y se registra, para que nunca se use en absoluto. Aquí está el diagrama anterior dividido por nombre de archivo:

Ofrezco una recompensa que vale toda mi reputación :) por refactorizaciones que conducirían a reducir la huella de memoria de mis blogs en un 30% o más.

Editar: instalé WP 3.1, aquí hay una comparación con la versión anterior.

El azul es WP 3.1, el rojo es 3.0.4. El nuevo WP es más rápido, pero también consume más memoria.

Aquí hay una lista por archivo de inclusión.

Esto me permite darme cuenta de la cantidad de memoria que consume el "paquete All In One SEO": una forma sería utilizar solo una fracción de la funcionalidad del complemento para obtener lo que quiero. Además, mis propios complementos parecen ser bastante malos.

Me gustaría probar la carga condicional en, por ejemplo, comment.php (no permitir comentarios en mi blog) y varios otros. Eliminé todo el código obsoleto. Recorté kses.php para cargar solo sus tablas globales a pedido. Simplifiqué l10n (no hago localización), haciendo que sus funciones devuelvan las cadenas de inmediato, sin búsquedas. Todavía estoy lejos de la marca del 30% que configuré arbitrariamente.

Editar: descargué y habilité APC con la configuración predeterminada (32 MB de caché de código de operación). Aquí está la comparación:

Puede ver que la carga del código se aceleró enormemente, y el código también ocupa menos espacio en la memoria (probablemente porque tratamos solo con códigos de operación, no con la fuente original). Sin embargo, el consumo de memoria sigue siendo bastante alto.

Roman Zenka
fuente
¿Podría cargar el archivo cachegrind en algún lugar? Solo tenga en cuenta que no recuerdo si se incluye algo que valga la pena mantener en privado, si es así, entonces no lo haga.
Rarst
@Rarst Debería estar bien. foxloft.com/files/mbala/cachegrind.out
Roman Zenka
1
hm, estoy de acuerdo con tu conclusión: nada realmente sobresale, pidiendo que lo arreglen. He descargado un nuevo perfil en mi pila de prueba local (3.1, MS, Twenty Ten, datos de prueba de unidad temática) y obtuve 1,5s (la mayor parte de la diferencia parece deberse a un menú personalizado: la cosa es lenta). Así que supongo que no hay nada que arreglar = investigación de almacenamiento en caché.
Rarst
@Rarst Muchas gracias por tu ayuda. Creo que hay cosas que arreglar, pero requeriría cambiar la arquitectura de Wordpress a una filosofía completamente diferente, y eso es demasiado trabajo.
Roman Zenka

Respuestas:

25

No vale la pena. WordPress no consume mucha memoria solo porque sí. Come mucha memoria porque ejecuta mucha funcionalidad bajo el capó.

Es mucho más fácil y eficiente almacenar en caché los resultados (página generada) con el complemento de caché estático y servirlo. De esa manera, la mayoría de los visitantes ni siquiera golpearán a WP.

Rarst
fuente
2
Ya estoy usando un caché, pero todavía tengo algunas páginas que son realmente dinámicas (por ejemplo, un carrito de compras). Y cuando las estrellas no están alineadas correctamente, el usuario puede esperar 20 segundos, es decir, concedido, en GoDaddy, pero incluso si no, creo que sería ~ 3 segundos al menos. Simplemente no puedo proporcionar el tipo de experiencia realmente ágil a la que la gente está acostumbrada de Google.
Roman Zenka
8
@Roman Zenka si tiene necesidades de rendimiento específicas, entonces es mejor buscar soluciones específicas, en lugar de esperar que WordPress mágicamente se vuelva súper rápido y ligero en recursos. Lo primero que sugeriría mirar es el caché de código de operación y el almacenamiento en caché estático fragmentado ... Pero antes de eso, debe compararlo y determinar no solo dónde va la memoria, sino también dónde se gasta el tiempo. WordPress es el entorno, no un cuello de botella en sí mismo. El cuello de botella está en lo que haces que haga.
Rarst
@Rarst Realmente comparé el uso de la CPU y no puedo señalar con el dedo a ningún lugar específico que cause el problema. Similar a la memoria, parece estar esparcida por todo el lugar. Sin embargo, es posible que mi evaluación comparativa no se realice de manera óptima (uso el perfilador XDebug y Cachegrind), por ejemplo, es bastante difícil separar la latencia debido a las llamadas a la base de datos. Estaría agradecido por los punteros a mejores técnicas de creación de perfiles.
Roman Zenka
Se agregó la captura de pantalla @Rarst Profiling.
Roman Zenka
44
También podría ser que los servidores de GoDaddy sean lentos. Son conocidos por no tener el mayor hardware y serían " más bien pagar por los anuncios de televisión de actualizar sus servidores "
Zack
23

Y es por eso que creo que WordPress tiene una gran necesidad de una reescritura. Ya no puede culpar a su consumo de memoria de la complejidad de lo que hace. Simplemente hace las cosas mal.

Qué conclusión tan ingenua. Leer cosas que usted nunca debe hacer, Parte I .

Gracias por las tramas de uso de memoria, sin embargo.

Edición mucho más tarde: Autommatic ha lanzado una biblioteca llamada prefork que parece hacer lo que está pidiendo: cargar el código de WordPress en RAM solo una vez.

scribu
fuente
Es cierto, es ingenuo. Tal vez debería haber dicho "refactorizar" en lugar de "reescribir", entonces suena mucho mejor. Publicación actualizada.
Roman Zenka
2
Bien, si tiene sugerencias específicas (especialmente parches), puede publicarlas en trac: core.trac.wordpress.org
scribu
Estoy trabajando en eso ahora. Estoy tratando de trazar un mapa de objetos en la memoria, así puedo ver cuánto es usado por qué. ¿Existe una herramienta que tomaría un volcado de memoria y la trazaría?
Roman Zenka
55
@scribu - ¡+1 para el enlace a la publicación de Joel!
MikeSchinkel
1
Ok, sólo tener en cuenta que WP_Object_Cache puede ser sustituida por una aplicación memcached etc.
scribu
17

Comenzando con WordPress 3.2, PHP 5.2 será el requisito mínimo. Creo que con eso bajo nuestros cinturones, partes del núcleo pueden comenzar a ser reestructuradas y usar clases con carga automática. Esto nos permitiría evitar cargar algunos fragmentos de código a menos que realmente se necesiten. Por ejemplo, si no hubiera incrustaciones o galerías en una vista de página, podríamos evitar cargar mucho código multimedia.

Sin embargo, incluso si deciden seguir esa ruta, esperaría que sea una evolución lenta (como muchos de los otros cambios que se han producido bajo el capó). Requeriría barajar la ubicación de muchos archivos y códigos, lo que podría romper la compatibilidad con versiones anteriores de algunos complementos.

Parte del problema (si realmente se le puede llamar así) es que sin ese tipo de carga condicional, el marco central no puede saber de antemano qué funcionalidad necesitará o no para generar la vista de contenido. Por lo tanto, se deben cargar muchas funciones en caso de que sean necesarias.

Dougal Campbell
fuente
@Dougal Campbell Comencé una recompensa por esta pregunta, para ver si podemos hackear al menos esta instancia de WordPress lo suficientemente mala como para obtener al menos un 30% de mejora en el consumo de memoria ahora, relativamente sin dolor. Podría inspirar parte del desarrollo futuro.
Roman Zenka
La carga condicional, si bien reduce potencialmente el consumo de memoria, perjudica la velocidad cuando está involucrado el almacenamiento en caché del código de operación . Tendemos a favorecer la velocidad.
scribu
Más pensamientos sobre carga automática: stackoverflow.com/questions/4788452/…
scribu
@scribu Cuando dices "carga condicional", ¿estás hablando de carga automática, o realmente cargando código basado en una condición? ¿Cuánto duele la velocidad?
Roman Zenka
1
¡Gracias! Como dije, no sé si el núcleo de WP alguna vez tomará esa ruta (la refactorización requerida podría ser demasiado extrema). Pero me impresionó mucho el esfuerzo que pusiste en analizar esto y los gráficos que produjiste. ¡Sigan con el buen trabajo!
Dougal Campbell
16

¿Cómo podemos hacer que Wordpress inicialice su entorno en la memoria solo una vez, y luego reutilizarlo muchas veces para cada golpe?

Se llama caché de código de operación.

http://en.wikipedia.org/wiki/PHP_accelerator

Otón
fuente
1
Voy a probar APC y ver qué pasa. Cuando originalmente hice esa pregunta, quise decir algo más que el almacenamiento en caché de opcode: me referí a reutilizar todo el entorno que construye WordPress: código + datos. Memcached le ayudará a obtener los datos más rápido, pero seguirá clonando los datos en la memoria del servidor. Ahora parece que el almacenamiento en caché del código de operación se encargaría de ~ 90% de todo el consumo de memoria.
Roman Zenka
Si tiene los recursos para algunos experimentos, también puede intentar configurar un entorno FastCGI. Estaría muy interesado en algunas comparaciones entre mod_php y ejecutar FastCGI.
Dougal Campbell
5

probablemente no logrará reducir tanto el uso de RAM. Pero si está utilizando mod_php, es posible que desee cambiar a en su mod_fcgidlugar.

Si bien mod_php es un poco más lento, carga php incluso cuando no es necesario, como servir imágenes, archivos estáticos o incluso el almacenamiento en caché. Si tiene muchas solicitudes, esto es mucho ram.

usar fcgid reducirá esto mucho.

Además, el uso de un caché estático (como w3total cache) evitará llamar a php, lo cual es una gran ventaja: menos uso de RAM, menos conexiones db.

boyska
fuente
4

Decir ah. Estoy trabajando en una aplicación web ahora que tengo la intención de sobrecargarme con datos y uso más allá de lo que puede manejar mi cuenta de alojamiento compartido, así que decidí, aunque hubiera sido muy fácil construir en WP, intentar trabajar desde BackPress como un marco y construir solo lo que necesitaba para mis casos de uso específicos.

Así que he podido reducir mi entorno central de los cientos de archivos PHP en WP a solo los veinte que realmente necesito, al tiempo que puedo aprovechar todo el db, HTTP, gestión de usuarios, formateo y cron funciones que amo en WordPress.

El problema es que es mucho trabajo, y nunca confiaría en mi hackjob para algo más allá de mi uso personal. Si desea utilizar el entorno WP completo, tómelo como está. Es tan bueno como lo es debido a que cientos de desarrolladores lo afinaron durante varios años. Como todos los que hemos dicho aquí, llegarás mucho más lejos al encontrar un mejor plan de alojamiento e investigar técnicas de almacenamiento en caché de las que es probable que obtengas pirateando el núcleo.

goldenapples
fuente
1
Estoy de acuerdo en que WP se ha ajustado durante mucho tiempo. Pero no creo que haya sido ajustado para trabajar en un alojamiento de mala calidad, con una mezcla particular de complementos. Tengo curiosidad por ver hasta dónde puedo llevarlo. Incluso si los cambios no llegan al núcleo, es bueno tener una forma documentada de piratear el núcleo si cree que debe hacerlo.
Roman Zenka
3

Sí, WordPress carga todo primero y luego hace lo que le pedimos que haga. Puedo recordar en alguna parte que podemos crear un grupo virtual en RAM donde podemos colocar archivos. Tuve la idea de poner todo el WordPress en la memoria (<10 MB) y luego podemos guardar una gran cantidad de E / S, lo que solo debería aumentar la velocidad. Pero nunca tuve la oportunidad de probarlo y, además, no soy realmente tan competente en la búsqueda de algo así. Pero parece que vale la pena intentarlo.

Ashfame
fuente
Y estoy de acuerdo con Rarst en usar un complemento de caché estático para que no se realice ningún procesamiento. Pero eso también se puede usar con buena dinámica. :)
Ashfame
Me gusta esa idea. No estoy seguro de cuánto de este problema se debe a las latencias de E / S, y cuánto se debe a que PHP mastica lentamente los datos. ¿Conoces alguna forma de saberlo?
Roman Zenka
Lo siento, es solo una idea en mi cabeza. Es posible que no afecte el rendimiento tanto como parece, ya que los datos generalmente se leen del disco duro como bloques, por lo que es posible que ya se hayan obtenido muchos otros datos necesarios. No estoy muy seguro.
Ashfame
3

Algunas sugerencias básicas:

  1. Complemento de caché total w3 para el almacenamiento en caché.
  2. instale y habilite memcache, también habilite desde la configuración de caché total w3 (el caché opcode también es una buena opción, pero no funciona bien con el complemento de caché total w3)
  3. minimizar consultas a enlaces directos en archivos de tema.
  4. Deshabilite todos los complementos adicionales no utilizados y elimínelos.
  5. optimizar la base de datos.

Estoy ejecutando un sitio conocido de WordPress con un tráfico enorme todos los días ... No estoy dedicado incluso, lo estoy haciendo genial para mí :)

Ayaz Malik
fuente