Skip to content

Instantly share code, notes, and snippets.

@asraa
Last active January 29, 2021 15:58
Show Gist options
  • Save asraa/8babd3516acd447aa0f2ff5aa61d2e19 to your computer and use it in GitHub Desktop.
Save asraa/8babd3516acd447aa0f2ff5aa61d2e19 to your computer and use it in GitHub Desktop.

Test description

Test origin is an nginx server that replies with an status 200 response and no body:

curl -v 127.0.0.1
*   Trying 127.0.0.1:80...
* Connected to 127.0.0.1 (127.0.0.1) port 80 (#0)
> GET / HTTP/1.1
> Host: 127.0.0.1
> User-Agent: curl/7.72.0
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Server: nginx/1.18.0
< Date: Thu, 14 Jan 2021 17:00:25 GMT
< Content-Type: text/plain
< Content-Length: 0
< Connection: keep-alive
< 
* Connection #0 to host 127.0.0.1 left intact

Envoy Config

static_resources:
  listeners:
  - name: listener_0
    address:
      socket_address:
        protocol: TCP
        address: 0.0.0.0
        port_value: 10000
    filter_chains:
    - filters:
      - name: envoy.filters.network.http_connection_manager
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
          stat_prefix: ingress_http
          route_config:
            name: local_route
            virtual_hosts:
            - name: fortio
              domains: ["*"]
              routes:
              - match:
                  prefix: "/"
                route:
                  cluster: fortio
          http_filters:
          - name: envoy.filters.http.router
  clusters:
  - name: fortio
    connect_timeout: 1s
    type: STRICT_DNS
    # Comment out the following line to test on v6 networks
    # dns_lookup_family: V4_ONLY
    # lb_policy: ROUND_ROBIN
    load_assignment:
      cluster_name: fortio
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address:
                address: 127.0.0.1
                port_value: 80

Nighthawk

For closed loop testing:

taskset -c 0 bazel-bin/nighthawk_client --duration 60 --prefetch-connections --connections 100 -v info --rps 1000  http://127.0.0.1:10000

For open loop testing:

taskset -c 0 bazel-bin/nighthawk_client --open-loop --duration 60 --prefetch-connections --connections 100 -v info --rps 1000  http://127.0.0.1:10000

For adaptive load testing, the demo from envoyproxy/nighthawk#612 ...

Conclusions

Results

Closed Loop

Latency:

RPS BASELINE http_parser llhttp Factory with http_parser
10k 000ms 144us 000ms 153us 000ms 144us
100k 001ms 681us 001ms 661us 001ms 733us
1M 000ms 147us 000ms 147us 000ms 149us

benchmark.http_2xx per second: (upstream_rq_total per second)

RPS BASELINE http_parser llhttp Factory with http_parser
10k 9999.98 9999.98 9999.98
100k 19537.03 19771.98 18953.13
1M 6430.72 6455.37 6374.03

Open Loop

Latency:

RPS BASELINE http_parser llhttp Factory with http_parser
10k 000ms 144us 000ms 153us 000ms 141us
100k 004ms 802us 004ms 801us 004ms 893us
500k 004ms 859us 004ms 737us 004ms 840us

benchmark.http_2xx per second: (upstream_rq_total per second)

RPS BASELINE http_parser llhttp Factory with http_parser
10k 9996.36 9991.66 9999.18
100k 20776.12 20780.71 20389.11
500k 20531.76 21057.95 20611.05

Adaptive QPS

An adaptive load test was run using Nighthawk’s adaptive controller (github.com/nighthawk/issues/416). The tool runs a nighthawk service and adjusts RPS based on feedback signals. The tool was configured to runs with an initial RPS of 10000, and feedback inputs:

  • <5ms for mean latency (limiting factor)
  • >95% success rate for received responses
- BASELINE http_parser llhttp Factory with http_parser Factory with llhttp
Final RPS 20125 20156 19531 19843

Factory Introduction

CPU Profiler

The CPU profile was collected with gperftools and pprof. At 100k RPS (1 min), comparing the baseline with the llhttp swap in:

$ pprof -text -diff_base /tmp/http_parser.cpuprof /tmp/llhttp.cpuprof 
File: envoy-static
Build ID: a4bf24672eeffa8fb0cfced8582945e4974b4d0c
Type: cpu
Showing nodes accounting for 0.12s, 0.2% of 59.97s total
Dropped 24 nodes (cum <= 0.30s)
      flat  flat%   sum%        cum   cum%
    -1.31s  2.18%  2.18%    -32.34s 53.93%  http_parser_execute
     0.78s  1.30%  0.88%     32.17s 53.64%  llhttp__internal__run
    -0.25s  0.42%  1.30%     -0.25s  0.42%  epoll_ctl
     0.22s  0.37%  0.93%      0.22s  0.37%  __GI___writev (inline)
    -0.21s  0.35%  1.28%     -0.21s  0.35%  __GI___readv (inline)

Comparing the baseline with the added factory:

pprof -text -focus=Parser -diff_base /tmp/http_parser.cpuprof /tmp/factory.cpuprof 
File: envoy-static
Build ID: a4bf24672eeffa8fb0cfced8582945e4974b4d0c
Type: cpu
Active filters:
   focus=Parser
Showing nodes accounting for 0.28s, 0.47% of 59.97s total
      flat  flat%   sum%        cum   cum%
     0.06s   0.1%   0.1%      0.06s   0.1%  Envoy::Http::Http1::LegacyHttpParserImpl::getErrno
    -0.05s 0.083% 0.017%     -0.05s 0.083%  Envoy::Router::HeaderParser::evaluateHeaders
     0.04s 0.067% 0.083%      0.04s 0.067%  Envoy::Http::Http1::LegacyHttpParserImpl::method
     0.04s 0.067%  0.15%      0.07s  0.12%  Envoy::Http::Http1::LegacyHttpParserImpl::pause
     0.03s  0.05%   0.2%      0.03s  0.05%  Envoy::Http::Http1::LegacyHttpParserImpl::statusCode
     0.03s  0.05%  0.25%      0.03s  0.05%  Envoy::Http::Http1::LegacyHttpParserImpl::usesTransferEncoding
     0.03s  0.05%   0.3%      0.03s  0.05%  http_parser_pause
     0.02s 0.033%  0.33%      0.02s 0.033%  Envoy::Http::Http1::LegacyHttpParserImpl::Impl::Impl(http_parser_type, void*)::{lambda(http_parser*)#1}::__invoke
     0.02s 0.033%  0.37%      0.02s 0.033%  Envoy::Http::Http1::LegacyHttpParserImpl::Impl::Impl(http_parser_type, void*)::{lambda(http_parser*, char const*, unsigned long)#2}::__invoke
     0.01s 0.017%  0.38%      0.01s 0.017%  Envoy::Http::Http1::LegacyHttpParserImpl::Impl::Impl(http_parser_type, void*)::{lambda(http_parser*, char const*, unsigned long)#3}::__invoke
     0.01s 0.017%   0.4%      0.01s 0.017%  Envoy::Http::Http1::LegacyHttpParserImpl::execute
     0.01s 0.017%  0.42%      0.01s 0.017%  Envoy::Http::Http1::LegacyHttpParserImpl::flags
     0.01s 0.017%  0.43%      0.01s 0.017%  Envoy::Http::Http1::LegacyHttpParserImpl::httpMajor
     0.01s 0.017%  0.45%      0.01s 0.017%  Envoy::Http::Http1::LegacyHttpParserImpl::methodName
     0.01s 0.017%  0.47%      0.01s 0.017%  Envoy::Http::Http1::LegacyHttpParserImpl::resume
         0     0%  0.47%      0.28s  0.47%  Envoy::Event::FileEventImpl::assignEvents(unsigned int, event_base*)::$_1::__invoke
         0     0%  0.47%      0.20s  0.33%  Envoy::Http::CodecClient::CodecReadFilter::onData
         0     0%  0.47%      0.20s  0.33%  Envoy::Http::CodecClient::onData
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment