<turbo-stream action="append" target="posts_list"><template>    <div class="postbit" id="35212" data-post-id="35212">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="sasajuric" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/sasajuric/120/991_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  sasajuric
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Author of Elixir In Action</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group quote-post-not-found" data-username="brightball" data-post="32" data-topic="5036" data-full="true">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/brightball/48/17192_2.png" class="avatar"><a href="https://forum.elixirforum.com/t/techempower-benchmarks-round-14/5036/32" rel="nofollow">TechEmpower Benchmarks Round 14</a></div>
<blockquote>
<p>We’d need somebody with more expertise than me to speak into the channels implementation and why it’s built the way it is. <a class="mention" href="/u/chrismccord" rel="nofollow">@chrismccord</a> want to chime in?</p>
</blockquote>
</aside>
<p>The process per channel and a separate process per socket ensure that:</p>
<ul>
<li>A crash in a channel doesn’t take down the whole connection and other conversations.</li>
<li>A busy channel doesn’t block the communication on other channels.</li>
</ul>
<p>As usual this comes with a trade-off, in this case in terms of both memory, and a slight perf cost (because of extra message hopping and scheduler overhead).</p>
<p>Currently, if you don’t like that trade-off, you can always fall back to plain cowboy. I argued that Phoenix could be slightly modified to make it possible to opt-out from the default approach and have just one process per socket. Some work has been done by José and me on this, but we kind of stashed it a year ago. José mentioned he’ll get back to it at some point.</p>
<p>Regardless, I believe that the current Phoenix approach is a good default, because it values fault-tolerance and overall system responsiveness, which is a good bias for many cases.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="35212" data-batch-url="/posts/batch_likers">
                        6
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/techempower-benchmarks/171/43">Post #42</a>
	                </div>
	            </div>
              <div id="likers-container-35212" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="35212"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #42"></div>
  </section>
</div>
    <div class="postbit" id="35213" data-post-id="35213">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="outlog" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  outlog
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I actually looked at this when we fixed up things for the other benchmarks, but gave up on it. Honestly the config for the DB is insane.<br>
In general the phoenix code is not optimized, and in my eyes it doesn’t look very functional or elixir-ish.</p>
<p>Three significant things slows down phoenix:</p>
<ol>
<li>Json encoding - obviously slower in elixir than in c.</li>
<li>DB test - poolsize 20 and the benchmark setup which is not normal/unrealistic (PG has max_connections 2000 and the the test is done at low (keepalive) concurrency of 256 - thus not requiring a DB pool at all - and indeed some of the frameworks are not using one )</li>
<li>Minor optimizations, making it faster and more elixir-ish - (pattern match params, batch update etc.)</li>
</ol>
<p>notes on the different functions from back then:</p>
<p><strong>1. json</strong><br>
<code>def _json</code> (json bench) and <code>def db</code> (db+json bench)<br>
use jiffy to encode.</p>
<pre><code>Benchee.run(%{time: 50, parallel: 8}, %{
  "poison"  =&gt; fn -&gt; Poison.encode!(%{message: "Hello, world!"}) end,
  "jiffy" =&gt; fn -&gt; :jiffy.encode(%{message: "Hello, world!"}) end,
  "jiffyerl" =&gt; fn -&gt; :jiffy.encode({[{&lt;&lt;"message"&gt;&gt;, &lt;&lt;"Hello, world!"&gt;&gt;}]}) end
})

Comparison: 
jiffyerl      343.87 K
jiffy         303.72 K - 1.13x slower
poison        188.26 K - 1.83x slower
</code></pre>
<p><strong>2. def queries and def updates params to int</strong><br>
both <code>def queries</code> and <code>def updates</code> currently does a less than optimal param parsing. by doing the classic <code>(conn, %{"queries" =&gt; queries_param})</code> the matching all the way to integer is ~50% faster(but its really fast anyhow)</p>
<pre><code>benchee:
    new        4.09 M
    old        2.74 M - 1.49x slower
</code></pre>
<p>this does require some rework to handle missing params cases. I propose this which is hopefully also much more idiomatic:</p>
<pre><code>  #pattern match queries and value queries_param
  def queries(conn, %{"queries" =&gt; queries_param}) do
    q = try do
      String.to_integer(queries_param)
    rescue
      ArgumentError -&gt; :not_integer
    end
    queries_rules(conn, q)
  end

  #queries didn't pattern match above aka are missing
  def queries(conn, _unused_params), do: queries_rules(conn, :missing)

  defp queries_rules(conn, queries_param) do
    case queries_param do
      :missing       -&gt; queries_response(conn, 1,   :missing)       # If the parameter is missing,
      :not_integer   -&gt; queries_response(conn, 1,   :not_integer)   # is not an integer, 
      x when x &lt; 1   -&gt; queries_response(conn, 1,   :less_than_one) # or is an integer less than 1, the value should be interpreted as 1; 
      x when x &gt; 500 -&gt; queries_response(conn, 500, :more_than_500) # if greater than 500, the value should be interpreted as 500.
      x              -&gt; queries_response(conn, x,   :ok)            # The queries parameter must be bounded to between 1 and 500. 
    end
  end 

  defp queries_response(conn, parsed_param, _status ) do
    conn
    |&gt; put_resp_content_type("application/json")
    |&gt; send_resp(200, Poison.encode!(Enum.map(1..parsed_param, fn _ -&gt; Repo.get(World, :rand.uniform(10000)) end)))
  end
</code></pre>
<p>I would have liked to do Integer.parse- but this is much slower than the try/rescue unfortunately - (elixir might be in need of a String.to_integer() equivalent that returns integer or :error and not ArgumentError - or a :ok/:error tuple):</p>
<pre><code>#slower than try/rescue :/
case Integer.parse(queries_param) do
  # {int, remainder} int is only perfectly good if remainder is empty ""
  {queries_int, ""} -&gt; queries_rules(conn, queries_int)
  _ -&gt;                 queries_rules(conn, :not_integer)
end
</code></pre>
<p>the same pattern matching params to int refactor applies to <code>def updates</code></p>
<p><strong>3. def updates</strong><br>
this is around where I gave up, as I realized the realities (or lack thereof!) of the DB benchmarks.<br>
use the same param matching as above.<br>
rules does NOT allow batch querying the records(sic!). In my limited test asyncing the querying was not fruitful.(yes I did test different DB pool sizes, and asyncing levels ymmv)<br>
rules does ALLOW batch updating.<br>
this is what I ended up with, which I make no claims about being pretty nor fully optimized:</p>
<pre><code>ids = 1..q 
|&gt; Stream.map(fn _ -&gt; :random.uniform(10_000) end)

ws = ids 
|&gt; Enum.map( &amp;Repo.one(
  from p in HelloPhoenix.Post, 
  where: p.id == ^&amp;1,
  select: map(p, [:id, :randomnumber]) ) )
|&gt; Enum.map( &amp;Map.put( &amp;1, :randomnumber, to_string(:random.uniform(10_000)) ))

Repo.insert_all(HelloPhoenix.Post, Enum.uniq_by(ws,fn x -&gt; x.id end ), on_conflict: :replace_all, conflict_target: :id)
</code></pre>
<p>and then return the <code>ws</code> json encoded. This utilizes <code>upsert</code> and does the update in a batch. <code>Enum.uniq_by(ws,fn x -&gt; x.id end )</code> is there to handle edge scenario, where <code>:random.uniform(10_000)</code> has returned the same number and there are duplicates in the ids array, obviously postgres barks at a batch update holding opposing truths - I hope other DBs does the same. And I’m at a loss how this is the spec for the benchmark, and was the tipping point for me.</p>
<p>In general I would say we go for making it pretty and nice code that showcases the readability/productivity of elixir/phoenix, I’m sure phoenix will perform fine (as it already does).</p>
<p>Changing the DB pool size to 2000 is just too much, and I doubt it’s even faster - especially in the real world.</p>
<p>I too would like to see multi-hour benchmarks, and get away from keepalive, no GC, do nothing really fast for 15 secs tests.<br>
I would also add (hot/rollover) code deploys, various peak times, slow clients, endpoint with errors etc. to the multihour tests.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="35213" data-batch-url="/posts/batch_likers">
                        4
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/techempower-benchmarks/171/44">Post #43</a>
	                </div>
	            </div>
              <div id="likers-container-35213" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="35213"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #43"></div>
  </section>
</div>
    <div class="postbit" id="35215" data-post-id="35215">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="brightball" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/brightball/120/17192_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  brightball
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group quote-post-not-found" data-username="outlog" data-post="35" data-topic="5036">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/o/c0e974/48.png" class="avatar"><a href="https://forum.elixirforum.com/t/techempower-benchmarks-round-14/5036/35" rel="nofollow">TechEmpower Benchmarks Round 14</a></div>
<blockquote>
<p>Changing the DB pool size to 2000 is just too much, and I doubt it’s even faster - especially in the real world.</p>
</blockquote>
</aside>
<p>Just looking at the 20 query or update per request part of the test, if we broken each query/update into it’s own process we’d be looking at 5,120 possible connections at the same time on the 256 concurrency. Can the pool go higher?</p>
<p>Just to satisfy my own curiosity I looked at the Go code for these benchmarks expecting to see use of goroutines…but they don’t seem to be using them either. Is that considered “batching”?</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="35215" data-batch-url="/posts/batch_likers">
                        2
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/techempower-benchmarks/171/45">Post #44</a>
	                </div>
	            </div>
              <div id="likers-container-35215" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="35215"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #44"></div>
  </section>
</div>
    <div class="postbit" id="35218" data-post-id="35218">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="sasajuric" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/sasajuric/120/991_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  sasajuric
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Author of Elixir In Action</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group quote-post-not-found" data-username="brightball" data-post="36" data-topic="5036">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/brightball/48/17192_2.png" class="avatar"><a href="https://forum.elixirforum.com/t/techempower-benchmarks-round-14/5036/36" rel="nofollow">TechEmpower Benchmarks Round 14</a></div>
<blockquote>
<p>Just looking at the 20 query or update per request part of the test, if we broken each query/update into it’s own process we’d be looking at 5,120 possible connections at the same time on the 256 concurrency. Can the pool go higher?</p>
</blockquote>
</aside>
<p>This is an interesting example of how these benches can diverge from the real life. Issuing concurrent queries is fine if you don’t expect many requests at the same time. However, if that can happen, then this approach might cause some bad effects. For example, if you and I issue our requests at the same time, and I want to update 5k elements, while you want to update just 1, you might end up being DoS-ed by my request if all of my 5k updates enter the pool queue before your single update.</p>
<p>A proper way to optimize this IMO is to reduce the number of db roundtrips, which is unfortunately not permitted by the rules.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="35218" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/techempower-benchmarks/171/46">Post #45</a>
	                </div>
	            </div>
              <div id="likers-container-35218" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="35218"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #45"></div>
  </section>
</div>
    <div class="postbit" id="35219" data-post-id="35219">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="brightball" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/brightball/120/17192_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  brightball
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>In one of the Go examples I was looking at, it had a comment that I’d be interested to dig into a little bit more (from the fastest Go benchmark):</p>
<p><a href="https://github.com/TechEmpower/FrameworkBenchmarks/blob/master/frameworks/Go/fasthttp/src/server-postgresql/server.go#L112-L113" class="onebox" target="_blank" rel="noopener nofollow ugc">https://github.com/TechEmpower/FrameworkBenchmarks/blob/master/frameworks/Go/fasthttp/src/server-postgresql/server.go#L112-L113</a></p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="35219" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/techempower-benchmarks/171/47">Post #46</a>
	                </div>
	            </div>
              <div id="likers-container-35219" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="35219"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #46"></div>
  </section>
</div>
    <div class="postbit" id="35223" data-post-id="35223">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="chrismccord" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/chrismccord/120/24233_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  chrismccord
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Creator of Phoenix</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>To be clear, uWebSockets is an entirely different comparison. Phoenix Channels is a protocol built on top of websockets with distributed pubsub and communication multiplexing. uWebSockets is a raw websocket library. A more apt comparison would be cowboy ws</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="35223" data-batch-url="/posts/batch_likers">
                        4
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/techempower-benchmarks/171/48">Post #47</a>
	                </div>
	            </div>
              <div id="likers-container-35223" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="35223"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #47"></div>
  </section>
</div>
    <div class="postbit" id="35224" data-post-id="35224">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="chrismccord" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/chrismccord/120/24233_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  chrismccord
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Creator of Phoenix</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Just a note from the other numerous times TechMeme comes up, last year (or before) they added Phoenix in a preview, but it was a very poor implementation. They were testing JSON benchmarks through the :browser pipeline, complete with crsf token generation. They had a dev DB pool size of 10, where other frameworks were given of pool size of 100. And they also had heavy IO logging, where other frameworks did no logging. We sent a PR to address these issues, and I was hoping to see true results in later runs, but recent runs have show high error rates and we don’t know the details why nor have they done a great job with any of the recent code as shown in this thread. tldr; these results are not representative of the framework and the core-team’s time is better spent elsewhere. For those interested, please feel free to send PRs to improve their code, but it’s not something I lose sleep over <img src="https://forum.elixirforum.com/images/emoji/apple/smiley.png?v=15" title=":smiley:" class="emoji" alt=":smiley:" loading="lazy" width="20" height="20"></p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="35224" data-batch-url="/posts/batch_likers">
                        15
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/techempower-benchmarks/171/49">Post #48</a>
	                </div>
	            </div>
              <div id="likers-container-35224" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="35224"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #48"></div>
  </section>
</div>
    <div class="postbit" id="35226" data-post-id="35226">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="outlog" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  outlog
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>any real world high load scenario would put the db pool under constraint within seconds - and in fact require a db pool.</p>
<p>any real world scenario would not make these kind of mass DB sequential queries - it’s an <code>absolute anti-pattern</code> for a <code>relational DB</code> - if one had a busy endpoint where this behaviour was necessary you would change the data structure and have an educational talk with the person who implemented it (and the person who approved it).</p>
<p>this benchmark is unreal - and it markets itself as real-world: <code>"..provides representative performance measures.."</code> - other benchmarks usually have the courtesy of not pretending to be real - but testing only overhead/throughput (thus using keepalive to accentuate differences) etc.</p>
<p>this unrealness/weirdness doesn’t particularly hurt elixir/phoenix it just makes it moot to optimize, thus I suggest going for pretty and nice proper code and style - and then not spend more time on it.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="35226" data-batch-url="/posts/batch_likers">
                        3
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/techempower-benchmarks/171/50">Post #49</a>
	                </div>
	            </div>
              <div id="likers-container-35226" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="35226"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #49"></div>
  </section>
</div>
    <div class="postbit" id="35228" data-post-id="35228">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="idi527" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  idi527
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I thought is was already clear from the name. I’m just impressed with that library, that’s all. I was planning to run the uwebsockets author’s ws benchmark against cowboy’s ws, but can’t find the time.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="35228" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/techempower-benchmarks/171/51">Post #50</a>
	                </div>
	            </div>
              <div id="likers-container-35228" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="35228"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #50"></div>
  </section>
</div>
    <div class="postbit" id="35238" data-post-id="35238">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="anthonyb" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  anthonyb
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<blockquote>
<p>What I’m saying is that I can’t conclude anything reliably from that benchmark. That’s my main point I’m arguing in this thread.</p>
</blockquote>
<p>No measurements are going to be perfectly reliable. The question is whether there is any useful information in the data. It sounds like you believe the answer is no and that if these same tech stacks were used in real-world scenarios, the relevant performance metrics would show little correlation with the TE benchmark results (i.e., you would expect to see essentially a random permutation of the rank ordering shown on the site). Ultimately, I suppose that’s an empirical question.</p>
<blockquote>
<p>Once I established that, I didn’t care much about few microseconds here/there.</p>
</blockquote>
<p>Sure, but I don’t think the argument for measuring performance is typically for the sake of saving a few microseconds (assuming that’s a small percentage savings for the task at hand). The argument I hear in favor of Phoenix is that it doesn’t require the typical tradeoff between productivity/developer happiness and speed/reliability. So, the claim is being made that its technical performance (both reliability and speed) is meaningfully superior to that of other options, and that technical performance does indeed matter. It’s hard to make such claims convincingly without doing some measurement (and comparison).</p>
<blockquote>
<p>Once you have the tech which can handle your load, other things start to matter, such as the support for fault-tolerance, stable latency, and troubleshooting a running system. Erlang/Elixir excel at this, and that matters, because it improves the uptime and availability, and makes the life of developers much easier.</p>
</blockquote>
<p>Yes, but how do you know if Elixir exhibits better fault-tolerance, stable latency, and uptime compared with other options? These are technical performance attributes as well. Presumably that would require some measurements of different systems under similar circumstances.</p>
<blockquote>
<blockquote>
<p>If you want, you could look at any given framework in a set of benchmarks to determine the capacity of that particular framework</p>
</blockquote>
</blockquote>
<blockquote>
<p>That might be true, but one big problem I have with TE…</p>
</blockquote>
<p>Yes, there are plenty of criticisms of TE, but I wasn’t referring to TE. I was addressing your more general claim that individual measurements in isolation are useful, whereas measurements of multiple platforms under similar circumstances are not. Given that the latter can be reduced to the former, this doesn’t make sense.</p>
<blockquote>
<p>You could get bigger savings by choosing a technology which allows developers to efficiently and confidently manage that kind of load, and to keep the system stable and running as much as possible, and to reduce the load on the support team. Again, raw performance is just a part of the story.</p>
</blockquote>
<p>Just substitute “stability” for “raw performance” in all of your arguments against comparative measurements, and it would seem we also have no way of determining that Elixir/Phoenix is generally any more stable or reliable than any other option. Presumably for each new project, we must build a realistic proof of concept in Elixir and several other stacks to see how each perform in that particular unique system (given, of course, that no two systems are ever sufficiently alike to generalize from any previous data or observations).</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="35238" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/techempower-benchmarks/171/52">Post #51</a>
	                </div>
	            </div>
              <div id="likers-container-35238" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="35238"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #51"></div>
  </section>
</div>
</template></turbo-stream><turbo-stream action="replace" target="load-more-container"><template><div id="load-more-container" class="load-more-container">
    <a class="load-more-button" data-turbo-stream="true" href="/topics/171/load_more?page=6">Load more posts (79 remaining)</a>
</div></template></turbo-stream>