Improvements to $&here
w/r/t forking
#160
Open
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
First of all -- rewrite
$&here
so that it more closely matches the otherpipefork()
ing primitives inprim-io.c
, rather than theREDIR()
-using primitives. There are aspects ofPRIM(here)
which match both sets of primitives (with this PR,$&here
is the onlypipefork()
-style primitive which uses adefer_*()
function), but I think that holistically$&here
"fits" better with thepipefork()
style.Plus, the
pipefork()
style makes it more straightforward to actually wait for the forked-off process, which we do now, no longer leaking child processes. This fixes #150.Lastly, we now compare the doc length to
PIPE_BUF
and if smaller, we just write the whole doc to the new pipe without forking at all. POSIX demands aPIPE_BUF
of at least 512 bytes, and most systems use 4096, but I expect that even the smaller value catches a pretty large majority of heredoc uses in modern use. (TechnicallyPIPE_BUF
doesn't even indicate pipe capacity on a system, and some shells like bash at least do an active test at build time to probe the actual capacity, but it makes for a pretty reasonable lower bound and, again, I think this lower bound catches most cases). Not all OSes (e.g., the Hurd) define aPIPE_BUF
; in that case we just fall back to always forking.See the following for the performance impact (in the optimal case, where there are no other forks involved) of removing the forks:
Even when writing to a fork/exec'd binary, the difference is fairly significant (over 20% reduction in real time):