nginx uses bitwise operations for HTTP method parsing

As in every HTTP server, method parsing is a pretty “hot” code path. That’s why it seems to be highly optimized:

#if (NGX_HAVE_LITTLE_ENDIAN && NGX_HAVE_NONALIGNED)

#define ngx_str3_cmp(m, c0, c1, c2, c3)                                       \
    *(uint32_t *) m == ((c3 << 24) | (c2 << 16) | (c1 << 8) | c0)

#define ngx_str3Ocmp(m, c0, c1, c2, c3)                                       \
    *(uint32_t *) m == ((c3 << 24) | (c2 << 16) | (c1 << 8) | c0)

#define ngx_str4cmp(m, c0, c1, c2, c3)                                        \
    *(uint32_t *) m == ((c3 << 24) | (c2 << 16) | (c1 << 8) | c0)

#define ngx_str5cmp(m, c0, c1, c2, c3, c4)                                    \
    *(uint32_t *) m == ((c3 << 24) | (c2 << 16) | (c1 << 8) | c0)             \
        && m[4] == c4

#define ngx_str6cmp(m, c0, c1, c2, c3, c4, c5)                                \
    *(uint32_t *) m == ((c3 << 24) | (c2 << 16) | (c1 << 8) | c0)             \
        && (((uint32_t *) m)[1] & 0xffff) == ((c5 << 8) | c4)

#define ngx_str7_cmp(m, c0, c1, c2, c3, c4, c5, c6, c7)                       \
    *(uint32_t *) m == ((c3 << 24) | (c2 << 16) | (c1 << 8) | c0)             \
        && ((uint32_t *) m)[1] == ((c7 << 24) | (c6 << 16) | (c5 << 8) | c4)

#define ngx_str8cmp(m, c0, c1, c2, c3, c4, c5, c6, c7)                        \
    *(uint32_t *) m == ((c3 << 24) | (c2 << 16) | (c1 << 8) | c0)             \
        && ((uint32_t *) m)[1] == ((c7 << 24) | (c6 << 16) | (c5 << 8) | c4)

#define ngx_str9cmp(m, c0, c1, c2, c3, c4, c5, c6, c7, c8)                    \
    *(uint32_t *) m == ((c3 << 24) | (c2 << 16) | (c1 << 8) | c0)             \
        && ((uint32_t *) m)[1] == ((c7 << 24) | (c6 << 16) | (c5 << 8) | c4)  \
        && m[8] == c8

#else /* !(NGX_HAVE_LITTLE_ENDIAN && NGX_HAVE_NONALIGNED) */

Instead of comparing 4 individual bytes, these macros “glue” them together in a 32-bit number and compare it to the (appropriately casted) string.

Wonder why there is ngx_str3Ocmp? The non-optimized version of it (in the “else”) skips the second character:

#define ngx_str3Ocmp(m, c0, c1, c2, c3)                                       \
m[0] == c0 && m[2] == c2 && m[3] == c3

And later it’s used to skip duplicate checks for all methods with an “O” in second position:

if (m[1] == 'O') {
    if (ngx_str3Ocmp(m, 'P', 'O', 'S', 'T')) {
        r->method = NGX_HTTP_POST;
        break;
    }

    if (ngx_str3Ocmp(m, 'C', 'O', 'P', 'Y')) {
        r->method = NGX_HTTP_COPY;
        break;
    }

    if (ngx_str3Ocmp(m, 'M', 'O', 'V', 'E')) {
        r->method = NGX_HTTP_MOVE;
        break;
    }

    if (ngx_str3Ocmp(m, 'L', 'O', 'C', 'K')) {
        r->method = NGX_HTTP_LOCK;
        break;
    }
}

You can take a look here. That’s some pretty impressive level of optimization!