Cómo comenzar rápidamente con VUE3.0: Ingrese al aprendizaje
Cuando varios contextos acceden a SharedArrayBuffer, si se realizan operaciones en el búfer al mismo tiempo, pueden ocurrir problemas de contención de recursos. La API de Atomics permite que múltiples contextos lean y escriban de forma segura un SharedArrayBuffer al forzar que solo se pueda realizar una operación en el búfer a la vez.
La naturaleza de las operaciones atómicas impide optimizaciones (como el reordenamiento de instrucciones) que el sistema operativo o el hardware de la computadora normalmente realizarían automáticamente. Las operaciones atómicas también hacen imposible el acceso a la memoria al mismo tiempo. Si se usan incorrectamente, pueden hacer que la ejecución del programa se ralentice. Por esta razón, la intención de diseño original de la API de Atomics es crear programas JavaScript complejos de subprocesos múltiples basados en un mínimo pero estable. comportamiento atómico.
La API de Atomics proporciona un conjunto de métodos simples para realizar operaciones de modificación in situ. En la especificación ECMA, estos métodos se definen como operaciones AtomicReadModifyWrite. En esencia, estos métodos leen un valor de una ubicación en SharedArrayBuffer, realizan operaciones aritméticas y bit a bit y, finalmente, escriben el resultado en la misma ubicación. La naturaleza atómica de estas operaciones significa que las operaciones de lectura, modificación y reescritura descritas anteriormente se ejecutarán en orden y no serán interrumpidas por otros subprocesos.
//Crea un búfer de tamaño 1 let sharedArrayBuffer = new SharedArrayBuffer(1); //Crear Unit8Arraylet basado en el búfer typedArray = new Unit8Array(sharedArrayBuffer); //Todos los ArrayBuffers se inicializan en 0console.log(typedArray); //Unidad8Array[0] //Realiza la suma atómica de 10 al valor en el índice 0Atomics.add(typedArray,0,10); //Unidad8Array[10] //Realiza la resta atómica de 10 en el valor del índice 0Atomics.sub(typedArray,0,10); //Unit8Array[0]
El compilador JavaScript del navegador y la propia arquitectura de la CPU tienen la autoridad para reorganizar las instrucciones para mejorar la eficiencia de ejecución del programa. En circunstancias normales, el entorno de subproceso único de JavaScript puede realizar esta optimización en cualquier momento, pero la reorganización de instrucciones en subprocesos múltiples puede provocar contención de recursos y es extremadamente difícil de solucionar.
La API de Atomics resuelve este problema de dos maneras principales:
el orden de todas las instrucciones atómicas entre sí nunca se reorganiza.
El uso de lecturas o escrituras atómicas garantiza que todas las instrucciones no se reordenen en relación con las lecturas y escrituras atómicas.
Además de leer y escribir valores de búfer, Atomics.load() y Atomics.store() también pueden crear "vallas de código". El motor JavaScript garantiza que las instrucciones no atómicas se puedan reorganizar localmente en relación con load() y store(), pero esta reorganización no violará los límites de las lecturas y escrituras atómicas.
constsharedArrayBuffer = nuevo SharedArrayBuffer(4); vista constante = nueva Unit32Array (sharedArrayBuffer); //Realizar escritura no atómica view[0] = 1; // Se puede garantizar que la escritura no atómica se complete antes de esta operación de lectura, por lo que 1console.log(Atomics.load(view,0)); //1 //Realizar escritura atómica Atomics.store(view,0,2); // Se puede garantizar que la lectura no atómica se producirá después de que se complete la escritura atómica, y 2console.log(view[0]) definitivamente se leerá aquí. //2
Para garantizar una lectura continua e ininterrumpida primero y luego la escritura, la API de Atomics proporciona dos métodos: exchange() y compareExchange(). Atomics.exchange() realiza un intercambio simple que garantiza que otros subprocesos no interrumpirán el intercambio.
constsharedArrayBuffer = nuevo SharedArrayBuffer(4); vista constante = nueva Unit32Array (sharedArrayBuffer); //Escribe 10Atomics.store(view,0,10) en el índice 0; //Lee el valor del índice 0 y escribe 5 en el índice 0console.log(Atomics.exchange(view,0,5)); //10 //Leer el valor del índice 0 console.log(Atomics.load(view,0)); //5
En un programa de subprocesos múltiples, es posible que un subproceso solo desee escribir en un búfer compartido si ningún otro subproceso ha modificado el valor desde la última vez que se leyó. Si el valor no se ha modificado, este hilo puede escribir de forma segura el valor actualizado: si el valor se ha modificado, realizar una operación de escritura destruirá el valor calculado por otros hilos. Para este tipo de tarea, la API de Atomics proporciona el método compare-Exchange(). Este método solo realiza la operación de escritura si el valor en el índice de destino coincide con el valor esperado.
Sin algún tipo de mecanismo de bloqueo, los programas multiproceso no pueden soportar requisitos complejos. Con este fin, la API de Atomics proporciona métodos que imitan Linux Futex (mutex rápido de espacio de usuario). Estos métodos, si bien son muy simples en sí mismos, pueden servir como componentes básicos para mecanismos de bloqueo más complejos.
Todas las operaciones atómicas de Futex solo se pueden usar en vistas Int32Array y, además, solo dentro de subprocesos de trabajo.
La mensajería entre documentos, a veces también llamada XDM (mensajería entre documentos), es la capacidad de transferir información entre diferentes contextos de ejecución (como diferentes subprocesos de trabajo o páginas de diferentes fuentes).
La API de codificación se utiliza principalmente para convertir entre cadenas y matrices estereotipadas.
File API todavía se basa en el campo de entrada del archivo en el formulario, pero agrega la capacidad de acceder directamente a la información del archivo. HTML5 agrega una colección de archivos al DOM para elementos de entrada de archivos. Cuando el usuario selecciona uno o más archivos en el campo de archivo, la colección de archivos contendrá un conjunto de objetos Archivo que representan los archivos seleccionados. Cada objeto Archivo tiene algunos atributos de solo lectura.
El tipo FileReader representa un mecanismo de lectura de archivos asincrónico. Puede pensar que FileReader es similar a XMLHttpRequest, excepto que se usa para leer archivos del sistema de archivos en lugar de leer datos del servidor. El tipo FileReader proporciona varios métodos para leer datos de archivos.
readAsText(file,encoding);//Lee el contenido de texto sin formato del archivo y guárdalo en el atributo de resultado
readAsDataURL(file);//Lee el archivo y guarda el URI de datos del contenido en el atributo de resultado
readAsBinaryString(file); //Lee el archivo y guarda los datos binarios de cada carácter en el atributo de resultado
readAsArrayBuffer(file); //Lee el archivo y guarda el contenido del archivo en el atributo de resultado en forma de ArrayBuffer
Una versión sincrónica de Tipo de lector de archivos.
En algunos casos, es posible que necesite leer parte del archivo en lugar de todo el archivo. Para ello, el objeto Archivo proporciona un método llamado segmento(). El método slice() recibe dos parámetros: el byte inicial y el número de bytes en el área de Yaodu. Este método devuelve una instancia de Blob, que en realidad es una superclase de File.
Blob representa un objeto binario grande, que es el tipo de encapsulación de JavaScript para datos binarios no modificables. Para crear blobs se pueden utilizar matrices que contienen cadenas, ArrayBuffers, ArrayBufferViews e incluso otros blobs. El constructor Blob puede recibir un parámetro de opciones y especificar el tipo MIME en él.
Streams API nació para resolver un problema simple pero básico: ¿Cómo consume una aplicación web pequeños bloques ordenados de información en lugar de grandes bloques de información? Hay dos escenarios de aplicación principales para esta capacidad.
La API Streams define tres secuencias:
Secuencia legible: una secuencia que puede leer bloques de datos a través de una interfaz pública. Los datos ingresan al flujo internamente desde la fuente subyacente y luego son procesados por el consumidor.
Flujo grabable: flujo en el que se pueden escribir bloques de datos a través de alguna interfaz pública. El productor (consumidor) escribe datos en la secuencia y los datos se transfieren internamente a la ranura de datos subyacente (sumidero).
Flujo de conversión: consta de dos flujos, el flujo de escritura se usa para recibir datos y el flujo de lectura se usa para generar datos. Estas dos comprobaciones de calidad de la transmisión son transformadores que pueden inspeccionar y modificar el contenido de la transmisión según sea necesario.
La API de criptografía web describe un conjunto de herramientas de criptografía que estandariza cómo JavaScript implementa el cifrado de forma segura y convencional. Estas herramientas incluyen generar, usar y aplicar pares de claves criptográficas, cifrar y descifrar información y generar números aleatorios de manera confiable.
Mucha gente usa Math.random()
cuando necesitan generar números aleatorios. Este método se implementa en el navegador como un generador de números pseudoaleatorios (PRNG, PseudoRandom Number Generator). El llamado pseudo se refiere al proceso de generación de valores que no es verdaderamente aleatorio. Los valores generados por PRNG sólo simulan características aleatorias. El PRNG del navegador no utiliza una fuente aleatoria verdadera, sino que solo aplica un algoritmo fijo a un estado interno. Cada vez que se llama a Math.random()
, este estado interno se modifica mediante un algoritmo y el resultado se convierte en un nuevo número aleatorio. Por ejemplo, el motor V8 utiliza un algoritmo llamado xorshift128+
para realizar esta modificación.
Dado que el algoritmo en sí es fijo y su entrada es solo el estado anterior, también se determina la secuencia de números aleatorios. xorshift128+
utiliza un estado interno de 128 bits y el algoritmo está diseñado para que cualquier estado inicial genere 2128 -1 valores pseudoaleatorios antes de repetirse. Este tipo de bucle se llama bucle de permutación y la longitud de este bucle se llama período. Es obvio que si el atacante conoce el estado interno del PRNG, puede predecir los valores pseudoaleatorios generados posteriormente. Si el desarrollador usa PRNG sin darse cuenta para generar una clave privada para el cifrado, el atacante puede usar esta característica de PRNG para calcular la clave privada.
Los generadores de números pseudoaleatorios se utilizan principalmente para calcular rápidamente números aparentemente aleatorios, pero no son adecuados para algoritmos de cifrado. Para resolver este problema, se utiliza un generador de números pseudoaleatorios criptográficamente seguro (CSPRNG, Cryptographically Secure PseudoRandom Number Generator), añadiendo además una entropía. Entrada, como probar el tiempo del hardware u otras características del sistema con comportamiento impredecible, aunque no es tan rápido como PRNG, el valor generado es más difícil de predecir y puede usarse para cifrado.
La API de criptografía web presenta CSPRNG, al que se puede acceder en el objeto Crypto
global a través de crypto.getRandomValues()
. A diferencia de Math.random()
que devuelve un número de punto flotante entre 0 y 1, getRandomValues()
escribe valores aleatorios en la matriz estereotipada que se le pasa como parámetro. La clase de la matriz estereotipada no importa porque el búfer subyacente se llenará con bits aleatorios.