zsh-workers
 help / color / mirror / code / Atom feed
* Some glob.c cleanups
@ 1995-07-14 15:10 Zoltan Hidvegi
  1995-07-14 17:59 ` Barton E. Schaefer
  0 siblings, 1 reply; 2+ messages in thread
From: Zoltan Hidvegi @ 1995-07-14 15:10 UTC (permalink / raw)
  To: zsh-workers

The patch below contains some little cleanups for glob.c. I moved
fwskipparens() from zle_tricky.c to utils.c, and made it global function. I
use it in two places in glob.c. This allowed me to remove a kludge labelled
goto.

The other change is more visible: in parsecomp zsh allocated a 2*PATH_MAX
buffer from the heap each time it parsed a glob pattern. This buffer was used
to store part of the pattern, which is usually much shorter than
2*PATH_MAX. This sometimes lead to very large memory usage. Also on some
machines or on all machines with ZSH_MEM, this larege allocated heap area was
not given back to the system after it was not needed, probably because the
memory fragmented in a way that prevented this. Also frequent calls to
malloc() slowd down zsh. I changed parsecomp to use a 2*PATH_MAX long local
variable, and use dupstring after the necessary string was calculated.

The old code used alloc() which fills the requested area with zeros, but the
code did not used this fact so I do not initialize the local variable
here. This may also speed up things a little bit.

On linux, before the patch:
ktud% foo=(a{,}{,}{,}{,}{,}{,}{,}{,}{,}{,})
ktud% ps aux $$
USER       PID %CPU %MEM SIZE  RSS TTY STAT START   TIME COMMAND
hzoli     7230  2.8  3.7  472  576 pp1 S    15:26   0:00 zsh -f
ktud% : ${foo%?}
ktud% ps aux $$
USER       PID %CPU %MEM SIZE  RSS TTY STAT START   TIME COMMAND
hzoli     7230  3.9 21.7 3180 3288 pp1 S    15:26   0:01 zsh -f

And after the patch:
ktud% foo=(a{,}{,}{,}{,}{,}{,}{,}{,}{,}{,})
ktud% ps aux $$
USER       PID %CPU %MEM SIZE  RSS TTY STAT START   TIME COMMAND
hzoli     7281  3.7  3.8  472  580 pp1 S    15:30   0:00 ./zsh -f
ktud% : ${foo%?}
ktud% ps aux $$
USER       PID %CPU %MEM SIZE  RSS TTY STAT START   TIME COMMAND
hzoli     7281  2.1  3.9  488  596 pp1 S    15:30   0:00 ./zsh -f

The difference is 2692k. On Solaris 2.3 this difference is `only' 674k but you
get similar result to linux if ZSH_MEM was defined. The reason for the 2692k is
that the heap is allocated in chunks which are a few bytes less than
8192. 2*PATH_MAX is usually 2048 bytes, so only three such area fits into one
chunk. That means that the memory required here is 2048*1024*4/3 which is
2730k.

Cheers,

   Zoltan

*** 1.8	1995/07/07 17:01:35
--- Src/glob.c	1995/07/14 13:09:36
***************
*** 1785,1802 ****
  {
      Comp c1;
      Complist p1;
  
!     if (pptr[0] == Star && pptr[1] == Star) {
  	/* Match any number of directories. */
! 	int follow = 0;
  
! 	if (pptr[2] == '/')
! 	    pptr += 3;
! 	else if (pptr[2] == Star && pptr[3] == '/') {
! 	    pptr += 4;
! 	    follow = 1;		/* with three stars, follow symbolic links */
! 	} else
! 	    goto kludge;	/* not the end of the path component. */
  
  	/* Now get the next path component if there is one. */
  	p1 = (Complist) alloc(sizeof *p1);
--- 1785,1799 ----
  {
      Comp c1;
      Complist p1;
+     char *str;
  
!     if (pptr[0] == Star && pptr[1] == Star &&
!         (pptr[2] == '/' || (pptr[2] == Star && pptr[3] == '/'))) {
  	/* Match any number of directories. */
! 	int follow;
  
! 	/* with three stars, follow symbolic links */
! 	pptr += 3 + (follow = pptr[2] == Star);
  
  	/* Now get the next path component if there is one. */
  	p1 = (Complist) alloc(sizeof *p1);
***************
*** 1812,1830 ****
  	p1->follow = follow;
  	return p1;
      }
!     if (*pptr == Inpar) {
  	/* parse repeated directories (ordinary groups are
  	 * handled by parsecompsw()) */
- 	char *str;
- 	int pars = 1;
- 
- 	for (str = pptr + 1; *str && pars; str++)
- 	    if (*str == Inpar)
- 		pars++;
- 	    else if (*str == Outpar)
- 		pars--;
- 	if (str[0] != Pound || str[-1] != Outpar || str[-2] != '/')
- 	    goto kludge;	/* not a repeated directory */
  	/* (dir/)# and (dir/)## code */
  	pptr++;
  	if (!(c1 = parsecompsw(0)))
--- 1809,1818 ----
  	p1->follow = follow;
  	return p1;
      }
!     if (*(str = pptr) == Inpar && !fwskipparens(Inpar, Outpar, &str) &&
!         *str == Pound && str[-2] == '/') {
  	/* parse repeated directories (ordinary groups are
  	 * handled by parsecompsw()) */
  	/* (dir/)# and (dir/)## code */
  	pptr++;
  	if (!(c1 = parsecompsw(0)))
***************
*** 1845,1851 ****
  	    return (p1->comp) ? p1 : NULL;
  	}
      } else {
-       kludge:
  	/* parse single path component */
  	if (!(c1 = parsecompsw(1)))
  	    return NULL;
--- 1833,1838 ----
***************
*** 1871,1877 ****
  parsecomp(void)
  {
      Comp c = (Comp) alloc(sizeof *c), c1, c2;
!     char *s = c->str = (char *)alloc(PATH_MAX * 2), *ls = NULL;
  
      /* In case of alternatives, code coming up is stored in tail. */
      c->next = tail;
--- 1858,1864 ----
  parsecomp(void)
  {
      Comp c = (Comp) alloc(sizeof *c), c1, c2;
!     char cstr[PATH_MAX * 2], *s = cstr, *ls = NULL;
  
      /* In case of alternatives, code coming up is stored in tail. */
      c->next = tail;
***************
*** 1890,1895 ****
--- 1877,1883 ----
  	    pptr++;
  	    if (!(c->next = parsecomp()))
  		return NULL;
+ 	    c->str = dupstring(cstr);
  	    return c;
  	}
  	if (*pptr == Star && pptr[1] &&
***************
*** 1909,1930 ****
  		return NULL;
  	    c1->next = c2;
  	    c->next = c1;
  	    return c;
  	}
  	if (*pptr == Inpar) {
  	    /* Found a group (...) */
- 	    int pars = 1;
  	    char *startp = pptr, *endp;
  	    Comp stail = tail;
  	    int dpnd = 0;
  
  	    /* Need matching close parenthesis */
! 	    for (pptr = pptr + 1; *pptr && pars; pptr++)
! 		if (*pptr == Inpar)
! 		    pars++;
! 		else if (*pptr == Outpar)
! 		    pars--;
! 	    if (pptr[-1] != Outpar) {
  		errflag = 1;
  		return NULL;
  	    }
--- 1897,1913 ----
  		return NULL;
  	    c1->next = c2;
  	    c->next = c1;
+ 	    c->str = dupstring(cstr);
  	    return c;
  	}
  	if (*pptr == Inpar) {
  	    /* Found a group (...) */
  	    char *startp = pptr, *endp;
  	    Comp stail = tail;
  	    int dpnd = 0;
  
  	    /* Need matching close parenthesis */
! 	    if (fwskipparens(Inpar, Outpar, &pptr)) {
  		errflag = 1;
  		return NULL;
  	    }
***************
*** 1955,1960 ****
--- 1938,1944 ----
  	    c->next->next = dpnd ? c1 : (Comp) alloc(sizeof *c);
  	    pptr = endp;
  	    tail = stail;
+ 	    c->str = dupstring(cstr);
  	    return c;
  	}
  	if (*pptr == Pound) {
***************
*** 1978,1983 ****
--- 1962,1968 ----
  	    if (!c2->next)
  		return NULL;
  	    *ls++ = '\0';
+ 	    c->str = dupstring(cstr);
  	    return c;
  	}
  	ls = s;			/* whatever we just parsed */
***************
*** 2011,2016 ****
--- 1996,2002 ----
      if (*pptr == '/' || !*pptr)
  	c->stat |= C_LAST;
      *s++ = '\0';
+     c->str = dupstring(cstr);
      return c;
  }
  
*** 1.12	1995/07/11 15:09:08
--- Src/utils.c	1995/07/14 13:09:36
***************
*** 2689,2691 ****
--- 2689,2711 ----
      }
      return (0L);
  }
+ 
+ /* Skip over a balanced pair of parenthesis. */
+ 
+ /**/
+ int
+ fwskipparens(char inpar, char outpar, char **s)
+ {
+     int level;
+ 
+     if (**s != inpar)
+ 	return -1;
+ 
+     for (level = 1; *++*s && level;)
+ 	if (**s == inpar)
+ 	   ++level;
+ 	else if (**s == outpar)
+ 	   --level;
+ 
+    return level;
+ }
*** 1.24	1995/07/12 14:51:48
--- Src/zle_tricky.c	1995/07/14 13:09:37
***************
*** 175,199 ****
  static int remove_at = -1;
  
  
- /* Skip over a balanced pair of parenthesis. */
- 
- static int
- fwskipparens(char inpar, char outpar, char **s)
- {
-     int level;
- 
-     if (**s != inpar)
- 	return -1;
- 
-     for (level = 1; *++*s && level;)
- 	if (**s == inpar)
- 	   ++level;
- 	else if (**s == outpar)
- 	   --level;
- 
-    return level;
- }
- 
  /* Find out if we have to insert a tab (instead of trying to complete). */
  
  /**/
--- 175,180 ----


^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: Some glob.c cleanups
  1995-07-14 15:10 Some glob.c cleanups Zoltan Hidvegi
@ 1995-07-14 17:59 ` Barton E. Schaefer
  0 siblings, 0 replies; 2+ messages in thread
From: Barton E. Schaefer @ 1995-07-14 17:59 UTC (permalink / raw)
  To: Zoltan Hidvegi, zsh-workers

On Jul 14,  4:10pm, Zoltan Hidvegi wrote:
} Subject: Some glob.c cleanups
}
} Also on some machines or on all machines with ZSH_MEM, this larege
} allocated heap area was not given back to the system after it was not
} needed, probably because the memory fragmented in a way that prevented
} this.

Just as a note:  I don't know of *any* malloc library that will compact
heap and return it to the system, no matter what allocation behavior
your application has.  Malloc maintains and re-uses its own internal
free list; when the free list doesn't contain a large-enough block for
a particular allocation, sbrk() is used to get more from the system,
but that new memory simply goes into the internal free list when freed.

Applications that release memory back to the system, like GNU emacs, use
their own heap allocation and compaction algorithms, and avoid malloc.
-- 
Bart Schaefer                     Vice President, Technology, Z-Code Software
schaefer@z-code.com                  Division of NCD Software Corporation
http://www.well.com/www/barts


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~1995-07-14 20:54 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1995-07-14 15:10 Some glob.c cleanups Zoltan Hidvegi
1995-07-14 17:59 ` Barton E. Schaefer

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).