From baa4cd510c29ea8bce1e3aaa8ddf91c4b5103d5e Mon Sep 17 00:00:00 2001 From: Dmitry Volodin Date: Thu, 7 Mar 2024 13:32:54 +0100 Subject: [PATCH] Publish benchmarks results. --- .requirements/bench.txt | 1 + CHANGELOG.md | 6 + README.md | 16 +++ benchmarks/README.md | 11 +- benchmarks/linear_x100_1k.png | 1 + benchmarks/p4_x100_1k.png | 1 + benchmarks/single_x100_1k.png | 1 + docs/index.md | 20 ++++ docs/linear_x100_1k.png | Bin 0 -> 45132 bytes docs/p4_x100_1k.png | Bin 0 -> 45806 bytes docs/single_x100_1k.png | Bin 0 -> 45018 bytes tools/docs/update-bench-charts.py | 187 ++++++++++++++++++++++++++++++ 12 files changed, 241 insertions(+), 3 deletions(-) create mode 120000 benchmarks/linear_x100_1k.png create mode 120000 benchmarks/p4_x100_1k.png create mode 120000 benchmarks/single_x100_1k.png create mode 100644 docs/linear_x100_1k.png create mode 100644 docs/p4_x100_1k.png create mode 100644 docs/single_x100_1k.png create mode 100755 tools/docs/update-bench-charts.py diff --git a/.requirements/bench.txt b/.requirements/bench.txt index 30701ef..4649bc8 100644 --- a/.requirements/bench.txt +++ b/.requirements/bench.txt @@ -5,3 +5,4 @@ aiohttp==3.9.3 aiosonic==0.18.0 niquests==3.5.2 pycurl==7.45.3 +matplotlib==3.8.3 \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 111ae6e..8fa30d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 To see unreleased changes, please see the [CHANGELOG on the main branch guide](https://github.com/gufolabs/gufo_http/blob/main/CHANGELOG.md). +## [Unreleased] + +### Added + +* Benchmark results and charts. + ## 0.1.1 - 2024-03-05 ### Added diff --git a/README.md b/README.md index d786184..44b7115 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,7 @@ *Gufo HTTP* is a high-performance Python HTTP client library that handles both asynchronous and synchronous modes. It wraps famous [Reqwest][Reqwest] HTTP client, written in [Rust][Rust] language with [PyO3][PyO3] wrapper. +Our task is to reach maximal performance while maintaining clean and easy-to use API. The getting of single URL is a simple task: @@ -49,7 +50,22 @@ async with HttpClient(auth=BasicAuth("scott", "tiger")) as client: ## Performance +Gufo HTTP is proved to be one of the fastest Python HTTP client available +in the various scenarios. For example: +### Single HTTP/1.1 requests scenario + +![Single requests](docs/single_x100_1k.png) + +### 100 Linear HTTP/1.1 requests scenario + +![Linear requests](docs/linear_x100_1k.png) + +### 100 Parallel HTTP/1.1 requests scenario + +![Parallel requests](docs/p4_x100_1k.png) + +Refer to [benchmarks](benchmarks/README.md) for details. ## On Gufo Stack diff --git a/benchmarks/README.md b/benchmarks/README.md index 5f3444d..a9b8afb 100644 --- a/benchmarks/README.md +++ b/benchmarks/README.md @@ -73,7 +73,7 @@ Run tests: pytest benchmarks/test_single_x100_1k.py ``` -Results: +### Results (lower is better) ``` ================================================================= test session starts ================================================================= platform linux -- Python 3.11.2, pytest-7.4.3, pluggy-1.4.0 @@ -106,6 +106,8 @@ Legend: ================================================================= 10 passed in 9.12s ================================================================== ``` +![Median chart](single_x100_1k.png) + ## 100 Linear HTTP/1.1 Requests Perform set of 100 linear http requests to read 1kb text file using single client session @@ -120,7 +122,7 @@ Run tests: pytest benchmarks/test_linear_x100_1k.py ``` -Results: +### Results (lower is better) ``` ================================================================= test session starts ================================================================= platform linux -- Python 3.11.2, pytest-7.4.3, pluggy-1.4.0 @@ -153,6 +155,8 @@ Legend: ================================================================= 10 passed in 14.29s ================================================================= ``` +![Median chart](linear_x100_1k.png) + ## 100 Parallel HTTP/1.1 Requests Perform 100 HTTP/1.1 requests to read 1kb text file with concurrency of 4 maintaininng @@ -169,7 +173,7 @@ Run tests: pytest benchmarks/test_p4_x100_1k.py ``` -Results: +### Results (lower is better) ``` ================================================================= test session starts ================================================================= platform linux -- Python 3.11.2, pytest-7.4.3, pluggy-1.4.0 @@ -201,6 +205,7 @@ Legend: OPS: Operations Per Second, computed as 1 / Mean ================================================================= 10 passed in 14.76s ================================================================= ``` +![Median chart](p4_x100_1k.png) ## Feedback diff --git a/benchmarks/linear_x100_1k.png b/benchmarks/linear_x100_1k.png new file mode 120000 index 0000000..81889ef --- /dev/null +++ b/benchmarks/linear_x100_1k.png @@ -0,0 +1 @@ +../docs/linear_x100_1k.png \ No newline at end of file diff --git a/benchmarks/p4_x100_1k.png b/benchmarks/p4_x100_1k.png new file mode 120000 index 0000000..11412c7 --- /dev/null +++ b/benchmarks/p4_x100_1k.png @@ -0,0 +1 @@ +../docs/p4_x100_1k.png \ No newline at end of file diff --git a/benchmarks/single_x100_1k.png b/benchmarks/single_x100_1k.png new file mode 120000 index 0000000..8a6b2af --- /dev/null +++ b/benchmarks/single_x100_1k.png @@ -0,0 +1 @@ +../docs/single_x100_1k.png \ No newline at end of file diff --git a/docs/index.md b/docs/index.md index 58796e7..78daa2e 100644 --- a/docs/index.md +++ b/docs/index.md @@ -13,6 +13,7 @@ hero: *Gufo HTTP* is a high-performance Python HTTP client library that handles both asynchronous and synchronous modes. It wraps famous [Reqwest][Reqwest] HTTP client, written in [Rust][Rust] language with [PyO3][PyO3] wrapper. +Our task is to reach maximal performance while maintaining clean and easy-to use API. The getting of single URL is a simple task: @@ -40,6 +41,25 @@ async with HttpClient(auth=BasicAuth("scott", "tiger")) as client: ... ``` +## Performance + +Gufo HTTP is proved to be one of the fastest Python HTTP client available +in the various scenarios. For example: + +### Single HTTP/1.1 requests scenario + +![Single requests](single_x100_1k.png) + +### 100 Linear HTTP/1.1 requests scenario + +![Linear requests](linear_x100_1k.png) + +### 100 Parallel HTTP/1.1 requests scenario + +![Parallel requests](p4_x100_1k.png) + +Refer to [benchmarks](benchmarks.md) for details. + ## On Gufo Stack This product is a part of [Gufo Stack][Gufo Stack] - the collaborative effort diff --git a/docs/linear_x100_1k.png b/docs/linear_x100_1k.png new file mode 100644 index 0000000000000000000000000000000000000000..7d45405e9d30a5a84a06e6e7e862d94cfc608035 GIT binary patch literal 45132 zcmdSCXIPcj)-_CuF}4t+qM(8WL=Z%zh)S`7TPe~71XPqNA_7WB6HAn)8vy|U=^aEs z6e*SfB29WxKt-kZD)k!^%sDyVbDsA-=P5s4t}9m%H+$dry4RX>%rVBCUO%iTw`e}c zd=?g#MT`UcR9IN%$g!||yZ*-?@RK#GVK5Ml@NXYzeFW78x&PXW#^AT0N$-J`%w5(WISdY_x z-$ctqnXs@VJ!b6Nt!8_-v%$_*p=NrxZ~Wz|TR$>5zF)ghWo@)wP}FUW;)vY~_m`PoAb z>Rh7Q9iR5F;Iw$a9DF`~X>2%TxP10o78butXP3@?e^Gtis;@6O=KZ7GH?u!I!t-4D z>uWWx|C=v;IzL_~U2%gKqoX>Zuv6t?i?)giQ_t?xGN-Y&C_mjB+yyl?n$Mm+%NvjC zGny=qIP}V2EKVc-NZ%ic->^Kb*du}G(fjk6w~s+qc7ovPbvKnZNXASXkJ%-+r5V?AfmitCn(b z@Ou@6yG(s)$!V+>5t5KNf?qY^+~z0WUKQud9V6?`vDHtW)$vrSzOiw1xWn4Y$u2!T zy;$wESRVl`rl~@quaG9bv!0r;W0c?KQ>_f$zu;4$uhIsuf_1N7{jMZ4sg{&A?5}6v z#^ai?6&LwD^t_Ia&Zhz|Io#w9hvCk>RehNfXWw1ivv;q}hd-|8@96$@&I0SPL6hc@ zfRkUoOihjV@RbM$6u%1CmW2EC7d7cW(owK*yVYm40|$PW{_@eQX!9JFi*kkmb@Zep zm2fj$i&l!uf9e0ETEOI~2n@9OT*R&(r=f7>%$c#ylv3;FyhTo5KKa%^xsdeGqG_{( zgF{%)yJx=*eQ61fJLJ3BeyB<_?R4GNH1jtacu)yC>CPWB;?(0Jb<)ph9Ua&&X4`x0 z%H_)|dMFH?pl<`SVPyhD2 z@6t@GVy{W-Gp{aM8Tsv;`K`lUZ|XB_;;@i|<2^ZMP1#Q8tgR=M45Z_JS|xGs{{1ag z(aL+Xv$H+T-JraaJ6s_D(IE>K^Sq@N^WRPyrKv-inWw|t_8 zjIwZ195T+C)rq=s+G(azWoF;7^l~ru_!jGV`RLO-n^yn@@?bMs@?#1h?0(lPk810zY8c>|!H2(1J-MgH2@pu#M%nR1mm7{&l>gi{6 zaX;&e2ey_ADFsQ|cO;~{jjY~beK=ˎsZwM*Z(-dMJ&GDelRd2(#1!(A(^t@u}k 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

aIHXRz2?Bg^NRH76EMGcEqm^WmoQ{fa809>uM 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 literal 0 HcmV?d00001 diff --git a/docs/p4_x100_1k.png b/docs/p4_x100_1k.png new file mode 100644 index 0000000000000000000000000000000000000000..3e3bdb14a3eb5c4bedac50f5ed41424d29e9729e GIT binary patch literal 45806 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

1)^q00%|{9Y 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 literal 0 HcmV?d00001 diff --git a/tools/docs/update-bench-charts.py b/tools/docs/update-bench-charts.py new file mode 100755 index 0000000..310485a --- /dev/null +++ b/tools/docs/update-bench-charts.py @@ -0,0 +1,187 @@ +# --------------------------------------------------------------------- +# Gufo HTTP: Generate benchmark charts +# --------------------------------------------------------------------- +# Copyright (C) 2024, Gufo Labs +# See LICENSE.md for details +# --------------------------------------------------------------------- +"""Parse bechmark results and generate charts.""" + +# Python modules +import enum +import re +from dataclasses import dataclass +from typing import Iterable, List, Tuple + +# Third-party modules +import matplotlib.pyplot as plt +from matplotlib import ticker + +rx_name = re.compile(r"^Name \(time in (\S+)\)") + + +@dataclass +class Benchmark(object): + """ + Benchmark descriptor. + + Attributes: + path: Output chart path. + title: Chart title. + """ + + path: str + title: str + + +BENCHMARKS = [ + Benchmark( + title="Single HTTP/1.1 Requests (Median)", + path="docs/single_x100_1k.png", + ), + Benchmark( + title="100 Linear HTTP/1.1 Requests (Median)", + path="docs/linear_x100_1k.png", + ), + Benchmark( + title="100 Parallel HTTP/1.1 Requests (Median)", + path="docs/p4_x100_1k.png", + ), +] + +NAME_MAP = {"gufo_http": "Gufo HTTP", "pycurl": "PycURL"} + + +def normalize_name(s: str) -> str: + """ + Normalize test name. + + Args: + s: Test name. + + Returns: + Normalized name. + """ + if s.startswith("test_"): + s = s[5:] + mode = "" + if s.endswith("_sync"): + s = s[:-5] + mode = " (Sync)" + elif s.endswith("_async"): + s = s[:-6] + mode = " (Async)" + s = NAME_MAP.get(s, s) + return f"{s}{mode}" + + +def build_barchart( + bench: Benchmark, data: List[Tuple[str, float]], scale: str +) -> None: + """ + Build bar chart into SVG file. + + Args: + bench: Benchmark description. + data: List of (name, value). + scale: Time scale label. + """ + + def is_gufo_http(s: str) -> bool: + return "Gufo HTTP" in s + + # Extracting test names and measured values from the data + tests, values = zip(*data) + + # Creating the bar chart + plt.figure(figsize=(10, 6)) + plt.barh( + tests, + values, + color=[ + "#2c3e50" if is_gufo_http(test) else "#34495e" for test in tests + ], + ) + plt.xlabel(f"Time ({scale})") + plt.title(bench.title) + # Adding thousands separator to y-axis labels + plt.gca().xaxis.set_major_formatter(ticker.StrMethodFormatter("{x:,.0f}")) + # Adding text annotations for ratio between each bar and smallest one + min_value = min(values) + for test, value in zip(tests, values): + ratio = value / min_value + fontweight = "bold" if is_gufo_http(test) else "normal" + plt.text( + value, test, f" x{ratio:.2f}", va="center", fontweight=fontweight + ) + # Make y-axis labels bold for test names containing "gufo_http" + for tick_label in plt.gca().get_yticklabels(): + if is_gufo_http(tick_label.get_text()): + tick_label.set_weight("bold") + # Adjusting right padding to shift border to the right + plt.subplots_adjust(right=1.3) + # Saving the plot as an SVG file + print(f"Writing {bench.path}") + plt.savefig(bench.path, format="png", bbox_inches="tight") + plt.close() + + +class Mode(enum.Enum): + """ + Parser mode. + + Attributes: + WAITING: Waiting for table of results. + SKIP_LINE: Table detected, need to skip next line. + PARSING: Parsing table. + """ + + WAITING = 0 + SKIP_LINE = 1 + PARSING = 2 + + +def iter_results(path: str) -> Iterable[Tuple[str, List[Tuple[str, float]]]]: + """ + Read benchmarks docs and extract values for charts. + + Args: + path: README.md path + + Returns: + Yields tuple of (scale, data block) + """ + r = [] + mode = Mode.WAITING + scale = None + with open(path) as fp: + for line in fp: + ln = line.strip() + if mode == Mode.WAITING: + m = rx_name.search(ln) + if m: + scale = m.group(1) + mode = Mode.SKIP_LINE + elif mode == Mode.SKIP_LINE: + mode = Mode.PARSING + elif mode == Mode.PARSING: + if ln.startswith("---"): + mode = Mode.WAITING + yield scale, r + r = [] + else: + parts = ln.split() + name = normalize_name(parts[0]) + value = float(parts[9].replace(",", "")) + r.append((name, value)) + + +def main() -> None: + """Main function.""" + for bench, (scale, data) in zip( + BENCHMARKS, iter_results("benchmarks/README.md") + ): + build_barchart(bench, data, scale) + + +if __name__ == "__main__": + main()