Google I/O 2012 – Optimizing Your Google App Engine App

MARZIA NICCOLAI: Hola, bienvenido
a Optimización de tu aplicación App Engine. Soy Marzia Niccolai. GREG DARKE: Soy Greg Darke. TROY TRIMBLE: Y yo soy
Troy Trimble. MARZIA NICCOLAI: Y hoy
vamos a hablar con usted. Aquí hay una pequeña descripción general
de la agenda que cubriremos. Primero, analizaremos
algunos consejos de codificación sobre cómo escribir su aplicación App Engine de manera
más eficiente. Luego cubriremos algunas
configuraciones de rendimiento. Y luego también vamos a
hablar un poco sobre lo que estamos planeando en el futuro y
cómo esto afectará la forma en que escalas y
escribes tu aplicación. Primero, solo quiero hablar un
poco sobre la latencia versus el costo, que es realmente
lo que estamos tratando de cubrir aquí cuando nos referimos a la optimización. Ahora bien, estos no siempre son
objetivos contradictorios. A veces, estas cosas están
en conflicto y, a veces, cuando optimizas para una,
optimizas para la otra.

Mi regla general cuando
pienso en estas cosas es que si hago algo más
eficiente, generalmente también reducirá su costo. Si uso más recursos para
lograr una latencia más baja, normalmente eso generará
costos más altos para mí. Y a veces, con App Engine
y la forma en que tenemos disponibles nuestras configuraciones de rendimiento,
puedes optar por reducir la cantidad de recursos que
estás usando.

Será menos costoso,
pero también tendrá una latencia ligeramente más lenta. Ahora bien, la otra pregunta
es, ¿qué entendemos por buena latencia? Así que puse una diapositiva aquí desde
un gráfico de la consola de administración sobre una aplicación en la que trabajo
y destaqué su controlador de latencia más baja y nuestro
controlador de latencia más alta. Ahora, para el controlador base, 46
milisegundos, solo diré que creo que es
bastante bueno. Es lo que su usuario
encontrará la primera vez que acceda a su aplicación. 46 milisegundos,
les sirven algo. Ahora. El controlador de latencia más alto,
pedirá 942 milisegundos, básicamente,
1 segundo. ¿ Eso es bueno o tan malo? Bueno, quiero decir, mucho
de eso depende. Y mucho de eso realmente cubre
el meollo de lo que estamos hablando hoy,
que es, bueno, ¿ quién ve esa solicitud? Si su usuario ve esa
solicitud, ¿es buena una segunda? Pero si son solo algunas solicitudes
ejecutándose en el backend, tal vez no me importe si son
942 milisegundos.

Por supuesto, en este caso,
es algo que se solicita de forma asincrónica
pero que se entrega a mi usuario. Entonces veo esos 942
milisegundos. Yo digo, bueno,
no está mal. ¿ Pero podría estar haciendo
algo mejor? Probablemente podría. Aparentemente, tengo que
estar aquí para que esto funcione. Bien, solo quiero decir que
estamos usando Python aquí para nuestros ejemplos de código.

Pero en realidad, muchas de estas
cosas son independientes del idioma. Cuando decimos algo que es
específico del idioma, lo diremos. E incluso Python,
no copie ni pegue este Python en su aplicación porque es
más un ejemplo de cosas buenas y malas que hacer, no un
código realmente listo para producción. Entonces, lo primero de lo que
voy a hablar son los consejos sobre Datastore. Y voy a estructurar esto,
primero, cosas que realmente hemos visto, cosas que
no debemos hacer. Y luego algunos consejos generales
sobre cosas que hacer. Ahora, lo primero que me
preguntan es: ¿cuáles son algunas estrategias generales cuando
escribo mis modelos para el almacén de datos? Y lo que siempre trato de decirle a la
gente es que piensen en las páginas que ofrecen a
los usuarios y traten de diseñar sus modelos para que esas páginas
se sirvan de manera eficiente.

Y, por supuesto,
no deberías dedicar tanto tiempo a optimizar las
páginas que rara vez ves, como las que ves con frecuencia. Porque esas serán
la mayor parte de sus solicitudes y la mayor parte de sus costos. Y esto no está realmente relacionado con la
optimización de su aplicación en sí, pero todos querían que
me conectara. Asegúrese de colocar su aplicación
en el almacén de datos de aplicaciones superior o migre su aplicación
porque ahora realmente no puede crear aplicaciones en el
almacén de datos maestro/esclavo. Pero esto será lo más
importante de todo porque, por encima de todo, desea que su aplicación sea confiable
, y HRD Datastore
lo ayudará a lograrlo. Tengo algunos ejemplos específicos
de cosas que voy a repasar. Y me sumergiré
directamente en ellos. Este es mi primer
antipatrón de Datastore.

Generalmente se parece
a esto. Tienes una consulta y estás
obteniendo un resultado. Y básicamente, lo que
se supone que dice este código es que sé qué modelo quiero
recuperar en el almacén de datos. Entonces tengo que preguntarme, ¿por qué
voy a consultarlo? En su lugar, tenemos algo
llamado obtención de almacén de datos. Y aquí tengo un nombre de clave para obtener
, que es algo que puedo configurar cuando creo el modelo.

También hay ID de almacén de datos si
no configura un nombre de clave. Si sabes cuál es el modelo que
esperas, realmente querrás intentar escribir
tu aplicación para poder usar tantos get como sea posible. Y la siguiente diapositiva realmente
muestra el motivo. Si miras lo que sucedió
cuando hice una consulta, bueno, hice dos operaciones de lectura del almacén de datos y
me tomó 59 milisegundos porque tuve que escanear
algunos índices. Después, 1 almacén de datos recupera la
operación y 4 milisegundos. Esto es realmente una obviedad, un 50%
menos y 14 veces más rápido. Esto es lo que quiero decir: coste
y eficiencia no siempre son contradictorios. Por supuesto, para Python,
esto es algo específico del lenguaje. No uses buscar en absoluto. Fetch en realidad llama a otra
función llamada ejecutar y luego la coloca en una lista. Por lo tanto, puede simplemente cortar la
ejecución directamente, lo que devuelve un generador. Y eso significará menos
memoria para su aplicación. Y, anecdóticamente,
no hay garantías. Es aproximadamente entre un 10% y un 15% más rápido
porque utiliza una captación previa asíncrona, que es
algo que Greg cubrirá un poco más adelante: la
asincronicidad.

Pero esto es algo a
destacar específicamente para Python. Ahora, mi próximo
patrón antidiseño de Datastore es algo que quizás no esté
usando en su aplicación hoy porque es algo que
simplemente… creo que fue hace dos o tres
lanzamientos, algo llamado consultas de proyección. Las consultas de proyección son realmente
buenas si solo lees datos y son una entidad pequeña.

Lo primero es cómo se
vería una consulta antigua en App Engine, un modelo donde y
luego el filtro. Ahora, el segundo parece muy
familiar para aquellos de nosotros que amamos SQL, y es que en realidad
solo estoy seleccionando los campos que realmente
quiero leer. Una vez más, esto era algo que no
se admitía hasta hace poco. Pero ahora que lo es, si
solo quieres la actualización más reciente de Firefox… creo que podemos esperar. Volvamos a la pantalla completa. Así que sólo quiero imprimir
estos dos campos de mi modelo, así que eso es todo lo que voy
a recuperar, texto y autor. Y la gran noticia aquí es que la
primera es una operación de lectura completa de Datastore, que cuesta $0,07 por
cada 100.000 operaciones en el precio de App Engine. La segunda consulta, 0,01 dólares por cada
100.000 operaciones, un 85 % menos.

Y esto es algo que es
realmente fácil de cambiar. Pero nuevamente, una cosa que hay que saber
acerca de las consultas de proyección es que no se puede escribir en el retorno de una entidad
desde consultas de proyección, por lo que es algo a tener
en cuenta. Siempre puedes, si encuentras
algo que quieras escribir, buscar esa entidad
y escribirla. O no es necesario reemplazarlo
en todas partes. Pero donde puedas usarlo,
realmente deberías hacerlo. Bien, uno de mis patrones antidiseño favoritos/menos
favoritos, algo que parece realmente
natural para todos nosotros: límite de compensación. Y parece una buena idea. Excepto que lo que sucede en App
Engine cuando especificas un desplazamiento es que escanea esos
primeros 10 índices y luego lee los 10 siguientes. Básicamente, estás
obteniendo casi 20 resultados de trabajo con esta consulta. Lo que no hemos configurado en App
Engine es un cursor de almacén de datos. Lo que hacen los cursores es devolverle
el lugar donde quedó la consulta.

Entonces, la próxima vez que ejecute
esa consulta, puede especificar ese cursor para que sepa por
dónde comenzar. Y nuevamente, esto es algo
en lo que ven aquí 25 operaciones de recuperación en el primer ejemplo porque
estamos haciendo casi todo el trabajo de la consulta. Y después, simplemente hacemos los
10 que queremos y es un 47% menos, 13 veces más rápido. Ahora vamos a entrar en
algunas cosas que realmente puedes hacer y que te ayudarán a
mejorar la eficiencia. Y recuerda que una cosa de la que
hablé fue minimizar la cantidad
de trabajo que realiza al publicar una página. Recientemente introdujimos
algo que se llama entidades integradas y es una
forma de almacenar datos estructurados dentro de un modelo. Y lo que esto realmente puede ayudarle a
hacer es desnormalizar sus datos de manera sensata.

Entonces, en este caso, lo que ves
es un contacto donde quiero almacenar direcciones dentro de
un contacto. Por lo tanto, es posible que desee almacenar estas
direcciones en otro lugar o usarlas en otro lugar. Pero también puedo guardar este
modelo en mi contacto. Y si necesito poner todo eso
en una página, toda la información está ahí. Una consulta, es realmente genial. Ahora bien, esto no es algo que
le permitirá ahorrar dinero, pero sí algo
que ayudará a que su aplicación se ejecute más rápido. Y lo último que quiero
señalar es que no indexen cosas que no necesitan
ser indexadas. Cuando App Engine muestra resultados,
siempre los muestra como un índice precalculado
para una consulta. Por lo general, lo que hacemos para
la mayoría de los modelos de productos en una propiedad es escribir todos
los índices cada vez que los crea o actualiza. Pero sabes que hay algunas
cosas sobre las que nunca
querrás consultar. En este caso, tengo algo
llamado nombre para mostrar. Eso es algo que
probablemente se suponía que debía verse bien en la página que quiero
almacenar en mi modelo.

Realmente nunca voy a consultar
sobre esto, entonces, ¿por qué voy a escribir una
fila de índice cada vez que actualizo este modelo? Entonces, simplemente poniendo index=false
aquí, cuando actualice esto, esa
fila de índice no se escribirá. Ahora no podré
consultarlo. Pero en este caso
no me importa. Y también me he ahorrado algo de
dinero porque no escribo un índice. Por supuesto, ahora que hemos
cubierto algunas cosas de Datastore, podemos hacerlo mejor. Porque el almacén de datos todavía requiere
mucho trabajo, por lo que puedes agregar una capa de almacenamiento en caché encima del almacén de datos. Es almacenamiento en caché, almacenamiento en caché, almacenamiento en caché
porque en realidad hay tres tipos diferentes de almacenamiento en caché que
cubriremos.

El primero es algo de lo que
siempre hablamos mucho. Es Memcache. Memcache es una memoria caché rápida
que tenemos disponible. Básicamente es algo donde
puedes colocar algo que usas con frecuencia, que es difícil de calcular, pero que
lees con frecuencia, ya sea desde el almacén de datos,
URLFetch o cualquier otra cosa. Pero aquí usamos el almacén de datos. Entonces, en este caso, tomé el
ejemplo del libro de visitas, donde estás leyendo saludos y
nosotros los enviamos cada vez que accedes
al libro de visitas. Por lo tanto, no es necesario extraer todos
esos saludos del almacén de datos cada vez, incluso si
no se ha actualizado. Entonces, lo que puedo hacer es
simplemente agregar todos esos datos a Memcache y extraerlos cuando
busco esa página. Y si no está allí,
siempre puedo leer desde el almacén de datos. Memcache no lleva
tanto tiempo. Quiero señalar una cosa
que hice en este ejemplo: en lugar de
almacenar los modelos en Memcache, almacené
algo de HTML renderizado. Y la razón por la que hago esto es un
problema que vemos a veces, que es que Memcache conserva tus
datos o los serializa.

Entonces, lo que sucede es que si su
modelo ha cambiado entre escritura y lectura
de Memcache, podría tener problemas. Esta es una forma de
solucionarlo, o simplemente es algo que puede tener en cuenta cuando
actualiza los modelos en su aplicación de servicio en vivo. Lo siguiente que
cubriré es el almacenamiento en caché de instancias. Bueno, ¿qué es el almacenamiento en caché de instancias? Esta es básicamente la memoria de
su instancia de App Engine y almacena algo
en esa memoria cuando la instancia está activa. Te permite tener tu
propia póliza de desalojo. Algo que no mencioné fue que
Memcache fue el desalojado menos utilizado recientemente. En este caso, almacenar algo
como una variable global le permite
almacenarlo de la forma que desee. También es más rápido
que Memcache. Es, bueno, casi
instantáneo. Memcache es bastante rápido, pero
puede haber ocasiones en las que quieras que sea más rápido.

Y en este caso, puedes simplemente
almacenarlo como una variable global en tu instancia. Pero para aquellos usuarios de Python,
lo que realmente deben hacer es usar NDB. Normalmente he usado ejemplos de DB
en la mayoría de mis ejemplos de código porque NDB se
usa relativamente. Pero en realidad he escrito aquí
cómo sería un algoritmo real de almacenamiento y lectura de Memcache
. Ni siquiera me voy a molestar en
revisarlo porque tiene cerraduras, lápidas
y todas esas cosas locas. Pero en realidad es difícil
hacerlo bien. Almacenar cosas en Memcache,
almacenar cosas en cachés de instancias, cosas que se escriben,
tener que actualizar, NDB en realidad está haciendo todo esto por usted. Entonces, si eres un usuario de Python
y no estás usando NDB, compruébalo. Con suerte, es bastante fácil
traducir uno al otro. Y obtendrás muchos
ahorros realmente interesantes.

No sé mucho sobre
Java, pero escuché que Objectify tiene algunas de las mismas cosas. Así que deberías comprobarlo
también. Y finalmente, aquí hay solo un
resumen de cuál es la diferencia entre Datastore,
Memcache y el almacenamiento en caché de instancias. Puedes ver aquí la latencia. Obviamente, Datastore tiene
la mayor latencia. Pero también almacenas
la mayoría de las cosas allí. Y está escrito allí, y
está escrito casi para siempre, a menos que decidas
eliminarlo. En términos de almacenamiento,
algo a destacar específicamente en el almacenamiento en caché de instancias
es que le permitimos tener instancias de mayor tamaño
en App Engine. El tamaño más pequeño es el
predeterminado, pero tenemos tamaños más grandes que cuestan más
dinero y tienen más memoria disponible.

Y una cosa que podrías hacer con
esa memoria es almacenar algunas cosas allí para que tu
aplicación sea más rápida. Y lo último que voy
a cubrir sobre el almacenamiento en caché es algo que realmente tendrá
un gran beneficio para las páginas de su aplicación que
rara vez se actualizan con contenido nuevo, que son los
encabezados de control de caché establecidos. Es algo muy fácil de hacer. Pero lo que hace es que cuando
esa solicitud se envía a servidores y
navegadores intermedios, les dice a esos servidores y navegadores cuánto tiempo deben
retener esa página antes de volver a solicitarla
al servidor.

Eso significa que su aplicación en
realidad no tendrá que hacer casi ningún trabajo
para estas solicitudes. Obtienes esas solicitudes solo para
ancho de banda en App Engine. Y lo que debes tener
cuidado, por supuesto, es que nunca puedes forzar que estas
páginas se vuelvan a solicitar antes del tiempo de vencimiento. Así que configúrelo de manera razonable. Quiero decir, de hecho hemos
visto aplicaciones que lo han configurado durante 365 días. Y, por supuesto,
lo configuran y se dan cuenta de que han cometido un error. Bueno, una vez que hayamos atendido
las solicitudes, estará fuera de nuestras manos. No podemos forzar a los servidores. De todos modos, no podemos obligar al navegador
a volver a realizar la solicitud. Así que haga de este un valor sensato,
pero aun así utilícelo. Y, de hecho, si ingresa a la
consola de administración, puede ir al menú desplegable y realizar solicitudes
por tipo por segundo. Y lo que verá aquí es que en
realidad se desglosa para esta aplicación cuántas
solicitudes estáticas, pero también cuántas solicitudes se atienden
desde el almacenamiento en caché perimetral. Y puedes ver aquí que en
realidad solo estoy pagando ancho de banda por esas solicitudes.

Mi servidor no funciona
o mi instancia no funciona. Por lo tanto, es una excelente manera de ahorrar
algo de dinero y ahorrar potencia informática para hacer
algo más interesante. Ahora se lo voy a pasar
a Greg, quien hablará sobre las solicitudes de API por lotes. GREG DARKE: Entonces, ¿qué son
las solicitudes de API por lotes? Las solicitudes de API por lotes le permiten
realizar operaciones en múltiples datos en un solo RPC. Y hacer esto permite que los
servidores de App Engine distribuyan su solicitud a
múltiples servidores. Y le permite amortizar
el costo de ese RPC en múltiples datos.

Entonces, ¿qué quiero decir con eso? Bueno, aquí usaré el
ejemplo de Taskqueue. Digamos, por ejemplo, que
me gustaría insertar 50 tareas en Taskqueue. Solo código simple,
recorre bucles y los agrega. En la parte superior hay un gráfico
de Appstats. Fue presentado por Guido van
Rossum en una charla de Google I/O en 2010, por lo que te sugiero que le eches
un vistazo para obtener más información. Pero en este gráfico aquí, pueden
ver cada uno de los RPC que genera
la aplicación. De hecho, recorté justo
después de los primeros 10 porque baja a 50. Como puede ver, cada solicitud
aquí toma entre 10 y 15 milisegundos. Entonces, en general, se necesitan más de 600
milisegundos para ingresar estas solicitudes reales en
Taskqueue. Entonces, si cambio este código
ligeramente, sigo construyendo todas las tareas, agregándolas a una
lista, estoy usando la interfaz API por lotes , que es q.add.

Puedes ver que todas las tareas
están insertadas, pero solo toma 22 milisegundos. Entonces hace que las solicitudes sean
mucho, mucho más rápidas. Tenemos muchas API que
realmente admiten esto: Memcache, Datastore, Taskqueue,
Full Text Search. De hecho, todos admiten la
posibilidad de operar en múltiples entidades para Datastore y
agregar múltiples documentos a un índice para
búsqueda de texto completo. Y en Memcache, puedes
obtener o colocar varias entradas allí.

Entonces, algunas cosas con las que tendrás que
tener cuidado cuando uses la API por lotes con
Taskqueue, por ejemplo, es que en realidad solo puedes
insertar hasta 32 megabytes de solicitudes allí. Por lo tanto, el uso de las API por lotes puede ser
un poco más complicado y tiene algunos problemas relacionados con el tamaño
y la cantidad de cosas que puede agregarles. Pero en general, es una
ventaja considerable para la latencia y hace que su
aplicación sea más rápida. Así que dejaré las solicitudes de API por lotes
por un segundo. Continuaré usando
flujos de trabajo asincrónicos. Por lo tanto, los flujos de trabajo asincrónicos
le permiten iniciar un RPC y luego continuar trabajando
en su aplicación. Esto le permite realizar múltiples
operaciones lentas en paralelo, como realizar múltiples
búsquedas de URL como las que tengo aquí. También le permite realizar
operaciones que requieren un uso intensivo de la CPU mientras espera que se complete la IO
.

Marzia aludió anteriormente a esto
con Datastore. Cuando haces una consulta en
Datastore usando la interfaz .run en Python y también en
Java, lo que realmente sucede es que hacemos una llamada asíncrona
para recuperar el siguiente conjunto de entidades, de modo que
realizamos la IO para encontrar la siguiente entradas mientras
seguirá iterando sobre el lote anterior que
devolvimos. Así que voy a
repasar rápidamente un ejemplo de cómo usar
RPC asíncronos para acelerar la recuperación de URL en este ejemplo. Voy a poner dos
ejemplos de esto. Esto utiliza el método un poco más antiguo que
utiliza devoluciones de llamada. Y luego repasaré
el nuevo. Entonces, lo principal que debe
escribir aquí para usar cualquiera de las API asincrónicas
es que en realidad necesitará un bucle de eventos que realice un seguimiento
de los RPC y llame a la función wait_any, que
llamará automáticamente a las devoluciones de llamada cuando estén listas. Tengo el do-fetch_call
aquí abajo, que dentro tengo un cierre para construir la
devolución de llamada real.

Y se lo paso a
make_fetch_call, que es la versión asincrónica real de
fetch en la API de recuperación de URL. En otras API, la versión asincrónica
generalmente recibe el mismo nombre
que la versión normal. Entonces, si se obtiene Datastore, la
versión asincrónica es get_asynch y esto
continúa. La recuperación de URL fue nuestra primera
API sincrónica y, por lo tanto, es diferente. Entonces, con este ejemplo aquí,
paso la devolución de llamada a la función de creación de RPC. Y así, cuando se realiza la llamada real
y finaliza la solicitud , se producirá esta devolución de llamada
y se nos proporcionarán los datos.

Como puede ver, esta versión
aquí en realidad no pasa nada de
esa devolución de llamada a la función principal. En realidad, eso es bastante difícil
de hacer usando el modelo de programación de devolución de llamada
aquí. Así que les daré… esta es la nueva versión
que usa tasklets NDB. La principal diferencia aquí es
que en lugar de tener que escribir su propio bucle de eventos, NDB
tiene uno escrito para usted.

Y, de hecho,
utiliza la nueva declaración de rendimiento como rutinas conjuntas. Entonces, todo lo que tiene que hacer es envolver
la función con este decorador NDB.tasklet y luego
generar los RPC. Y esto le permite escribir
programas que parecen fluir hacia abajo pero que en realidad
llamarán dentro y fuera del bucle de eventos. Entonces puedes ver que este ejemplo
aquí hace lo mismo. Llama a make_fetch_call. Simplemente devuelve el
resultado. Y de hecho tenemos la
declaración de devolución aquí.

Entonces, en NDB, con tasklets, en
realidad debes generar la excepción de devolución, y ese
resultado se vuelve a pasar a la lista en la parte inferior. Entonces, si echamos un vistazo al
antes y al después real. Entonces, antes, al recuperar cuatro
RPC (lo siento, cuatro sitios web), en realidad tomaba casi
4 segundos. Al hacerlo con un
modelo asincrónico, aún puede realizar el procesamiento entre cada una
de estas solicitudes. Y en este caso tarda
poco más de 3 segundos. Entonces un ahorro bastante grande. Pero si esto estaba en su
controlador principal, como Marzia aludió anteriormente, probablemente todavía fuera
demasiado lento para usted.

Algunas de las API que admiten
la asincronía: Blobstore, Memcache, URLFetch
y Datastore. Entonces, lo que realmente querrá
hacer con las solicitudes, si desea recopilar datos de un
sitio externo y luego poder servirlos como parte de su
solicitud de página de inicio, lo que tal vez quiera hacer es almacenar en caché
esos datos y almacenarlos en caché. en el almacén de datos. Entonces, Datastore, como dijimos
antes, dura aproximadamente 50 milisegundos por solicitud. Mientras que si estás viendo lo
mismo para buscar una URL en un recurso externo lento
, eso puede llevar más de 2 segundos. Entonces, es posible que desee
utilizar procesos fuera de línea para poder posponer
la actualización de esas páginas.

Porque de lo contrario, cuando el
caché caduque simplemente usando una solución ingenua,
todavía tendrías que hacer que una persona espere esa
solicitud de 2 segundos para poder recopilarlo nuevamente y
llenar tu caché. Otras cosas para las que puede utilizar
procesos fuera de línea: realizar procesos externos lentos, por ejemplo, de
facturación. También puede usarlo para crear
sistemas de flujo de trabajo o realizar fan-in, lo cual se describe
en la charla de Brett Slatkin de 2010. Así que repasaré
un ejemplo de cómo usar Taskqueue y
haré el ejemplo de búsqueda de URL que di antes. Entonces estoy usando NDB aquí. La razón por la que estoy usando NDB es que
proporciona almacenamiento en caché transparente a Memcache y
al caché de instancia. Entonces, si esta era una
propiedad bastante utilizada y se mostraba en su página de inicio, entonces es
posible que ni siquiera tenga que ir al almacén de datos.

Ya se podría recuperar en
Memcache o también podría estar simplemente en la
caché de la instancia. Entonces, voy al método de obtención de URL
, así que omitiré el tiempo de truncamiento. Es solo un método auxiliar que
se utiliza para garantizar que no recuperemos esto. No creo demasiadas tareas
para recuperar esto. Entonces, si observamos el método de obtención de URL
, construimos un nombre de clave basado en la URL. Estamos usando sha1, de esa manera
podemos asegurarnos de que el espacio de nombres de todas estas
claves esté distribuido de manera bastante uniforme . Entonces, lo primero que hacemos es
intentar buscarlo en Datastore, si está allí. Si no está allí,
lo buscaremos directamente desde el recurso externo,
lo guardaremos y lo devolveremos de inmediato. Entonces, en el caso de que el primer usuario
vea esta página, es posible que tenga que pagar
aquí el retraso de solicitud de 2 segundos. Si estuviera implementando esto
en su propio código, puede enviar un 302 al
usuario o enviar un marcador de posición para que se muestre la página.

Y luego puede volver
e intentar volver a solicitar la página para que el
usuario vea algo antes. Entonces aquí, si lo encontramos en
Memcache o en Datastore, verificamos si los datos han caducado. Si es así, simplemente aplazamos
una tarea a Taskqueue. Y eso luego
buscará de forma asincrónica la nueva versión mientras devolvemos
la versión actual que está en el caché
al usuario. Y como puede ver, con el
método de actualización de caché, es simplemente recuperarlo del
recurso externo y luego colocarlo ciegamente en Datastore.

Así que ahora pasaré a
Troy, quien hablará sobre la configuración de rendimiento. TROY TRIMBLE: Genial. Gracias, Greg. [CONVERSACIÓN LATERAL] TROY TRIMBLE: Prueba, prueba. Muy bien, ahí vamos. Simplemente hagámoslo. Lo haremos en vivo. Está bien. Hola a todos. Soy ingeniero de software senior
en App Engine. Y hoy
les hablaré sobre las configuraciones de rendimiento que
pueden configurar para que su aplicación optimice ya sea a bajo
costo o a baja latencia. Entonces, la configuración de rendimiento
es algo que introdujimos el año pasado. Hasta donde yo sé, no hemos hablado con ellos
públicamente, como en una conferencia
en este contexto. Entonces hay algunos de ellos. Están en la
parte de configuración de la aplicación de la consola de administración. Y pueden ver aquí que
está la clase de instancia de front-end que Marzia mencionó
anteriormente. Hay instancias inactivas y
latencia pendiente.

Entonces, lo primero de lo que me
gustaría hablar es sobre la optimización para una latencia baja. Entonces, ¿por qué desea optimizar
para lograr una latencia baja? Bueno, es bastante
sencillo. Tiene una interfaz de usuario web o una
interfaz móvil y desea tener una experiencia web muy, muy ágil y buena
para sus usuarios. Entonces, la primera configuración que
puede usar es lo que llamamos instancias inactivas mínimas. Y lo que esto le dice al
programador de App Engine es que usted preferiría que mantuviera
al menos esta cantidad de instancias inactivas en todo momento
para su aplicación. Y para qué se utilizan estas instancias inactivas
es para enviarles tráfico cuando todas
sus instancias activas o dinámicas están actualmente ocupadas
atendiendo otras solicitudes. Y esto es extremadamente útil
para cosas como tráfico en ráfagas o impredecible, de modo
que no tenga que sufrir la temida solicitud de carga
para una solicitud de cara al usuario. Entonces, lo que normalmente les
decimos a los socios internos y externos
que hagan es: si van a tener algún
tipo de evento, como un evento de Google I/O, o algún tipo de
prensa, o alguna característica nueva que piensan que va a
generar una gran cantidad de tráfico a su sitio, por lo que
aumentan temporalmente este número para
amortiguar ese tráfico en ráfagas.

Y luego, más adelante pueden
volver a bajarlo para ahorrar algo más de dinero. La segunda configuración que puede
establecer para optimizar la latencia baja es la
configuración de latencia máxima pendiente. Y lo que esta configuración le dice
al programador es que usted preferiría que ninguna solicitud a
su aplicación espere más que esta cantidad de tiempo
antes de ser procesada por una de sus instancias. Y nuevamente, esto es algo
para decirle al programador que si realmente
desea una experiencia de usuario agradable, no espere a que
aparezca una instancia. Pero automáticamente: el programador debería
aprovisionar automáticamente una cantidad de instancias
para mantener la latencia pendiente promedio por debajo de este umbral. Aquí hay un ejemplo de la
consola de instancias, que también está en la consola de administración. Y puede ver aquí que en
este caso hemos configurado tres para la configuración de instancias mínimas inactivas
. Y eso está representado a la
derecha por la disponibilidad como residente, y luego los dinámicos
debajo que son una especie de clones dinámicos activos.

Entonces puede ver, como mencioné
anteriormente, que la mayoría de las solicitudes a esta aplicación
han sido manejadas por las instancias dinámicas y
solo unas pocas han sido manejadas por las residentes. A continuación se muestra un ejemplo de la
configuración cuando se configuran las instancias inactivas mínimas y
la latencia pendiente máxima. En este caso, la consola de administración
me advierte porque no configuré correctamente la
configuración de solicitud de preparación en app.yaml o
appengine-web.xml. Y este es un requisito para que el programador
utilice adecuadamente las miniinstancias inactivas
. Y eso se debe a que el programador
activará estas instancias inactivas en segundo plano
utilizando lo que llamamos solicitudes de preparación. Y puedes leer más
sobre eso en línea. También me gustaría mencionar,
muy brevemente, una nueva característica que acaba de
aparecer con 1.7.0. Y esa es la
integración del servicio de velocidad de página. Y no entraré en detalles
aquí, pero es parte de la configuración de rendimiento. Y lo que hará es básicamente
almacenar en caché y reescribir el contenido de varios
de sus recursos estáticos para, básicamente, acelerar el
contenido de los datos de su servicio.

A continuación me gustaría hablar sobre
la optimización a bajo costo. Y lo que quiero decir aquí es que
todo el mundo quiere optimizar a bajo coste. Pero en el caso de la configuración de rendimiento
, de lo que realmente estamos hablando aquí es de
usuarios que son aficionados o personas que tienen aplicaciones
con las que realmente no monetizan su tráfico. Están ejecutando esto de forma
gratuita y solo quieren intentar mantener sus costos bajos
a expensas de tener solicitudes de usuarios con latencia potencialmente mayor
para su aplicación. Y la primera configuración
que tenemos aquí es el máximo de instancias inactivas. Y la idea es que le está
diciendo al programador de App Engine que preferiría
que no mantuviera más de esta cantidad de
instancias inactivas para ayudar a servir su aplicación. Y esto también influye en cómo
calculamos las horas de instancia de front-end cobradas
por su aplicación. Porque si nos dijeras que solo
quiero tres instancias inactivas. Y por alguna razón, el
programador puso 10 instancias inactivas, bueno, entonces
no se le deberían cobrar las 7 adicionales.

La segunda configuración aquí es
la latencia mínima pendiente. Y lo que esto le dice al
programador es que usted preferiría que el programador permitiera que
las solicitudes esperaran al menos este tiempo antes de provocar una solicitud de carga
y activar una nueva instancia para atender la solicitud. Y lo que esto hace es básicamente
maximizar la utilización de las instancias
que ya tiene para intentar mantener los costos bajos. Nuevamente, aquí hay un ejemplo
de cómo los configuré.

Configuré la instancia inactiva máxima
en 3 y la latencia pendiente mínima en 750 milisegundos. Y en este punto, me gustaría
tomarme un breve momento para explicar por qué tengo
números específicos aquí de 3 y 750 milisegundos. Estos no son generalmente
aplicables a todas las aplicaciones. Son sólo ejemplos
que he elegido. El número correcto para su
solicitud depende completamente de su
solicitud. Y le animamos a que pruebe
y experimente con estas configuraciones para encontrar el
valor adecuado para su aplicación. A continuación, me gustaría hablar sobre un
antipatrón muy serio que hemos visto demasiadas
veces en la naturaleza.

Y esto consiste básicamente en utilizar simultáneamente
las configuraciones de bajo costo y baja latencia
para su aplicación. Y el problema con esto,
y pueden ver lo que he hecho aquí, es que tanto la instancia inactiva mínima como máxima
es 15. Y el delta entre la latencia mínima
pendiente y máxima pendiente es 50 milisegundos. Y el problema con esta
configuración es que confunde mucho al programador de App Engine
. Simplemente no sabe cómo
operar dentro de un margen tan estrecho de estos umbrales. Y lo que ve, como
administrador de App Engine, es que su aplicación… el programador activará
estas instancias para su aplicación, pero tendrán una
duración extremadamente corta. Aparecerán y
desaparecerán muy, muy rápidamente mientras intenta
satisfacer básicamente estos dos umbrales. Y básicamente genera una gran
agitación en el sistema. Y también devaluará cosas
como el almacenamiento en caché de instancias porque su caché de instancia
no estará disponible por tanto tiempo. Entonces nuestra recomendación
es no hacer esto.

Nuestra recomendación es hacer
algo como esto donde usas solo la configuración de bajo costo o solo
la de baja latencia y configuras las otras
en automática. Ahora me gustaría hablar sobre los
servidores de App Engine, que es un proyecto en curso en este momento,
y cómo afectará las configuraciones de rendimiento que
puede establecer para su aplicación para hacerlas más potentes y
flexibles en el futuro. Pero primero, me gustaría hablar
sobre la motivación por la que hacemos esto. Y la única manera de hacerlo es
hablando de cómo es la jerarquía actual de App Engine
. Como puede ver aquí, tenemos
una aplicación de primer nivel. Cada aplicación tiene un
conjunto de servidores ( o lo siento,
disculpe, servidores) y algún tipo de versiones. Y cada uno de ellos tiene un
conjunto de instancias asociadas. Y como muchos de ustedes saben, si
han estado jugando con la configuración de rendimiento antes,
solo la versión predeterminada recibe la
configuración de rendimiento de la que acabo de hablar.

Entonces, lo que hemos escuchado de los
clientes, al hablar con ellos y recibir comentarios sobre
la arquitectura actual, es que una de las cosas que
realmente no les gusta es que solo tienen una única
versión que se escalará automáticamente para a ellos. Y solo una versión
recibirá la configuración de rendimiento. Entonces, todas las versiones no predeterminadas
no obtienen estas configuraciones de rendimiento. Entonces, lo que hemos hecho es
mudarnos a un mundo que se parece más a esto,
básicamente. Vamos a introducir
un nuevo nivel, que se llama servidor. Y lo que es un servidor es una agrupación conceptual de versiones. Sin embargo, la idea es que en
este nuevo mundo la versión predeterminada de un servidor ahora
podrá recibir la configuración de rendimiento y
tenerla activa y también podrá realizar el escalado automático. Por lo tanto, puede tener varios servidores
con varias versiones predeterminadas o una única
versión predeterminada por servidor, pero cada uno de ellos podrá escalarse
independientemente uno del otro. Entonces, por ejemplo, puedes tener
un servidor con una versión predeterminada que sea para tu
patchwork, para tu MapReduce.

Y esas configuraciones de rendimiento
pueden intentar utilizar las instancias tanto como sea posible
porque lo único que intenta hacer es obtener rendimiento. No necesita baja latencia,
solo necesita rendimiento. De manera similar, continúa teniendo
su interfaz de usuario web que tiene una latencia extremadamente baja y un número
mínimo de instancias inactivas para manejar el tráfico en ráfagas
y brindar una experiencia de usuario realmente ágil . Y para dar un ejemplo de
cómo podrían verse en el futuro, por ejemplo, cómo
vamos a hacer las configuraciones de rendimiento en el futuro, es que en
realidad las tomaremos de la consola de administración
y las colocaremos en su aplicación. .yaml o su App
Engine web.xml. Y así, cuando cargue su
código, también cargará la configuración de rendimiento
que considere apropiada para ese código. Y para dar un ejemplo de eso,
aquí está, por ejemplo, mi servidor frontend móvil. Como puedes ver aquí, esto está en
app.yaml, pero habrá el equivalente en
App Engine web.xml. Y puedes ver aquí, sin embargo,
que hay un nuevo campo llamado servidor.

Esta es mi interfaz móvil.
También tendremos una nueva sección llamada configuración del servidor. Y como pueden ver aquí, son
exactamente las mismas configuraciones que teníamos en la consola de administración. En este caso, configuré F2
y 25 minutos de instancias inactivas y una latencia pendiente máxima
de 250. Las funciones automáticas están ahí solo
para completar, pero en realidad son innecesarias. Esos son los valores predeterminados.

Y este es un ejemplo de
lo que hoy en día se llama tradicionalmente backend. Así es como se verá
en el futuro. De hecho, vamos a mover
la configuración de lo que está hoy en backends.yaml o
backends.xml y, en el futuro, las colocaremos en
app.yaml o App Engine web.xml . Y entonces, en este caso, verá que
este es mi servidor backend geográfico. Tiene 10 instancias. Estático, solo 10 instancias,
sin ajuste de escala automático. Y tiene una clase de instancia de
B8 porque necesito mucha memoria para realizar un
excelente almacenamiento en caché geográfico. Y, para resumir, Marzia
cubrió muchos patrones y antipatrones de modelado de Datastore excelentes
, junto con una serie de técnicas de almacenamiento en caché
. Greg habló sobre las API por lotes
, algunas de las API síncronas que tenemos y algunas
técnicas de procesamiento fuera de línea.

Y cubrí las
configuraciones de rendimiento actuales y cómo se verán
en el futuro. Y con eso, nos gustaría
agradecerles a todos por venir. Ha sido un placer
hablar con usted hoy. Y nos gustaría abrir
el espacio para preguntas. Sin embargo, me gustaría decirle muy brevemente que
si tiene alguna pregunta relacionada específicamente con
su aplicación y que no cree que se aplique a otras personas en
la sala, venga a buscarnos después, dado que este
es una especie de foro. donde queremos responder preguntas generales
tanto como sea posible. Muchas gracias. [APLAUSOS] AUDIENCIA: Estabas hablando de
simplemente seleccionar ciertos campos y que es
mucho más barato. Me pregunto por qué… MARZIA NICCOLAI: Proyecto…

¿
hola? ¿ Está encendido? Oh. ¿ Consultas de proyección? AUDIENCIA: Sí. ¿ Podría ser también más barato
que obtener o es solo para realizar consultas? MARZIA NICCOLAI: Ambas son
pequeñas operaciones de almacén de datos, por lo que son básicamente equivalentes. Pero obviamente, si
vas a… quiero decir, siempre debes
usar get primero. Pero si tiene que hacer una consulta,
utilizar una consulta de proyección le permitirá ahorrar dinero. Quiero decir, si tu entidad
es lo suficientemente pequeña, es la mejor.

Porque a veces
las consultas de proyección pueden tardar un poco más si la entidad
es demasiado grande. Pero solo para unos pocos campos,
es una operación pequeña versus una operación de lectura. AUDIENCIA: Y si realiza una consulta
y lo hace solo con claves, y luego obtiene por separado y
entrelaza con Memcache, su recomendación sería
simplemente hacer una consulta de proyección o hacer una consulta solo con clave y luego
intentar encontrar las entidades en el ¿Memcache? MARZIA NICCOLAI: Entonces, en ese
caso, si estás haciendo una consulta de solo claves y luego una obtención, son
dos operaciones pequeñas versus una operación pequeña para la
consulta de proyección.

Así que creo que
, en ese caso, sería mejor realizar consultas de proyección. Ah, y también tenemos chocolate,
como la última sesión para la gente que
hace preguntas. Entonces, si quieres después,
puedes subir y conseguir un poco. AUDIENCIA: ¿Solo tiene curiosidad por saber si
tiene algunos consejos de depuración para consultas lentas? A menudo encuentro que, especialmente si
estoy obteniendo mucha información, parece que
va muy lento y es un poco difícil de depurar porque
es algo asíncrono, por lo que realmente no ves el costo
hasta más tarde, cuando estás usando la información.

Y no hay
mucha visibilidad… debajo del capó, parece que
cuando haces consultas que están dentro de un grupo de
claves, hay muchas situaciones en las que, en última instancia, se
realizan múltiples búsquedas individuales y no se realiza
el tipo de búsqueda por lotes. se podría esperar que lo
haga una base de datos SQL real. Entonces, en general, ¿cómo
puedo ir a mirar y ver? ¿Por qué es lento? ¿ Realmente está alcanzando un índice? ¿ Qué es lo que está
tardando tanto? ¿ Es la cantidad de
datos que se transfieren, etc.? Porque
a veces me parece un poco opaco. MARZIA NICCOLAI: Creo que las consultas
siempre llegan a los índices. Pero… [ __ ] WHITE: [INAUDIBLE]. MARZIA NICCOLAI: Correcto.

Pero creo que en este
caso, no soy un súper experto en almacenes de datos
, pero me gustan las consultas en zigzag en las que se unen
varias cosas. Quiero decir, probablemente no soy la
persona adecuada para responder esto en detalle, tal vez Greg. GREG DARKE: Solo diré que si
quieres venir y charlar con nosotros después, probablemente
podamos ayudarte con eso. AUDIENCIA: Está bien. Pero me pregunto si hay
páginas básicas sobre las estadísticas o algo que les muestre,
aquí están las consultas que están haciendo. Aquí están las consultas lentas, o
cuánto tiempo tardan en general, o cuántos
datos está transfiriendo, o cuántos RPC diferentes
está creando realmente en el backend.

TROY TRIMBLE: Las cosas de Appstat
que estábamos mostrando , como la mayoría de los
clips aquí con líneas de tiempo y cosas así,
que la mayoría estaban en la charla de Greg, es una herramienta de
depuración extremadamente valiosa que puedes usar en
base única de solicitud. Y tiene… al menos para Python, tiene un
volcado de pila completo donde lo llevará a la línea exacta
de código que lo ejecutó. Entonces realmente puedes profundizar y
decir, oh, esta consulta tomó mucho tiempo. Se ejecutó fuera de servicio
con este otro. Y este es el que
realmente necesito encontrar. Y te dirá cuál
es la línea de código.

AUDIENCIA: Genial. MARZIA NICCOLAI: Pero
también creo… Quiero decir, solía haber
más consultas que requerían índices compuestos que luego
no eran necesarios. Pero aún puedes
volver a agregar índices compuestos para algunas consultas. Estos escribirán más índices,
pero podrían ser más rápidos. Pero nuevamente, es como si hubiera
muchas dependencias que probablemente no sea el mejor
experto para decírselas. Pero esa es una opción también
cuando antes se requería un índice compuesto y ahora
ya no lo es. En ese caso, volver a agregar el índice compuesto
podría acelerar la consulta . AUDIENCIA: Gracias. GREG DARKE: ¿Por la parte de atrás? AUDIENCIA: Sí,
tenía una pregunta. Me pregunto si tenía algún
plan para reducir el precio o quizás ofrecer
precios por niveles para cosas como juegos donde es más difícil monetizar
al ritmo que es el precio actual. TROY TRIMBLE: Quiero decir, hasta donde yo sé,
no tenemos planes de reducir los precios en este momento. Siempre estamos evaluando.

Sabemos que acabamos de publicar
nuevos precios para Compute Engine y cosas
así que están escalonadas. Así que parece que así
van las cosas, pero lamentablemente no tenemos nada que anunciar
hoy. AUDIENCIA: Genial. Gracias. He notado que cada vez que
configuro una instancia residente con la instancia mínima inactiva, mi
aplicación, como a las 2:00 de la mañana cuando nadie la accede
y tengo una instancia inactiva por la que estoy pagando, si accedo a
mi app, prefiere simplemente activar una instancia dinámica
en lugar de usar lo que estoy pagando.

MARZIA NICCOLAI: De modo que
las instancias mini inactivas en realidad están más orientadas a manejar el
tráfico en ráfagas. Por eso siempre preferimos
instancias dinámicas. Pero mantenemos las instancias inactivas
en caso de que no hayamos predicho correctamente si
hay suficientes instancias dinámicas disponibles para atenderlas. Entonces ese es realmente el propósito. Lo que siempre uso en
un ejemplo es, si estás lanzando un sitio web y es
posible que tengas un salto muy pronunciado, muy pronunciado.

Y es difícil para nosotros predecir
exactamente cómo sucederá. Entonces es posible que desee
activar muchas instancias inactivas porque esas instancias
pueden atender una solicitud en caso de necesidad. Pero cuando hay tráfico que es
más estable o que fluye con facilidad,
las instancias inactivas no son tan útiles porque generalmente somos
muy buenos para predecir cuándo hacer una instancia dinámica.

AUDIENCIA: ¿Entonces es para la ráfaga,
no para el tiempo de inicio? MARZIA NICCOLAI: Quiero decir,
es para ambos. Pero debería pensar en ello como
algo que puede atender una solicitud mientras la
solicitud dinámica está funcionando. AUDIENCIA: Bingo. Vale, genial. Gracias. AUDIENCIA: Hola. Gracias por App Engine. Y dijiste que no usáramos límite
y compensación, obviamente porque eso es muy ineficiente, ¿
verdad? TROY TRIMBLE:
En ese caso, está realmente compensado. AUDIENCIA: Oh, compensación. Así es. TROY TRIMBLE: El límite está bien,
pero no hay compensación. AUDIENCIA: Quise decir eso, sí. Pero ¿qué pasa si quieres
retroceder y avanzar una página? Cursor, usas cursor, ¿verdad? MARZIA NICCOLAI: Hay un cursor de inicio
y de fin, ambos. Solo uso el cursor de inicio. AUDIENCIA: Correcto. Cursor de inicio. Pero digamos que tienes un sueldo y
quieres retroceder.

¿ Puedes ir hacia atrás
y hacia adelante? El cursor solo
avanza ¿no? TROY TRIMBLE: No, puede establecer
un cursor de finalización en una consulta. Eso es lo que ella está diciendo. Entonces, de forma predeterminada, es como si hubiera
start_cursor y end_cursor. Entonces puede decir: Creo que está al final,
básicamente de su consulta, creo que debería tener ese cursor al
final. Sé que no lo estoy explicando
muy bien. AUDIENCIA: Tiene que
haber una mejor manera de… AUDIENCIA: Sí, sí. Pero no siempre puedes… No siempre puedo hacer eso.

Preguntaré después. AUDIENCIA: ¿
La configuración del servidor está habilitada ahora o en la próxima versión? MARZIA NICCOLAI: Entonces, la
configuración del servidor es precisamente en lo que estamos trabajando para implementar
ahora. Y una de las razones principales para
mencionarlo es porque… quiero decir, creo que realmente estamos
buscando comentarios sobre cómo podría ser más útil
para ustedes y darles una idea de lo que estamos pensando
en el futuro. . No tenemos una
fecha de lanzamiento prevista, per se. TROY TRIMBLE: Sí, estamos
trabajando activamente en esto en este momento. Si desea hablar más sobre
esto, lo animo a que venga a buscarme después de que hayamos terminado
aquí, y me encantaría escuchar sus comentarios
o ideas al respecto. Definitivamente. Eso va para todos. AUDIENCIA: ¿Hay alguna forma de
visualizar la latencia pendiente? El que no se ve en
la solicitud y a mí me parece que no está reportado en ningún lado. También en el salpicadero, ¿no? MARZIA NICCOLAI: Está
en los registros. Y lo que realmente mencionaría
aquí es que en realidad no tenemos esto; en realidad no hemos escrito
esto, pero probablemente sea realmente útil, tenemos una API de lector de registros
, que en realidad le permite MapReduce
o leer.

sus registros. Y podrías hacer algo como
leer la latencia pendiente. Lea todas sus solicitudes, la
información sobre sus solicitudes, viértalas en algo
como BigQuery o incluso escriba un tipo
de visualización personalizada para ese tipo de registros. Quiero decir, las herramientas básicas para
esto están aquí, pero es algo muy incipiente en términos de
hacer que sean realmente fáciles de usar para ti. Pero es posible. Y creo que es realmente emocionante
poder leer los registros, volcarlos en
BigQuery y realizar consultas. Y creo que es algo que
queremos mejorar en el futuro. Pero obviamente ustedes
podrían hacerlo ahora. Y siempre hay
fuentes abiertas. Quiero decir, no es para exagerar, pero
esto es algo que realmente quiero usar y no he
tenido tiempo de escribir.

Si quisieras escribirlo
, podrías. Y sería realmente útil. Pero para su propia aplicación
y para las aplicaciones de otras personas . TROY TRIMBLE: Sí, bueno,
no se visualiza bien en gráficos ni nada por el estilo, como
en el tablero. Como ella dijo, no solo están en
la API de registros, los datos que se obtienen desde allí, sino que también están
en el lector de registros en la consola de administración. Está justo en la primera línea
de cada solicitud, le indica como pendiente, es como pendiente_ms. Y te lo dice. MARZIA NICCOLAI: Si estaba en
la cola pendiente, está pendiente_latencia en los registros. AUDIENCIA: Tengo curiosidad acerca de la
implementación de entidades integradas y cómo
se compararían las características de rendimiento con otro tipo de
opciones sencillas que tiene ahora, como
JSONificar una entidad o decaparla. GREG DARKE: Entonces, las
entidades integradas son en realidad solo otro modelo de almacén de datos que
acaba de serializarse y luego almacenarse en un campo blob. Lo siento. Para las propiedades estructuradas locales,
se almacenan en un campo de blob en el objeto.

Y puedes comprimirlo
si quieres. Para estructurar correctamente,
tomamos el nombre de las propiedades y las mutamos
para que aún podamos permitirle realizar consultas
sobre eso. En cuanto al rendimiento, el
tiempo de serialización es el mismo que llevaría serializar
las dos entidades. El rendimiento adecuado para una
propiedad estructurada local es simplemente la cantidad de tiempo necesaria
para almacenar esos datos. Con las propiedades estructuradas locales
, debido a que no hay índices adicionales, no tiene
que pagar el tiempo de espera a que esos índices se escriban
para propagarse. Pero aparte de eso, sí. AUDIENCIA: Entonces habló de
entidades locales, entidades locales estructuradas, que
dijo que son datos linealizados. Entonces, ¿qué pasa cuando
lo escribes de nuevo? ¿Lo redistribuye nuevamente
y lo escribe? ¿ O lo escribes
en un solo lugar? Digamos, por ejemplo, que tienes una
publicación de blog y tienes información de perfil.

La información del perfil es
una entidad local en… MARZIA NICCOLAI: Entonces
solo la escribe en el lugar donde usted la escribe. Realmente no cubrí cómo
se podría usar esto, por ejemplo, para desnormalizar completamente. Es solo para señalar cómo se
puede almacenar una estructura. Cuando lo pones en una
entidad, simplemente escribe esa entidad. No
lo actualiza en todas partes. Aún tienes que
hacerlo tú mismo. Pero es realmente bueno porque
te brinda una manera agradable y lógica de entender y
estructurar esto para facilitar la desnormalización, lo que obviamente
ayuda con las consultas. Así que no cubrí
esa parte. AUDIENCIA: El límite máximo de
escritura de 100 o 1000 entidades por transacción aún se aplica
cuando la escribe en… GREG DARKE: Entonces, con la
propiedad estructurada local, en realidad solo cuenta
como una única entidad que está escribiendo. Pero aún debe
cumplir con el límite de un megabyte por entidad. Por lo tanto, puede tener
tantos valores en esa propiedad estructurada local como desee,
siempre que se ajusten al límite de tamaño de un megabyte
de la entidad que contiene esa propiedad estructurada local
.

AUDIENCIA: Entonces, si tengo
mil publicaciones de blog y escribo un perfil de
1 MB, ¿todavía está bien? Entonces no tienes que preocuparte
por escribirlo como 1000 megabytes, ¿verdad? ¿ Estoy teniendo sentido aquí? MARZIA NICCOLAI: No estoy segura
de que lo entendamos exactamente. Entonces la propiedad estructurada se
almacena dentro de una entidad. AUDIENCIA: Piense en ello como
una publicación de blog y una información de perfil. La información de un perfil se encuentra
dentro de la publicación del blog porque desea
desnormalizarla en caso de que desee realizar una consulta. Entonces, si tienes que escribir un
cambio en la información del perfil… MARZIA NICCOLAI: Tendrías
que escribirlo en todas partes. AUDIENCIA: Oh, está bien. AUDIENCIA: Tengo una pregunta
sobre consultas. Supongamos que tengo una
entidad con 10 campos. Supongo que si consulto los 10
campos, es una lectura de entidad completa , ¿verdad? Lo que determina el umbral,
si es una lectura pequeña o… MARZIA NICCOLAI: Si usa
una consulta de proyección y realmente llama a los 10
campos, sigue siendo solo la operación pequeña. Lo que podría suceder
allí es que los escaneos de índice podrían tardar un poco más.

Así que puede que no sea más rápido,
pero sí más barato. AUDIENCIA: Impresionante. Gracias. MARZIA NICCOLAI: Espera, ¿7? AUDIENCIA: [INAUDIBLE]. MARZIA NICCOLAI: No, no. Es una pequeña operación. Es una pequeña operación. Teníamos a Alfredo. AUDIENCIA: Hubo un problema
en el que olvidé qué versión, pero los archivos estáticos en el registro
ya no mostraban la referencia en el registro de acceso.

¿ Page Speed ​​solucionará
ese problema o seguirá teniendo ese problema? AUDIENCIA: [INAUDIBLE]. GREG DARKE: ¿Quieres
responder? MARZIA NICCOLAI: Creo que la velocidad de página
es ortogonal. TROY TRIMBLE: Les presento a
todos a [ __ ] White. [APLAUSOS] [ __ ] WHITE: Para ese
tema específico, sé que no obtenemos toda la
información que tenemos de las solicitudes normales
de solicitudes de caché perimetral. Entonces, si tiene la facturación habilitada,
está brindando un recurso estático y
sale de nuestro caché perimetral. No necesariamente tenemos el
tamaño de la respuesta, o la referencia, o creo que el
campo del agente de usuario, por lo que falta algo de eso. MARZIA NICCOLAI: Entonces, Page Speed
es en realidad nuestra integración con el otro
servicio de Google, Page Speed. Así que eso
no tiene ninguna relación con este tema.

Lo que hace es utilizar ese
servicio para comprimir archivos CSS y, a veces,
archivos JavaScript y servirlos desde el
caché de velocidad de la página. Entonces es muy rápido. Entonces estas dos cuestiones
no están relacionadas. AUDIENCIA: Sólo un pequeño comentario
sobre mi pregunta anterior. Con gráficos pendientes de latencia,
acabo de comprobarlo. De hecho, la última
biblioteca de ProdEagle le permite graficar la latencia pendiente. Para su información, para todos los
que se lo preguntaban. MARZIA NICCOLAI: Genial. GREG DARKE: Genial. AUDIENCIA: Gracias. GREG DARKE: Gracias. AUDIENCIA: Si ya estás
minimizando y combinando tus archivos JS y CSS, ¿Page
Speed ​​te ofrece alguna ventaja? TROY TRIMBLE: Me referiría a la
documentación sobre este. Sé que básicamente tienen
una serie de opciones que puedes elegir dependiendo
de lo que quieras hacer.

Por ejemplo, hay
CSS incorporado. Y no sé si
hacen sprites o algo así. Pero quiero decir, básicamente cada
opción individual realiza una optimización independiente
de las demás. Entonces realmente depende de lo que
estés buscando. AUDIENCIA: ¿Sería una
ventaja ponerlo en la caché de Page Speed? TROY TRIMBLE: Sí. Quiero decir, el almacenamiento en caché
siempre es bueno.

Así que sí, quiero decir, sería una
ventaja ponerlo en la caché de Page Speed. Sí. AUDIENCIA: Está bien. Experimentaré con eso. Gracias. [ __ ] WHITE: Creo que próximamente
habrá mejor documentación , pero el servicio Page Speed
es muy, muy similar a la velocidad de página de código abierto: el
complemento Mod Page Speed ​​Apache. Entonces, el tipo de cosas que hay
son exactamente las que estamos exponiendo, simplemente integradas
en su aplicación. AUDIENCIA: Ya estoy usando las
herramientas de cierre de Google, que ya hacen un trabajo bastante bueno
. Sería bueno. GREG DARKE:
Muchas gracias. Si alguien más quiere… MARZIA NICCOLAI: Sí, si
hiciste una pregunta, recuerda venir a buscar tus barras de chocolate. Y si quieres
venir a hablar con nosotros individualmente, aquí estaremos. [APLAUSOS].

As found on YouTube