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


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>What do these layers of abstraction do?</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="280143" 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/elixir-vs-python-performance-benchmarking/54260/12">Post #11</a>
	                </div>
	            </div>
              <div id="likers-container-280143" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="280143"
                     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 #11"></div>
  </section>
</div>
    <div class="postbit" id="280184" data-post-id="280184">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>raw has no effect on read. It is only for file handles. In this case, still goes to a server that serializes both reads and writes. I will try to start a discussion on why that’s the case. It feels unnatural to try to address a race condition that is natural to the file system itself and will happen with other programs running in the same machine anyway.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="280184" 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/elixir-vs-python-performance-benchmarking/54260/13">Post #12</a>
	                </div>
	            </div>
              <div id="likers-container-280184" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="280184"
                     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 #12"></div>
  </section>
</div>
    <div class="postbit" id="280205" data-post-id="280205">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>It looks like the overhead is spinning up a new process:</p>
<p><strong>raw</strong><br>
Allows faster access to a file, as no Erlang process is needed to handle the file. However, a file opened in this way has the following limitations:</p>
<ul>
<li>The functions in the io module cannot be used, as they can only talk to an Erlang process. Instead, use functions <a href="https://www.erlang.org/docs/19/man/file.html#read-2" rel="nofollow">read/2</a>,<a href="https://www.erlang.org/docs/19/man/file.html#read_line-1" rel="nofollow">read_line/1</a>, and <a href="https://www.erlang.org/docs/19/man/file.html#write-2" rel="nofollow">write/2</a>.</li>
<li>Especially if read_line/1 is to be used on a raw file, it is recommended to combine this option with option {read_ahead, Size} as line-oriented I/O is inefficient without buffering.</li>
<li>Only the Erlang process that opened the file can use it.</li>
<li>A remote Erlang file server cannot be used. The computer on which the Erlang node is running must have access to the file system (directly or through NFS).</li>
</ul>
<p>When the mode isn’t raw, the iodevice is a pid.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="280205" 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/elixir-vs-python-performance-benchmarking/54260/14">Post #13</a>
	                </div>
	            </div>
              <div id="likers-container-280205" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="280205"
                     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 #13"></div>
  </section>
</div>
    <div class="postbit" id="280231" data-post-id="280231">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="fireproofsocks" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/fireproofsocks/120/7669_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  fireproofsocks
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Thank you all for the continued input.  This is interesting!  I formalized my repo to use Benchee so I could continue trying out some variants.  Here are the results (so far):</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">Name                        ips        average  deviation         median         99th %
python                     2.27         0.44 s    ±22.35%         0.45 s         0.64 s
:prim_file async           1.38         0.72 s    ±22.75%         0.63 s         1.04 s
Concurrent                 0.63         1.59 s     ±8.90%         1.59 s         1.78 s
Split file                 0.40         2.51 s    ±22.56%         2.35 s         3.30 s
Task.async_stream          0.32         3.16 s    ±21.99%         3.19 s         3.95 s
:prim_file                 0.31         3.26 s    ±41.38%         2.82 s         5.19 s
File                       0.31         3.27 s    ±24.74%         3.48 s         4.00 s
Jsonrs                     0.28         3.54 s    ±20.90%         3.56 s         4.27 s

Comparison:
python                     2.27
:prim_file async           1.38 - 1.64x slower +0.28 s
Concurrent                 0.63 - 3.59x slower +1.14 s
Split file                 0.40 - 5.68x slower +2.07 s
Task.async_stream          0.32 - 7.16x slower +2.72 s
:prim_file                 0.31 - 7.37x slower +2.81 s
File                       0.31 - 7.41x slower +2.83 s
Jsonrs                     0.28 - 8.02x slower +3.10 s
</code></pre>
<p>In short, Python is still the fastest.  The fastest Elixir solution (so far) is the one that uses <code>Task.async_stream</code> and the <code>:prim_file</code>:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">    index_file
    |&gt; File.stream!()
    |&gt; Task.async_stream(fn line -&gt;
      path = String.trim(line)
      {:ok, contents} = :prim_file.read_file(path)
      {:ok, %{"paths" =&gt; txt_paths}} = Jason.decode(contents)

      Enum.each(txt_paths, fn p -&gt;
        :prim_file.read_file_info(p)
      end)
    end)
    |&gt; Stream.run()
</code></pre>
<p>I tried variants that used EITHER <code>Task.async_stream</code> OR <code>:prim_file</code>, but they didn’t perform as well.  Loading the file into memory instead of streaming it also didn’t perform as well.  I haven’t been able to <a href="https://forum.elixirforum.com/t/running-failed-to-find-library-init-function/54284/3" rel="nofollow">get jiffy working</a>, so I gave <code>jsonrs</code> a try, but unfortunately, it performed the worst of these (!!).</p>
<p>What is challenging here is that the solutions have very different performance characteristics.  In other words, it’s easy to fall into a hole here, so I’m hoping to identify patterns to avoid.  I should probably try coming up with more simplified use-cases, because this one touches on a lot of things: streaming, checking the file system, and JSON decoding.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="280231" 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/elixir-vs-python-performance-benchmarking/54260/15">Post #14</a>
	                </div>
	            </div>
              <div id="likers-container-280231" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="280231"
                     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 #14"></div>
  </section>
</div>
    <div class="postbit" id="280244" data-post-id="280244">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I’m interested in Elixir solutions that are not only faster, but also as clean and naive as the Python solution (from above). It doesn’t use any special Python libraries. It doesn’t obviously drop into C code (like the best Elixir version uses Erlang functions and types. ?)</p>
<p>This is very clean code (literally, in Bob Martin’s Clean Coding style.)</p>
<pre data-code-wrap="python"><code class="lang-python">from os.path import exists
import json
from time import time

index_file = "tmp/files/index.txt"

existing = []

def vet_files():
    with open(index_file, 'r') as myfile:
        for line in myfile:
            open_json_file(line.rstrip())
            # dict_obj = json.loads(person_data)


def open_json_file(json_file):
    with open(json_file, 'r') as myfile:
        for line in myfile:
            data = json.loads(line)
            files_exist(data['paths'])

def files_exist(paths):
    for p in paths:
        existing.append(exists(p))

if __name__ == "__main__":
    start_time = int(time() * 1000)
    vet_files()
    end_time = int(time() * 1000)
    print(f'Duration: {end_time - start_time} ms')
    print(all(existing))
</code></pre> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="280244" 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/elixir-vs-python-performance-benchmarking/54260/16">Post #15</a>
	                </div>
	            </div>
              <div id="likers-container-280244" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="280244"
                     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 #15"></div>
  </section>
</div>
    <div class="postbit" id="280245" data-post-id="280245">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I’d be curious how it would do against raw file</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">index_file
|&gt; :file.open([:raw, :read_ahead])
|&gt; :file.read(1_000_000)
|&gt; ...
</code></pre> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="280245" 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/elixir-vs-python-performance-benchmarking/54260/17">Post #16</a>
	                </div>
	            </div>
              <div id="likers-container-280245" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="280245"
                     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 #16"></div>
  </section>
</div>
    <div class="postbit" id="280253" data-post-id="280253">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="dogweather" data-post="16" data-topic="54260">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/dogweather/48/1906_2.png" class="avatar"> dogweather:</div>
<blockquote>
<p>It doesn’t obviously drop into C code</p>
</blockquote>
</aside>
<p>Is that so? Only because you are using a python function to call the library function is doesn’t mean there isn’t a native C implementation under the hood.<br>
What about the abomination the python is at this moment in time? Nobody can’t understand at this point if the language is interpreted or compiled anymore because of how many optimizations are in place to make it fast.</p>
<blockquote>
<p>like the best Elixir version uses Erlang functions and types</p>
</blockquote>
<p>If you are just getting in elixir you might be thinking that using an erlang library is strange and it is the same as calling C code, however this is definitely not true as elixir gets compiled to erlang, so no overhead is involved here.<br>
Moreover if you have access to 2 separate languages and ecosystems without any setup and overhead why not use whats best from both worlds?</p>
<blockquote>
<p>This is very clean code (literally, in Bob Martin’s Clean Coding style.)</p>
</blockquote>
<p>Is that so? What about concurrency? The elixir solution above is either using tasks or streams and you are showing a solution that can run only in a blocking manner.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="280253" 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/elixir-vs-python-performance-benchmarking/54260/18">Post #17</a>
	                </div>
	            </div>
              <div id="likers-container-280253" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="280253"
                     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 #17"></div>
  </section>
</div>
    <div class="postbit" id="280283" data-post-id="280283">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="fireproofsocks" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/fireproofsocks/120/7669_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  fireproofsocks
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Just for the record, that was my Python code and I made no attempts to optimize – I just poked at it for a few minutes until it worked. <img src="https://forum.elixirforum.com/images/emoji/apple/grimacing.png?v=15" title=":grimacing:" class="emoji" alt=":grimacing:" 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="280283" 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/elixir-vs-python-performance-benchmarking/54260/19">Post #18</a>
	                </div>
	            </div>
              <div id="likers-container-280283" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="280283"
                     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 #18"></div>
  </section>
</div>
    <div class="postbit" id="280291" data-post-id="280291">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="fireproofsocks" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/fireproofsocks/120/7669_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  fireproofsocks
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Reading chunks of data (instead of lines) is awkward in this case because each <em>line</em> contains a value.  When processing chunks, you have to manually split on newlines and reassemble any values that got split.  (At least, I need more coffee before I can come up with a solution to that).  Also <code>:file.read/2</code> returns charlists, and I’m not sure what kind of overhead it would be introducing to convert those back into strings.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="280291" 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/elixir-vs-python-performance-benchmarking/54260/20">Post #19</a>
	                </div>
	            </div>
              <div id="likers-container-280291" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="280291"
                     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 #19"></div>
  </section>
</div>
    <div class="postbit" id="280292" data-post-id="280292">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Ok so :file.read_line and go through all the lines?</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="280292" 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/elixir-vs-python-performance-benchmarking/54260/21">Post #20</a>
	                </div>
	            </div>
              <div id="likers-container-280292" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="280292"
                     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 #20"></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/54260/load_more?page=3">Load more posts (3 remaining)</a>
</div></template></turbo-stream>