- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
// https://habr.com/ru/company/oleg-bunin/blog/493242/
// Алгоритмы быстрой обработки HTTP-строк 
// .....
// Как устроен парсер? Мы, как nginx, определяем массив байт и по нему
// проверяем входные данные — это пролог функции. Здесь мы работаем
// только с короткими сроками, используем likely, потому что branch misprediction
// для коротких строк болезненнее, чем для длинных. Выносим этот код наверх.
// У нас есть ограничение в 4 из-за последней строчки — мы должны написать
// достаточно мощное условие. Если будем обрабатывать больше 4 байт, то условие
// будет тяжелее, а код медленнее.
static const unsigned char uri_a[] __attribute__((aligned(64))) = {
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        ...
        // Branch misprediction is more crucial for short strings
        if (likely(len <= 4)) {
                switch (len) {
                case 0:
                    return 0;
                case 4:
                    c3 = uri_a[s[3]];
                    // fall through to process other chars
                case 3:
                    c2 = uri_a[s[2]];
                case 2:
                    c1 = uri_a[s[1]];
                case 1:
                    c0 = uri_a[s[0]];
                }
                return (c0 & c1) == 0 ? c0 : 2 + (c2 ? c2 + c3 : 0);
        }
// Основная петля и большой хвост. В основном цикле обработки мы делим
// данные: если они достаточно длинные, обрабатываем по 128, 64, 32 или
//  по 16 байт. Имеет смысл обрабатывать по 128: мы параллельно используем
// несколько каналов процессора (несколько pipeline) и суперскалярность процессора.
for ( ; unlikely(s + 128 <= end); s += 128) {
        n = match_symbols_mask128_c(__C.URI_BM, s);
        if (n < 128)
                return s - (unsigned char *)str + n;
}
if (unlikely(s + 64 <= end)) {
        n = match_symbols_mask64_c(__C.URI_BM, s);
        if (n < 64)
                return s - (unsigned char *)str + n;
        s += 64;
}
if (unlikely(s + 32 <= end)) {
        n = match_symbols_mask32_c(__C.URI_BM, s);
        if (n < 32)
                return s - (unsigned char *)str + n;
        s += 32;
}
if (unlikely(s + 16 <= end)) {
        n = match_symbols_mask16_c(__C.URI_BM128, s);
        if (n < 16)
                return s - (unsigned char *)str + n;
        s += 16;
}
                                     
        
            ... пиздец. Там еще в той статье пишут, что CloudFlare через AVX2 какое-то говно оптимизируют в говнопаринге http запросов.
Поэтому я за бинарную сериализацию, без всей этой хуйни человекочитаемой