summaryrefslogtreecommitdiffstats
path: root/bin
diff options
context:
space:
mode:
authorjilles <jilles@FreeBSD.org>2016-01-30 21:21:25 +0000
committerjilles <jilles@FreeBSD.org>2016-01-30 21:21:25 +0000
commit8705203e12c893788c5411aecab0a0c7b1500713 (patch)
treeb027c2c7d784bb2dd96af19d3d2a1032843693b5 /bin
parent365b605737d46eaff10439e6236e87a2d102cdb8 (diff)
downloadFreeBSD-src-8705203e12c893788c5411aecab0a0c7b1500713.zip
FreeBSD-src-8705203e12c893788c5411aecab0a0c7b1500713.tar.gz
sh: Don't allocate a redirtab if there are no redirections.
Builtins (including variable assignments without command word), function calls and redirected compound commands need to restore file descriptors to their original state after execution. This is handled by allocating a redirtab structure. These mallocs and frees show up heavily in pmcstat. Only allocate a redirtab if there are actually redirections and maintain a count of how many levels of REDIR_PUSH there are without redirtabs. A simple loop without external programs like sh -c 'i=0; w=$(printf %0100d 7); while [ "$i" -lt 1000000 ]; do i=$((i+1)); done' is over 25% faster on an amd64 bhyve VM.
Diffstat (limited to 'bin')
-rw-r--r--bin/sh/redir.c29
1 files changed, 22 insertions, 7 deletions
diff --git a/bin/sh/redir.c b/bin/sh/redir.c
index 95d3238..0a7aa96 100644
--- a/bin/sh/redir.c
+++ b/bin/sh/redir.c
@@ -70,6 +70,7 @@ struct redirtab {
struct redirtab *next;
int renamed[10];
int fd0_redirected;
+ unsigned int empty_redirs;
};
@@ -82,6 +83,9 @@ static struct redirtab *redirlist;
*/
static int fd0_redirected = 0;
+/* Number of redirtabs that have not been allocated. */
+static unsigned int empty_redirs = 0;
+
static void openredirect(union node *, char[10 ]);
static int openhere(union node *);
@@ -115,12 +119,17 @@ redirect(union node *redir, int flags)
memory[i] = 0;
memory[1] = flags & REDIR_BACKQ;
if (flags & REDIR_PUSH) {
- sv = ckmalloc(sizeof (struct redirtab));
- for (i = 0 ; i < 10 ; i++)
- sv->renamed[i] = EMPTY;
- sv->fd0_redirected = fd0_redirected;
- sv->next = redirlist;
- redirlist = sv;
+ empty_redirs++;
+ if (redir != NULL) {
+ sv = ckmalloc(sizeof (struct redirtab));
+ for (i = 0 ; i < 10 ; i++)
+ sv->renamed[i] = EMPTY;
+ sv->fd0_redirected = fd0_redirected;
+ sv->empty_redirs = empty_redirs - 1;
+ sv->next = redirlist;
+ redirlist = sv;
+ empty_redirs = 0;
+ }
}
for (n = redir ; n ; n = n->nfile.next) {
fd = n->nfile.fd;
@@ -303,6 +312,12 @@ popredir(void)
struct redirtab *rp = redirlist;
int i;
+ INTOFF;
+ if (empty_redirs > 0) {
+ empty_redirs--;
+ INTON;
+ return;
+ }
for (i = 0 ; i < 10 ; i++) {
if (rp->renamed[i] != EMPTY) {
if (rp->renamed[i] >= 0) {
@@ -313,8 +328,8 @@ popredir(void)
}
}
}
- INTOFF;
fd0_redirected = rp->fd0_redirected;
+ empty_redirs = rp->empty_redirs;
redirlist = rp->next;
ckfree(rp);
INTON;
OpenPOWER on IntegriCloud