Skip to content

Commit 37d92ba

Browse files
committed
site docs
1 parent ab6e4d6 commit 37d92ba

11 files changed

+106
-120
lines changed

docs/example-concurrent-processing.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -181,9 +181,9 @@ <h1 id="concurrent-processes"><a class="header" href="#concurrent-processes">Con
181181
most storage. <code>proc</code> makes it possible to run <code>ls --summarize</code> with parallelism
182182
matching the number of CPU cores available (or whatever concurrency you
183183
specify). The specific methods that support concurrent operations are
184-
<a href="https://deno.land/x/proc@0.21.6/mod3.ts?s=Enumerable&amp;p=prototype.concurrentMap">.concurrentMap()</a>
184+
<a href="https://deno.land/x/proc@0.21.7/mod3.ts?s=Enumerable&amp;p=prototype.concurrentMap">.concurrentMap()</a>
185185
and
186-
<a href="https://deno.land/x/proc@0.21.6/mod3.ts?s=Enumerable&amp;p=prototype.concurrentUnorderedMap">.concurrentUnorderedMap()</a>.</p>
186+
<a href="https://deno.land/x/proc@0.21.7/mod3.ts?s=Enumerable&amp;p=prototype.concurrentUnorderedMap">.concurrentUnorderedMap()</a>.</p>
187187
<p>To list the <code>s3</code> buckets in your AWS account from terminal:</p>
188188
<pre><code class="language-sh">aws s3 ls
189189
</code></pre>
@@ -223,7 +223,7 @@ <h1 id="concurrent-processes"><a class="header" href="#concurrent-processes">Con
223223
)
224224
</code></pre>
225225
<p>Use <code>nice</code> because <em>this will eat your server otherwise.</em> The method
226-
<a href="https://deno.land/x/proc@0.21.6/mod3.ts?s=Enumerable&amp;p=prototype.concurrentUnorderedMap">.concurrentUnorderedMap()</a>
226+
<a href="https://deno.land/x/proc@0.21.7/mod3.ts?s=Enumerable&amp;p=prototype.concurrentUnorderedMap">.concurrentUnorderedMap()</a>
227227
will, by default, run one process for each CPU available concurrently until all
228228
work is done.</p>
229229
<p>The result will look something like this:</p>

docs/index.html

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -173,21 +173,21 @@ <h1 class="menu-title">proc</h1>
173173

174174
<div id="content" class="content">
175175
<main>
176-
<h1 id="proc-0216"><a class="header" href="#proc-0216"><code>proc 0.21.6</code></a></h1>
176+
<h1 id="proc-0217"><a class="header" href="#proc-0217"><code>proc 0.21.7</code></a></h1>
177177
<p><code>proc</code> let's you use child processes with
178178
<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/AsyncIterator"><code>AsyncIterable</code></a>
179179
instead of the streams API, and it includes a library of higher-order functions
180180
for <code>AsyncIterator</code> via
181-
<a href="https://deno.land/x/proc@0.21.6/mod.ts?s=Enumerable"><code>Enumerable</code></a> that
181+
<a href="https://deno.land/x/proc@0.21.7/mod.ts?s=Enumerable"><code>Enumerable</code></a> that
182182
roughly matches what you can do with an array (<code>map</code>, <code>filter</code>, <code>find</code>), but for
183183
asynchronous code.</p>
184184
<p><code>proc</code> simplifies the process of converting a <code>bash</code> script into a Deno
185185
application. The intention is to make writing code that uses lots of IO and
186186
child processes <em>almost</em> as easy as shell scripting, but you also get proper
187187
error handling, type checking, and Deno's security-by-default.</p>
188-
<p><a href="https://deno.land/x/proc@0.21.6/mod.ts">Developer Documentation</a></p>
188+
<p><a href="https://deno.land/x/proc@0.21.7/mod.ts">Developer Documentation</a></p>
189189
<h2 id="usage"><a class="header" href="#usage">Usage</a></h2>
190-
<pre><code class="language-typescript">import { run } from &quot;https://deno.land/x/proc@0.21.6/mod.ts&quot;;
190+
<pre><code class="language-typescript">import { run } from &quot;https://deno.land/x/proc@0.21.7/mod.ts&quot;;
191191
</code></pre>
192192
<h2 id="a-simple-example"><a class="header" href="#a-simple-example">A Simple Example</a></h2>
193193
<p>Run <code>ls -la</code> as a child process. Decode <code>stdout</code> as lines of text. Print to

docs/introduction.html

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -173,21 +173,21 @@ <h1 class="menu-title">proc</h1>
173173

174174
<div id="content" class="content">
175175
<main>
176-
<h1 id="proc-0216"><a class="header" href="#proc-0216"><code>proc 0.21.6</code></a></h1>
176+
<h1 id="proc-0217"><a class="header" href="#proc-0217"><code>proc 0.21.7</code></a></h1>
177177
<p><code>proc</code> let's you use child processes with
178178
<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/AsyncIterator"><code>AsyncIterable</code></a>
179179
instead of the streams API, and it includes a library of higher-order functions
180180
for <code>AsyncIterator</code> via
181-
<a href="https://deno.land/x/proc@0.21.6/mod.ts?s=Enumerable"><code>Enumerable</code></a> that
181+
<a href="https://deno.land/x/proc@0.21.7/mod.ts?s=Enumerable"><code>Enumerable</code></a> that
182182
roughly matches what you can do with an array (<code>map</code>, <code>filter</code>, <code>find</code>), but for
183183
asynchronous code.</p>
184184
<p><code>proc</code> simplifies the process of converting a <code>bash</code> script into a Deno
185185
application. The intention is to make writing code that uses lots of IO and
186186
child processes <em>almost</em> as easy as shell scripting, but you also get proper
187187
error handling, type checking, and Deno's security-by-default.</p>
188-
<p><a href="https://deno.land/x/proc@0.21.6/mod.ts">Developer Documentation</a></p>
188+
<p><a href="https://deno.land/x/proc@0.21.7/mod.ts">Developer Documentation</a></p>
189189
<h2 id="usage"><a class="header" href="#usage">Usage</a></h2>
190-
<pre><code class="language-typescript">import { run } from &quot;https://deno.land/x/proc@0.21.6/mod.ts&quot;;
190+
<pre><code class="language-typescript">import { run } from &quot;https://deno.land/x/proc@0.21.7/mod.ts&quot;;
191191
</code></pre>
192192
<h2 id="a-simple-example"><a class="header" href="#a-simple-example">A Simple Example</a></h2>
193193
<p>Run <code>ls -la</code> as a child process. Decode <code>stdout</code> as lines of text. Print to

docs/performance.html

Lines changed: 31 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -175,44 +175,37 @@ <h1 class="menu-title">proc</h1>
175175
<main>
176176
<h1 id="performance"><a class="header" href="#performance">Performance</a></h1>
177177
<p>A few notes on performance.</p>
178-
<h2 id="avoid-string-conversions"><a class="header" href="#avoid-string-conversions">Avoid String Conversions</a></h2>
179-
<p>Avoid unnecessary string conversions.</p>
180-
<p>Conversions from bytes to JavaScript strings and back are expensive. String data
181-
is typically represented at UTF-8, which is one to six bytes per unicode code
182-
point. JavaScript strings are represented in memory as UTF-16, or 16 bits or 32
183-
bits (2 bytes or 4 bytes) to represent one unicode code point. Conversion logic
184-
is non-trivial.</p>
185-
<p>Whenever possible, <code>proc</code> allows passing raw byte arrays between processes so
186-
conversion is optional.</p>
187-
<p>Do this:</p>
188-
<pre><code class="language-typescript">const lineCount = parseInt(
189-
await read(&quot;warandpeace.txt&quot;).run(&quot;wc&quot;, &quot;-l&quot;).lines.first,
190-
10,
191-
);
192-
</code></pre>
193-
<p>Not this. This will work, as the lines will automatically be converted back to
194-
UTF-8 before being passed to <code>wc -l</code> (which counts lines). However, this makes
195-
the V8 engine do a lot of extra work and slows down execution.</p>
196-
<pre><code class="language-typescript">const lineCount = parseInt(
197-
await read(&quot;warandpeace.txt&quot;).lines.run(&quot;wc&quot;, &quot;-l&quot;).lines.first,
198-
10,
199-
);
200-
</code></pre>
201-
<h2 id="asynchronous-code"><a class="header" href="#asynchronous-code">Asynchronous Code</a></h2>
202-
<p>Asynchronous code is fast, but it's not as fast as code using for-loops, arrays,
203-
and simple types.</p>
204-
<p>Given what it is doing, V8 does a stellar job of optimizing asynchronous code.
205-
Most of the time, you shouldn't have to worry about performance of code written
206-
this way. However, <code>async</code>/<code>await</code> isn't (quite) a zero-cost abstraction.</p>
207-
<p>When performance is a concern and data size allows, it may be more performant to
208-
move operations to in-memory arrays. Code that does lots of small operations or
209-
works on very small data can usually be reworked into non-asynchronous code for
210-
better performance.</p>
211-
<p>Keep in mind that code written using promises, <code>AsyncIterable</code>, and
212-
<code>async</code>/<code>await</code> is going to be very well optimized and run quickly. A <em>lot</em> of
213-
work went into making promise code run as quickly as possible in V8. Write clean
214-
code first and measure your performance before you start trying to hand-optimize
215-
things.</p>
178+
<h2 id="does-performance-matter"><a class="header" href="#does-performance-matter">Does Performance Matter?</a></h2>
179+
<p>For 90% of the code you write, the bottom line is that performance does not
180+
matter. For example, if you have some code that reads configuration on startup
181+
and dumps it into an object, that code might be complicated, but it won't matter
182+
if it runs in 10 milliseconds or 100 nanoseconds. Write clear code first and
183+
optimize once things are working. Follow this process, and you will quickly
184+
figure out which things do and don't matter.</p>
185+
<h2 id="the-cost-of-iteration"><a class="header" href="#the-cost-of-iteration">The Cost of Iteration</a></h2>
186+
<p>We use iteration everywhere. Doing it wrong can kill your performance. Doing it
187+
right can get you close to (single threaded) C performance. This is a quick
188+
summary of what you can expect. To keep it short, I am just going to cover the
189+
high points and not show my work.</p>
190+
<p>The fastest code you can write in pure JavaScript looks like
191+
<a href="https://en.wikipedia.org/wiki/Asm.js">asm.js</a>. If you stick to <code>for</code> loops that
192+
count and index simple types or data object lookups in arrays or numbers in
193+
typed-arrays (like <code>Uint8Array</code>), you can expect that code to run at or near
194+
single-threaded C speed.</p>
195+
<p>Expect <code>for...of</code> with iterables and generators to be about 10x slower. This
196+
includes array methods like <code>map</code>, <code>filter</code>, and <code>reduce</code>. Anything that has to
197+
call a function in a loop is going to have extra overhead.</p>
198+
<p>Promise-driven asynchronous code is another 10x slower, or 100x slower than the
199+
<code>asm.js</code>-style code. This affects code written using <code>proc</code>, particularly
200+
<code>Enumerable</code>.</p>
201+
<p>So does this mean you have to always use <code>asm.js</code> syntax? Not at all. <code>for...of</code>
202+
syntax and array methods make for cleaner code, and asynchronous operations are
203+
the whole reason we're here. Iteration performance is mostly about the inner
204+
loops. If your inner loops are tight, a little less efficiency in the outer
205+
loops won't matter much. Write clean code first. When things are working, look
206+
for opportunities to make it faster. Often this will mean a little profiling and
207+
rewriting a few routines in <code>asm.js</code> style. If you do it right, you should be
208+
able to get very good performance along with readable code.</p>
216209
<p><a href="https://medium.com/netscape/async-iterators-these-promises-are-killing-my-performance-4767df03d85b">Async Iterators: These Promises Are Killing My Performance!</a>
217210
on Medium and supporting benchmarks in
218211
<a href="https://github.com/danvk/async-iteration">async-iteration</a> on Github.</p>

0 commit comments

Comments
 (0)