<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ciro Spaciari</title>
    <description>The latest articles on DEV Community by Ciro Spaciari (@cirospaciari).</description>
    <link>https://dev.to/cirospaciari</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F162135%2F6bfb6623-2680-4188-bd54-ba4c26366cb7.png</url>
      <title>DEV Community: Ciro Spaciari</title>
      <link>https://dev.to/cirospaciari</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/cirospaciari"/>
    <language>en</language>
    <item>
      <title>Adding better DX to the fastest Python WebFramework</title>
      <dc:creator>Ciro Spaciari</dc:creator>
      <pubDate>Mon, 09 Jan 2023 10:30:11 +0000</pubDate>
      <link>https://dev.to/cirospaciari/adding-better-dx-to-the-fastest-python-webframework-3o1d</link>
      <guid>https://dev.to/cirospaciari/adding-better-dx-to-the-fastest-python-webframework-3o1d</guid>
      <description>&lt;p&gt;After more than a year of active development, I finally publish my package to PyPI!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;socketify
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After some people asks to also create a WSGI and ASGI server to improve projects using other frameworks, I worked hard to get it right.&lt;/p&gt;

&lt;p&gt;But in the end, we outperform uvicorn and meinheld with Flask, Django, Emmett, FastAPI, and Falcon in TechEmPower plaintext with our WSGI and ASGI servers!&lt;/p&gt;

&lt;p&gt;And we got the Top 1 with socketify itself! &lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.techempower.com/benchmarks/#section=test&amp;amp;runid=7ce481b2-49ec-4a4d-952d-bb1334d4a4ad&amp;amp;test=plaintext&amp;amp;l=hra0hr-35r"&gt;https://www.techempower.com/benchmarks/#section=test&amp;amp;runid=7ce481b2-49ec-4a4d-952d-bb1334d4a4ad&amp;amp;test=plaintext&amp;amp;l=hra0hr-35r&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Also added a CLI tool with very familiar options for uvicorn and gunicorn users&lt;/p&gt;

&lt;p&gt;CLI: &lt;a href="https://docs.socketify.dev/cli.html"&gt;https://docs.socketify.dev/cli.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Also added lifespan (start and shutdown) events to socketify itself, and added an improved DX for routing and support to Extensions/Plugins.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# main.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;socketify&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;App&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;App&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;on_start&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;on_start&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="c1"&gt;# we can start connection pools here
&lt;/span&gt;        &lt;span class="k"&gt;pass&lt;/span&gt;

    &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;on_shutdown&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;on_shutdown&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="c1"&gt;# and here we can clean connection pools
&lt;/span&gt;        &lt;span class="k"&gt;pass&lt;/span&gt;

    &lt;span class="n"&gt;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;router&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;router&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prefix&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/api"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;private&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;router&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/api"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;auth_middleware&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;home&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello, World!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# will serve in /api/hello
&lt;/span&gt;    &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/hello"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
       &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello API!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# will serve in /api/users and use auth_middleware
&lt;/span&gt;    &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;private&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/users"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_users&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
       &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello private API!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; python3 &lt;span class="nt"&gt;-m&lt;/span&gt; socketify main:run &lt;span class="nt"&gt;--port&lt;/span&gt; 8080 &lt;span class="nt"&gt;--workers&lt;/span&gt; 2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;About Extensions: &lt;a href="https://docs.socketify.dev/extensions.html"&gt;https://docs.socketify.dev/extensions.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;My focus until v0.1.0 now will be to add features to help developers and add more optimizations.&lt;/p&gt;

&lt;p&gt;Are there any features that you want to see in the future? I will love to get community feedback!&lt;/p&gt;

&lt;p&gt;Project: &lt;a href="https://github.com/cirospaciari/socketify.py"&gt;https://github.com/cirospaciari/socketify.py&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Issues and Planned Features: &lt;a href="https://github.com/cirospaciari/socketify.py/issues"&gt;https://github.com/cirospaciari/socketify.py/issues&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Releases: &lt;a href="https://github.com/cirospaciari/socketify.py/releases"&gt;https://github.com/cirospaciari/socketify.py/releases&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>showdev</category>
      <category>webdev</category>
    </item>
    <item>
      <title>The Status of Python Web Performance at the end of 2022</title>
      <dc:creator>Ciro Spaciari</dc:creator>
      <pubDate>Mon, 14 Nov 2022 13:14:57 +0000</pubDate>
      <link>https://dev.to/cirospaciari/a-look-on-python-web-performance-at-the-end-of-2022-3i02</link>
      <guid>https://dev.to/cirospaciari/a-look-on-python-web-performance-at-the-end-of-2022-3i02</guid>
      <description>&lt;p&gt;Let's talk about the current state of python web framework throughput performance, using the very popular TechEmPower as reference, looking only to PlainText to check only the framework throughput not the DB library or JSON library performance, we can see that for a few years &lt;a href="https://github.com/squeaky-pl/japronto" rel="noopener noreferrer"&gt;&lt;code&gt;japronto&lt;/code&gt;&lt;/a&gt; dominates the top.&lt;/p&gt;

&lt;h2&gt;
  
  
  Round 21:
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F6379399%2F200957650-577ef219-d759-4517-868d-e5721d191d1c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F6379399%2F200957650-577ef219-d759-4517-868d-e5721d191d1c.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Check the results here: &lt;a href="https://www.techempower.com/benchmarks/#section=data-r21&amp;amp;test=plaintext&amp;amp;l=zijzen-6bj" rel="noopener noreferrer"&gt;https://www.techempower.com/benchmarks/#section=data-r21&amp;amp;test=plaintext&amp;amp;l=zijzen-6bj&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The state of japronto
&lt;/h2&gt;

&lt;p&gt;The source code from the project resides in the &lt;a href="https://github.com/squeaky-pl/japronto" rel="noopener noreferrer"&gt;github&lt;/a&gt;, with more than 8.6k stars and 596 forks is a very popular github, but no new releases are made since 2018, looks pure much not maintained anymore, no PR's are accepted no Issues are closed, still without windows or macOS Silicon, or PyPy3 support. Japronto it self uses &lt;a href="https://github.com/MagicStack/uvloop" rel="noopener noreferrer"&gt;uvloop&lt;/a&gt; with more than 9k stars and 521 forks and different from japronto is seems to be well maintained.&lt;/p&gt;

&lt;p&gt;So how the only Python framework hiting more than 1 million, actually more than 2.6 million of requests per second, more than 4.7 times than the second place falcon with only 564k requests per second, is an obsolete project with no secure updates since 2018 and still keeped by TechEmPower in the charts? I don't know but japronto github says that is an early preview and recomend the use of sanic with hits 277k requests per second.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/sanic-org/sanic" rel="noopener noreferrer"&gt;Sanic&lt;/a&gt; is very very popular with 16.6k stars, 1.5k forks, opencollective sponsors and a very active github.&lt;br&gt;
&lt;a href="https://github.com/falconry/falcon" rel="noopener noreferrer"&gt;Falcon&lt;/a&gt; is more popular than japronto with 8.9k stars, 898 forks, opencollective sponsors and a very active github too.&lt;br&gt;
Despite Japronto been keeped as first place by TechEmPower, Falcon is a way better solution in general with performance similar to &lt;a href="https://github.com/fastify/fastify" rel="noopener noreferrer"&gt;fastify&lt;/a&gt; an very fast node.js framework that hits 575k requests per second in this benchmark.&lt;/p&gt;

&lt;h2&gt;
  
  
  So... Is still hope for hitting 1 million requests or more with Python?
&lt;/h2&gt;

&lt;p&gt;After year of japronto dominance as the firsy place of TechEmPower PlaintText for Python,&lt;br&gt;
a new library called &lt;a href="https://github.com/vibora-io/vibora" rel="noopener noreferrer"&gt;vibora&lt;/a&gt; appears... and it's another project without any updates since 2019. Ok let's filter vibora and japronto and go for the next one that is active, a new library called &lt;a href="https://github.com/cirospaciari/socketify.py" rel="noopener noreferrer"&gt;socketify.py&lt;/a&gt; and also another new library called &lt;a href="https://github.com/sansyrox/robyn" rel="noopener noreferrer"&gt;robyn&lt;/a&gt; arrives on the millions req/s in the &lt;a href="https://tfb-status.techempower.com/" rel="noopener noreferrer"&gt;live results&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F6379399%2F201527713-2e90455d-8d3a-4740-8957-dcaa7ace5ce4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F6379399%2F201527713-2e90455d-8d3a-4740-8957-dcaa7ace5ce4.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Check the results here: &lt;a href="https://www.techempower.com/benchmarks/#section=test&amp;amp;runid=43469a25-670e-4bda-a3c3-652839435784&amp;amp;test=plaintext&amp;amp;l=hra0hr-35n&amp;amp;w=18y6o-0-0-0&amp;amp;f=0-0-0-0-0-w-0-0-0-0-0-8vn08w-0-0" rel="noopener noreferrer"&gt;https://www.techempower.com/benchmarks/#section=test&amp;amp;runid=43469a25-670e-4bda-a3c3-652839435784&amp;amp;test=plaintext&amp;amp;l=hra0hr-35n&amp;amp;w=18y6o-0-0-0&amp;amp;f=0-0-0-0-0-w-0-0-0-0-0-8vn08w-0-0&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With &lt;a href="https://github.com/cirospaciari/socketify.py" rel="noopener noreferrer"&gt;socketify.py&lt;/a&gt; hiting more than 2 million of requests with Python or PyPy3, and &lt;a href="https://github.com/sansyrox/robyn" rel="noopener noreferrer"&gt;robyn&lt;/a&gt; with more than 1 million the hope of an stable and well maintained library that can hit in the millions is born again.&lt;/p&gt;

&lt;h2&gt;
  
  
  But how it compare in others benchmarks?
&lt;/h2&gt;

&lt;p&gt;I pick uvicorn, falcon and robyn for comparison using &lt;a href="https://github.com/hatoo/oha" rel="noopener noreferrer"&gt;oha&lt;/a&gt; using 40 concurrent requests for 5s, running 1 time for warmup and getting an average of 3 runs, just sending back an &lt;code&gt;"Hello, World!"&lt;/code&gt; message.&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;p&gt;oha &lt;span class="nt"&gt;-c&lt;/span&gt; 40 &lt;span class="nt"&gt;-z&lt;/span&gt; 5s &lt;a href="http://localhost:8000/" rel="noopener noreferrer"&gt;http://localhost:8000/&lt;/a&gt;&lt;/p&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  HTTP requests per second (Linux x64)&lt;br&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fcirospaciari%2Fsocketify.py%2Fmain%2Fmisc%2Fbench-bar-graph.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fcirospaciari%2Fsocketify.py%2Fmain%2Fmisc%2Fbench-bar-graph.svg" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It's a really an over simplificated microbenchmark, but shows a big difference between TechEmPower benchmarks using wrk and + 16 pipelining with an lua script, and of course will not hit 1 million req/s on my machine, running tfb tools in my machine socketify.py + PyPy3 hits 770k req/s for some context.&lt;/p&gt;

&lt;p&gt;It also show that PyPy3 will not magically boost your performance, you need to integrate in a manner that PyPy3 can optimize and delivery CPU performance, with a more complex example maybe it can help more. But why socketify is so much faster using PyPy3? The answer is CFFI, socketify did not use Cython for integration and cannot delivery the full performance on Python3, this will be solved with &lt;a href="https://hpyproject.org/" rel="noopener noreferrer"&gt;HPy&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Also we can see that the Cython + meinheld (that is builded with C) are WAY faster than other options of falcon, but you will not get an optimized JIT for all python code that you write in a real life project.&lt;/p&gt;

&lt;p&gt;HTTP pipelining is buggy and not really supported by browsers, the technique was superseded by multiplexing via HTTP/2, which is supported by most modern browsers, TechEmPower don't test HTTP/2 or HTTP/3.&lt;/p&gt;

&lt;p&gt;In HTTP/3, multiplexing is accomplished via QUIC which replaces TCP. This further reduces loading time, as there is no head-of-line blocking even if some packets are lost.&lt;/p&gt;

&lt;p&gt;Supporting HTTP/2 and HTTP/3 is way more important than winning TechEmPower HTTP/1.1 benchmarks, this only means you need to take any benchmark with a grain of salt, and run bencharks in an more close to reality scenario by our self, Caching strategy, Bandwidth, Latency, CPU time, Memory, all are relevant and not really tested here. &lt;/p&gt;

&lt;h3&gt;
  
  
  WebSocket Messages per second (Linux x64)
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fcirospaciari%2Fsocketify.py%2Fmain%2Fmisc%2Fws-bar-graph.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fcirospaciari%2Fsocketify.py%2Fmain%2Fmisc%2Fws-bar-graph.svg" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Socketify.py got almost 900k messages/s with PyPy3 and 860k with Python3 the same performance as &lt;a href="https://bun.sh" rel="noopener noreferrer"&gt;Bun&lt;/a&gt;,&lt;br&gt;
with Falcon 35k messages/s and with Falcon with PyPy3 56k messages/s, node.js manages 192k.&lt;/p&gt;

&lt;p&gt;Bun is REALLY fast! But why the performance of Bun is almost identicall to socketify.py? The answer is that it also uses uWebSockets as base, actually the same code of the PR i made to the C API is been used in Bun with some tweaks, and it endup with almost the same performance that &lt;a href="https://github.com/cirospaciari/socketify.py" rel="noopener noreferrer"&gt;socketify.py&lt;/a&gt;, showing that both have some DNA in common.&lt;/p&gt;

&lt;p&gt;I will do a more deep look and benchmarks in future, but for now it's it.&lt;/p&gt;

&lt;p&gt;This library still very young with less than 100 stars on github, still a very young library that gives commercial support and are looking for sponsors, It's built on the shoulders of giants (very well tested, maintained and supported giants), bringing HTTP, HTTP/2 and WebSockets support, with experimental HTTP/3 in the roadmap, is already a much more complete than japronto.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Runtime versions: PyPy3 7.3.9, Python 3.10.7, node v16.17.0, bun v0.2.2&lt;br&gt;&lt;br&gt;
Framework versions: gunicorn 20.1.0 + uvicorn 0.19.0, socketify alpha, gunicorn 20.1.0 + falcon 3.1.0, robyn 0.18.3&lt;br&gt;&lt;br&gt;
HTTP tested with oha -c 40 -z 5s &lt;a href="http://localhost:8000/" rel="noopener noreferrer"&gt;http://localhost:8000/&lt;/a&gt; (1 run for warmup and 3 runs average for testing)&lt;br&gt;&lt;br&gt;
WebSocket tested with &lt;a href="https://bun.sh" rel="noopener noreferrer"&gt;Bun.sh&lt;/a&gt; bench chat-client check the source code in &lt;a href="https://github.com/cirospaciari/socketify.py/tree/main/bench" rel="noopener noreferrer"&gt;this link&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Machine OS: Debian GNU/Linux bookworm/sid x86_64 Kernel: 6.0.0-2-amd64 CPU: Intel i7-7700HQ (8) @ 3.800GHz Memory: 32066MiB &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Follow &lt;a href="https://twitter.com/cirospaciari" rel="noopener noreferrer"&gt;@cirospaciari&lt;/a&gt; on twitter for more updates about &lt;a href="https://github.com/cirospaciari/socketify.py" rel="noopener noreferrer"&gt;socketify.py&lt;/a&gt; and if you have some time check out the github &lt;a href="https://github.com/cirospaciari/socketify.py" rel="noopener noreferrer"&gt;https://github.com/cirospaciari/socketify.py&lt;/a&gt; this project can be even better with some community love ;)&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>python</category>
      <category>webdev</category>
    </item>
    <item>
      <title>This is how i got more performance in WebSockets than Node or Bun using Python</title>
      <dc:creator>Ciro Spaciari</dc:creator>
      <pubDate>Fri, 11 Nov 2022 20:44:57 +0000</pubDate>
      <link>https://dev.to/cirospaciari/bun-was-16-times-faster-than-python-in-websockets-but-not-anymore-og5</link>
      <guid>https://dev.to/cirospaciari/bun-was-16-times-faster-than-python-in-websockets-but-not-anymore-og5</guid>
      <description>&lt;p&gt;&lt;a href="https://bun.sh" rel="noopener noreferrer"&gt;Bun&lt;/a&gt; is changing out the scenario for Node.js, with much more performance in HTTP and WebSockets, but how FAST it is compared with Python?&lt;/p&gt;

&lt;p&gt;In the Bun website &lt;a href="https://bun.sh/" rel="noopener noreferrer"&gt;https://bun.sh/&lt;/a&gt;, the source code of the WebSocket benchmark is available, so... let's try to run Falcon + uvicorn on it!&lt;/p&gt;

&lt;h2&gt;
  
  
  Benchmark
&lt;/h2&gt;

&lt;p&gt;I just simplified a little the benchmark, to remove a string concatenation, to measure more of the raw throughput with less impact other things, and runned using Falcon + uvicorn and &lt;a href="https://github.com/cirospaciari/socketify.py" rel="noopener noreferrer"&gt;socketify.py&lt;/a&gt;, when benchmarking i was talking with Vytautas Liuolia in the &lt;a href="https://gitter.im/falconry/user" rel="noopener noreferrer"&gt;Falcon Gitter&lt;/a&gt; for tunning HTTP performance in other raw throughtput testing as well, and Falcon is not so much focused on WS performance, this also depends a lot of ASGI server too. For this test i choose uvicorn with gunicorn as ASGI server. &lt;/p&gt;

&lt;p&gt;Messages per second with Linux x64:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fcirospaciari%2Fsocketify.py%2Fmain%2Fmisc%2Fws-bar-graph.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fcirospaciari%2Fsocketify.py%2Fmain%2Fmisc%2Fws-bar-graph.svg" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Runtime versions: PyPy3 7.3.9, Python 3.10.7, node v16.17.0, bun v0.2.2&lt;br&gt;&lt;br&gt;
Framework versions: gunicorn 20.1.0 + uvicorn 0.19.0, socketify alpha, gunicorn 20.1.0 + falcon 3.1.0, robyn 0.18.3&lt;br&gt;&lt;br&gt;
WebSocket tested with &lt;a href="https://bun.sh" rel="noopener noreferrer"&gt;Bun.sh&lt;/a&gt; bench chat-client check the source code in &lt;a href="https://github.com/cirospaciari/socketify.py/tree/main/bench" rel="noopener noreferrer"&gt;this link&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Machine OS: Debian GNU/Linux bookworm/sid x86_64 Kernel: 6.0.0-2-amd64 CPU: Intel i7-7700HQ (8) @ 3.800GHz Memory: 32066MiB &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Socketify.py got almost 900k messages/s with PyPy3 and 860k with Python3 the same performance as &lt;a href="https://bun.sh" rel="noopener noreferrer"&gt;Bun&lt;/a&gt;,&lt;br&gt;
with Falcon 35k messages/s and with Falcon with PyPy3 56k messages/s, node.js manages 192k.&lt;/p&gt;

&lt;p&gt;Bun is REALLY fast! But why the performance of Bun is almost identicall to socketify.py? The answer is that it also uses uWebSockets as base, actually the same code of the PR i made to the C API is been used in Bun with some tweaks, and it endup with almost the same performance that &lt;a href="https://github.com/cirospaciari/socketify.py" rel="noopener noreferrer"&gt;socketify.py&lt;/a&gt;, showing that both have some DNA in common.&lt;/p&gt;

&lt;p&gt;Follow &lt;a href="https://twitter.com/cirospaciari" rel="noopener noreferrer"&gt;@cirospaciari&lt;/a&gt; on twitter for more updates about &lt;a href="https://github.com/cirospaciari/socketify.py" rel="noopener noreferrer"&gt;socketify.py&lt;/a&gt; and if you have some time check out the github &lt;a href="https://github.com/cirospaciari/socketify.py" rel="noopener noreferrer"&gt;https://github.com/cirospaciari/socketify.py&lt;/a&gt; this project can be even better with some community love ;)&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>python</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Socketify.py - Maybe the fastest web framework for Python and PyPy</title>
      <dc:creator>Ciro Spaciari</dc:creator>
      <pubDate>Tue, 08 Nov 2022 21:19:58 +0000</pubDate>
      <link>https://dev.to/cirospaciari/socketifypy-maybe-the-fastest-web-framework-for-python-and-pypy-57ba</link>
      <guid>https://dev.to/cirospaciari/socketifypy-maybe-the-fastest-web-framework-for-python-and-pypy-57ba</guid>
      <description>&lt;p&gt;This year i started a journey to bring a really fast framework for Http, Http2, Http3 and WebSockets to Python and PyPy. &lt;/p&gt;

&lt;h2&gt;
  
  
  The problems with japronto and uvloop
&lt;/h2&gt;

&lt;p&gt;Japronto don't get any github updates since 2020 and don't get any src update since 2018, japronto don't support SSL, WebSockets, &lt;a href="https://www.pypy.org/" rel="noopener noreferrer"&gt;&lt;code&gt;PyPy3&lt;/code&gt;&lt;/a&gt;, Windows or macOS Silicon.&lt;br&gt;
I really needed good support + performance, not only performance.&lt;br&gt;
Almost any solution out there have a really big performance hit when using PyPy3 or are not really fast enougth&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution
&lt;/h2&gt;

&lt;p&gt;We discover a really fast, small, and well maintained C++ Library called &lt;a href="https://github.com/uNetworking/uWebSockets" rel="noopener noreferrer"&gt;uNetworking/uWebSockets&lt;/a&gt;, but no C API available, so we create and adapt the full C API from &lt;a href="https://github.com/uNetworking/uWebSockets" rel="noopener noreferrer"&gt;uNetworking/uWebSockets&lt;/a&gt; and will integrate libuv powered fetch and file IO, this same C API is used by &lt;a href="https://bun.sh/" rel="noopener noreferrer"&gt;Bun&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ⚡ Benchmarking
&lt;/h2&gt;

&lt;p&gt;HTTP requests per second (Linux x64)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fcirospaciari%2Fsocketify.py%2Fmain%2Fmisc%2Fbench-bar-graph.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fcirospaciari%2Fsocketify.py%2Fmain%2Fmisc%2Fbench-bar-graph.svg" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;WebSocket messages per second (Linux x64)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fcirospaciari%2Fsocketify.py%2Fmain%2Fmisc%2Fws-bar-graph.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fcirospaciari%2Fsocketify.py%2Fmain%2Fmisc%2Fws-bar-graph.svg" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It's a really an over simplificated microbenchmark, but shows a big difference between TechEmPower benchmarks using wrk and + 16 pipelining with an lua script, and of course will not hit 1 million req/s on my machine, running tfb tools in my machine socketify.py + PyPy3 hits 770k req/s vs 582k from japronto and in WebSockets almost 900k messages/s with PyPy3 and 860k with Python3 the same performance as &lt;a href="https://bun.sh" rel="noopener noreferrer"&gt;Bun&lt;/a&gt;,&lt;br&gt;
with Falcon 35k messages/s and with Falcon with PyPy3 56k messages/s, node.js manages 192k, and still can get at least 30% or more performance once fully integrated with libuv + asyncio.&lt;/p&gt;

&lt;p&gt;See more benchmark info here: &lt;a href="https://github.com/cirospaciari/socketify.py#zap-benchmarks" rel="noopener noreferrer"&gt;https://github.com/cirospaciari/socketify.py#zap-benchmarks&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  💡 Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;WebSocket with pub/sub support&lt;/li&gt;
&lt;li&gt;Fast and realiable Http/Https&lt;/li&gt;
&lt;li&gt;Support for Windows, Linux and macOS Silicon &amp;amp; x64&lt;/li&gt;
&lt;li&gt;Support for &lt;a href="https://www.pypy.org/" rel="noopener noreferrer"&gt;&lt;code&gt;PyPy3&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://github.com/python/cpython" rel="noopener noreferrer"&gt;&lt;code&gt;CPython&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Dynamic URL Routing with Wildcard &amp;amp; Parameter support&lt;/li&gt;
&lt;li&gt;Sync and Async Function Support&lt;/li&gt;
&lt;li&gt;Really Simple API&lt;/li&gt;
&lt;li&gt;Fast and Encrypted TLS 1.3 quicker than most alternative servers can do even unencrypted, cleartext messaging&lt;/li&gt;
&lt;li&gt;Per-SNI HttpRouter Support&lt;/li&gt;
&lt;li&gt;Proxy Protocol v2&lt;/li&gt;
&lt;li&gt;Shared or Dedicated Compression Support&lt;/li&gt;
&lt;li&gt;Max Backpressure, Max Timeout, Max Payload and Idle Timeout Support&lt;/li&gt;
&lt;li&gt;Automatic Ping / Pong Support&lt;/li&gt;
&lt;li&gt;Per Socket Data&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🔎 Upcoming Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Fetch like API powered by libuv&lt;/li&gt;
&lt;li&gt;Async file IO powered by libuv&lt;/li&gt;
&lt;li&gt;Full asyncio integration with libuv&lt;/li&gt;
&lt;li&gt;Full Http3 support&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://hpyproject.org/" rel="noopener noreferrer"&gt;&lt;code&gt;HPy&lt;/code&gt;&lt;/a&gt; integration to better support &lt;a href="https://github.com/python/cpython" rel="noopener noreferrer"&gt;&lt;code&gt;CPython&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://www.pypy.org/" rel="noopener noreferrer"&gt;&lt;code&gt;PyPy&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://github.com/oracle/graalpython" rel="noopener noreferrer"&gt;&lt;code&gt;GraalPython&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Hot Reloading&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We created and adapt the full C API from &lt;a href="https://github.com/uNetworking/uWebSockets" rel="noopener noreferrer"&gt;uNetworking/uWebSockets&lt;/a&gt; and will integrate libuv powered fetch and file IO, this same C API is used by &lt;a href="https://bun.sh/" rel="noopener noreferrer"&gt;Bun&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  📦 Installation
&lt;/h2&gt;

&lt;p&gt;For macOS x64 &amp;amp; Silicon, Linux x64, Windows&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

pip &lt;span class="nb"&gt;install &lt;/span&gt;git+https://github.com/cirospaciari/socketify.py.git
&lt;span class="c"&gt;#or specify PyPy3&lt;/span&gt;
pypy3 &lt;span class="nt"&gt;-m&lt;/span&gt; pip &lt;span class="nb"&gt;install &lt;/span&gt;git+https://github.com/cirospaciari/socketify.py.git
&lt;span class="c"&gt;#or in editable mode&lt;/span&gt;
pypy3 &lt;span class="nt"&gt;-m&lt;/span&gt; pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; git+https://github.com/cirospaciari/socketify.py.git@main#egg&lt;span class="o"&gt;=&lt;/span&gt;socketify


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  🤔 Usage
&lt;/h2&gt;

&lt;p&gt;Hello world app&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;socketify&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;App&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello World socketify from Python!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Listening on port http://localhost:%d now&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;SSL version sample&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 python
from socketify import App, AppOptions

app = App(AppOptions(key_file_name="./misc/key.pem", cert_file_name="./misc/cert.pem", passphrase="1234"))
app.get("/", lambda res, req: res.end("Hello World socketify from Python!"))
app.listen(3000, lambda config: print("Listening on port http://localhost:%d now\n" % config.port))
app.run()


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;WebSockets&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;socketify&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;App&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;AppOptions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;OpCode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;CompressOptions&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;ws_open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;A WebSocket got connected!&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello World!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;OpCode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TEXT&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;ws_message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;opcode&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;#Ok is false if backpressure was built up, wait for drain
&lt;/span&gt;    &lt;span class="n"&gt;ok&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;opcode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;    
&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/*&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;compression&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;CompressOptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SHARED_COMPRESSOR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;max_payload_length&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;idle_timeout&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;open&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ws_open&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ws_message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;drain&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;WebSocket backpressure: %i&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_buffered_amount&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;close&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;WebSocket closed&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Nothing to see here!&lt;/span&gt;&lt;span class="sh"&gt;'"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Listening on port http://localhost:%d now&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;And &lt;a href="https://github.com/cirospaciari/socketify.py/tree/main/examples" rel="noopener noreferrer"&gt;click here&lt;/a&gt; more than 20 examples &lt;/p&gt;

&lt;h2&gt;
  
  
  💼 Commercially supported
&lt;/h2&gt;

&lt;p&gt;Socketify is an active project and will be maintained over time with security updates and new features and will be commercial support available&lt;/p&gt;

&lt;p&gt;Check our github page: &lt;a href="https://github.com/cirospaciari/socketify.py" rel="noopener noreferrer"&gt;https://github.com/cirospaciari/socketify.py&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>showdev</category>
      <category>webdev</category>
      <category>pubsub</category>
    </item>
    <item>
      <title>Faster and simple Http and WebSocket Server for Ruby</title>
      <dc:creator>Ciro Spaciari</dc:creator>
      <pubDate>Tue, 18 Jan 2022 18:04:06 +0000</pubDate>
      <link>https://dev.to/cirospaciari/faster-and-simple-http-and-websocket-server-for-ruby-cd1</link>
      <guid>https://dev.to/cirospaciari/faster-and-simple-http-and-websocket-server-for-ruby-cd1</guid>
      <description>&lt;h2&gt;
  
  
  uWebSockets for Ruby - uWebSockets.rb
&lt;/h2&gt;

&lt;p&gt;I started to implement uWebSockets C API wrapper and a Ruby version a few days ago.&lt;br&gt;
I got some good performance results (about 5x agoo in using techempower benchmarks for plaintext), for now i just implemented http/https apis but i will implement websockets this week and write some documentation (only linux support, mac should works fine as well, but i will add windows and mac tests and support too)&lt;/p&gt;

&lt;p&gt;I will be glad for some feedback and help for testing in the near future &lt;a href="https://github.com/cirospaciari/uWebSockets.rb"&gt;https://github.com/cirospaciari/uWebSockets.rb&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Overly simple hello world app
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s2"&gt;"uws"&lt;/span&gt;

&lt;span class="no"&gt;UWS&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;App&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;lambda&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Hello World uWS from Ruby!"&lt;/span&gt;&lt;span class="p"&gt;)})&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8082&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;lambda&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Listening on port &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;port&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Gemfile
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gem 'uws', git: 'https://github.com/cirospaciari/uWebSockets.rb.git', branch: 'main', submodules: true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Run
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bundle &lt;span class="nb"&gt;exec &lt;/span&gt;ruby ./hello_world.rb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  SSL version sample
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s2"&gt;"uws"&lt;/span&gt;

&lt;span class="no"&gt;UWS&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;SSLApp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="ss"&gt;key_file_name: &lt;/span&gt;&lt;span class="s2"&gt;"./misc/key.pem"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="ss"&gt;cert_file_name: &lt;/span&gt;&lt;span class="s2"&gt;"./misc/cert.pem"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="ss"&gt;passphrase: &lt;/span&gt;&lt;span class="s2"&gt;"1234"&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;lambda&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Hello World uWS from Ruby!"&lt;/span&gt;&lt;span class="p"&gt;)})&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8082&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;lambda&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Listening on port &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;port&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>ruby</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
