Démasquage de données Websocket / multi-octets xor

La spécification websocket définit le démasquage des données en tant que

j = i MOD 4 transformed-octet-i = original-octet-i XOR masking-key-octet-j 

où mask a une longueur de 4 octets et le démasquage doit être appliqué par octet.

Y a-t-il un moyen de le faire plus efficacement que de simplement boucler des octets?

Le serveur qui exécute le code peut être considéré comme un processeur Haswell, le système d’exploitation est Linux avec un kernel supérieur à 3.2, de sorte que SSE, etc., sont tous présents. Le codage est fait en C, mais je peux aussi faire asm si nécessaire.

J’avais essayé de chercher la solution moi-même, mais j’étais incapable de déterminer s’il y avait une instruction appropriée dans l’une des douzaines de SSE1-5 / AVE / (quelle que soit l’extension – perdue de vue depuis des années)

Merci beaucoup!

Edit: Après avoir relu la spécification à quelques resockets, il semble qu’il s’agisse uniquement de coder les octets de données avec les octets de masque, ce que je peux faire 8 octets à la fois jusqu’aux derniers octets. La question est toujours ouverte, car je pense qu’il pourrait probablement restr encore un moyen d’optimiser l’utilisation de SSE ou similaire (traitement de 16 octets à la fois? Permettant au processus de faire la boucle for??)

Oui, vous pouvez XOR 16 octets en une seule instruction avec SSE2 ou 32 octets à la fois avec AVX2 (Haswell et versions ultérieures).

SSE2:

 #include  // SSE2 inssortingnsics __m128i v, v_mask; uint8_t *buff; // buffer - must be 16 byte aligned for (int i = 0; i < N; i += 16) // note that N must be multiple of 16 { v = _mm_load_si128(&buff[i]); // load 16 bytes v = _mm_xor_si128(v, v_mask); // XOR with mask v = _mm_store_si128(&buff[i], v); // store 16 masked bytes } 

AVX2:

 #include  // AVX2 insortingnsics __m256i w, w_mask; uint8_t *buff; // buffer - must be 16 byte aligned, // and preferably 32 byte aligned for (int i = 0; i < N; i += 32) // note that N must be multiple of 32 { w = _mm256_load_si256(&buff[i]); // load 32 bytes w = _mm256_xor_si256(w, w_mask); // XOR with mask w = _mm256_store_si256(&buff[i], w); // store 32 masked bytes }