12El principio y la implementación de Tencent MMKV
Sin embargo, también trae muchos problemas, especialmente el problema ANR causado por SP, que es muy común.
Debido a esto, posteriormente aparecieron algunas alternativas a SP, como MMKV.
Este artículo incluye principalmente los siguientes contenidos.
Pregunta en 1. Uso básico e introducción de Preferencias Compartidas
2.2. MMKV
Principios de 3.3. MMKV
1. Modo de lectura y escritura: E/S directa.
2. Formato de datos: xml
3. Modo de escritura: actualización completa
Debido a que SP usa el formato xml para guardar datos, solo puede actualizarlos cada vez. Se reemplazan los datos.
Esto significa que si tenemos 100 datos, si solo actualizamos un dato, también necesitamos convertir todos los datos al formato xml y luego escribirlos en el archivo a través de io.
Esto también conduce a una baja eficiencia de escritura en SP.
Como se muestra arriba
1.commit tiene un valor de retorno que indica si la modificación se envió correctamente.
2. La confirmación es sincrónica y no se completará hasta que la operación del disco sea exitosa.
Por lo tanto, cuando la cantidad de datos es relativamente grande, es probable que el uso de la confirmación provoque ANR.
El envío es sincrónico y SP también proporciona aplicaciones asincrónicas.
Aplicar envía atómicamente los datos modificados a la memoria y luego los envía de forma asincrónica al disco de hardware, mientras que la confirmación los envía de forma sincrónica al disco de hardware. Por lo tanto, cuando se envían varias confirmaciones simultáneas, esperarán a que las confirmaciones procesadas se guarden en el disco antes de operar, lo que reduce la eficiencia. Aplicar solo envía el contenido de forma atómica. La función llamada aplicar más tarde sobrescribirá directamente los datos de la memoria anterior, lo que mejora la eficiencia hasta cierto punto.
Pero la aplicación también puede causar problemas de ANR.
Para garantizar que las tareas asincrónicas se puedan completar a tiempo, se llamará a QueuedWork.waitToFinish() cuando el ciclo de vida esté en handleStopService(), handlePauseActivity() y handleStopActivity(), esperando la escritura. tarea a completar.
Entonces, cuando la cantidad de datos es relativamente grande, la aplicación también provocará ANR.
No solo las operaciones de escritura, todos los métodos getXXX() son sincrónicos. Cuando el hilo principal llama al método get, debe esperar a que el SP termine de cargarse, lo que también puede causar ANR.
Llamar al método getSharedPreferences() eventualmente llamará al método SharedPreferenceSimpl # startloadFromdisk() para iniciar el hilo para leer datos de forma asíncrona.
Como puedes ver, se inicia un hilo para leer los datos de forma asincrónica. Cuando estamos leyendo datos relativamente grandes y no hemos terminado de leerlos, llamamos al método getXXX().
Cuando se llama al método wait() en un método sincronizado, esperará a que el hilo iniciado por el método getSharedPreferences() termine de leer los datos antes de continuar. Si está bien leer unos pocos KB de datos, suponiendo que se lea un archivo grande, el hilo principal inevitablemente se bloqueará.
MMKV es un componente clave-valor basado en el mapeo de memoria mmap. La serialización/deserialización subyacente se implementa mediante protobuf, que tiene un alto rendimiento y una gran estabilidad. Se utiliza en WeChat desde mediados de 2015 y su rendimiento y estabilidad se han verificado con el tiempo. Recientemente ha sido portado a la plataforma Android/macOS/Win32/POSIX y es de código abierto.
1.MMKV implementa la interfaz SharedPreferences y puede cambiar sin problemas.
2. Proporcione un bloque de memoria en el que se pueda escribir en cualquier momento a través del archivo de asignación de memoria mmap. La aplicación solo escribe datos en él y el sistema operativo es responsable de volver a escribir la memoria en el archivo. No hay necesidad de preocuparse por la pérdida de datos debido a fallas.
3. Seleccione el protocolo protobuf para 3. Serialización de datos MMKV, pb tiene un buen rendimiento en términos de rendimiento y uso de espacio.
4.SP es una actualización completa y MMKV es una actualización incremental, que tiene ventajas de rendimiento.
Se pueden encontrar detalles de uso detallados en el archivo: github.com/Tencent/MMK…
Sabemos que SP está escrito y operado en base a IO. Para comprender IO, primero debemos comprender el espacio del usuario y el espacio del kernel.
Proceso de escritura de archivos:
1. Llame a write para indicarle al kernel la dirección inicial y la longitud de los datos que se escribirán.
2. El kernel copia los datos al caché del kernel.
3. Es llamado por el sistema operativo para copiar los datos al disco y completar la escritura.
Linux inicializa el contenido de un área de memoria virtual asociando el área de memoria virtual con objetos en el disco. Este proceso se llama mapeo de memoria.
Mmap asignará espacio de direcciones en la memoria virtual del proceso y creará una relación de mapeo.
Después de realizar esta relación de mapeo, puede leer y escribir esta memoria a través del puntero, y el sistema volverá a escribir automáticamente en el disco de archivos correspondiente.
Se puede observar que la velocidad de escritura de MMAP es básicamente la misma que la de la memoria, mucho mayor que la de SP, por lo que MMKV es más rápido.
Sin embargo, esto también hará que el SP actualice completamente los datos según sea necesario.
La estructura de datos de MMKV es la siguiente
MMKV usa Protobuf para almacenar datos, guarda menos datos redundantes, ahorra más espacio y puede agregar datos fácilmente al final.
Escritura incremental
Independientemente de si las palabras clave se repiten, los datos se agregan directamente a los datos anteriores. Esto es más eficiente y solo es necesario insertar un dato para actualizar los datos.
Por supuesto, esto también causará problemas. ¿Qué debo hacer si el contenido se agrega de forma incremental y el archivo aumenta de tamaño?
Cuando el tamaño del archivo no es suficiente, es necesario escribirlo completo. Después de eliminar las claves duplicadas de los datos, si el tamaño del archivo coincide con el tamaño de los datos escritos, el volumen de escritura completo se puede actualizar directamente; de lo contrario, es necesario expandirlo. (Al expandir, el tamaño del archivo que puede ser necesario en el futuro se calcula en función del tamaño promedio de cada K-V para la expansión para evitar escrituras regulares a gran escala).