tech-userlevel archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: mail(1) - string relaxation
Can you forward these patches to gnats?
On Mon, Dec 9, 2013 at 3:03 PM, Steffen Daode <sdaoden%gmail.com@localhost>
wrote:
> Hello,
> i've implemented string relaxation in the S-nail(1) codebase and
> gained massive reduction of memory overhead.
> Since this thing is an exploded BSD Mail i thought doing the same
> for NetBSD mail(1) wouldn't be something bad, but it seems the
> wins are not comparable dramatic, most likely because of the
> completely different MIME approach. Still there is a win,
> especially with large mailboxes (many messages that is) which need
> to be updated (after 'unre'ing a message, for example).
> This diff should work just fine, even if the signal handling of
> NetBSD mail(1) is far more improved in comparison; (note that,
> because of the sreset() that happens on each command loop tick,
> even the other case would likely survive (in fact i'm not quite
> sure if the recursion doesn't simply jump away, but if so,
> again..)).
> (And note my repo hasn't been updated for about two months, i'm
> behind GPRS most of the time, but i don't remember any mail
> change? On interest and otherwise i'll update and resend.)
> Ciao,
>
> --steffen
>
> diff -Napru nmail/cmd1.c nmail.relax/cmd1.c
> --- nmail/cmd1.c 2013-12-09 13:16:52.000000000 +0100
> +++ nmail.relax/cmd1.c 2013-12-09 19:09:03.000000000 +0100
> @@ -124,13 +124,16 @@ headers(void *v)
> flag = 0;
> if (dot != get_message(n))
> dot = mp;
> + srelax_on();
> for (/*EMPTY*/; mp; mp = next_message(mp)) {
> if (mp->m_flag & MDELETED)
> continue;
> if (flag++ >= size)
> break;
> printhead(get_msgnum(mp));
> + srelax();
> }
> + srelax_off();
> if (flag == 0) {
> (void)printf("No more mail.\n");
> return 1;
> @@ -343,6 +346,7 @@ type1(int *msgvec, int doign, int mime_d
> * exit code will never be seen.
> */
> sig_check();
> + srelax_on();
> oldsigpipe = sig_signal(SIGPIPE, cmd1_brokpipe);
> if (setjmp(pipestop))
> goto close_pipe;
> @@ -365,8 +369,10 @@ type1(int *msgvec, int doign, int mime_d
> args.mip = NULL;
> #endif
> (void)thread_recursion(mp, type1_core, &args);
> + srelax();
> }
> close_pipe:
> + srelax_off();
> #ifdef MIME_SUPPORT
> if (mip != NULL) {
> struct sigaction osa;
> @@ -549,6 +555,7 @@ top(void *v)
> args.lineb = 1;
> recursive = do_recursion();
> msgCount = get_msgCount();
> + srelax_on();
> for (ip = msgvec; *ip && ip - msgvec < msgCount; ip++) {
> struct message *mp;
>
> @@ -556,7 +563,9 @@ top(void *v)
> dot = mp;
> args.parent = recursive ? mp : NULL;
> (void)thread_recursion(mp, top_core, &args);
> + srelax();
> }
> + srelax_off();
> return 0;
> }
>
> diff -Napru nmail/cmd2.c nmail.relax/cmd2.c
> --- nmail/cmd2.c 2013-12-09 13:16:52.000000000 +0100
> +++ nmail.relax/cmd2.c 2013-12-09 19:02:25.000000000 +0100
> @@ -234,6 +234,7 @@ save1(char str[], int markmsg, const cha
> warn(NULL);
> return 1;
> }
> + srelax_on();
> for (ip = msgvec; *ip && ip - msgvec < msgCount; ip++) {
> struct save1_core_args_s args;
> struct message *mp;
> @@ -245,9 +246,12 @@ save1(char str[], int markmsg, const cha
> if (thread_recursion(mp, save1_core, &args)) {
> warn("%s", fn);
> (void)Fclose(obuf);
> + srelax_off();
> return 1;
> }
> + srelax();
> }
> + srelax_off();
> (void)fflush(obuf);
> if (ferror(obuf))
> warn("%s", fn);
> @@ -690,6 +694,7 @@ detach1(void *v, int do_unnamed)
> msgvec[1] = 0;
> }
> recursive = do_recursion();
> + srelax_on();
> for (ip = msgvec; *ip && ip - msgvec < msgCount; ip++) {
> struct detach1_core_args_s args;
> struct message *mp;
> @@ -700,7 +705,9 @@ detach1(void *v, int do_unnamed)
> args.igtab = do_unnamed ? detachall : ignoreall;
> args.dstdir = dstdir;
> (void)thread_recursion(mp, detach1_core, &args);
> + srelax();
> }
> + srelax_off();
> return 0;
> }
>
> diff -Napru nmail/extern.h nmail.relax/extern.h
> --- nmail/extern.h 2013-12-09 13:16:52.000000000 +0100
> +++ nmail.relax/extern.h 2013-12-09 18:36:12.000000000 +0100
> @@ -278,6 +278,9 @@ int sendmail(void *);
> void * csalloc(size_t, size_t);
> void * salloc(size_t);
> void sreset(void);
> +void srelax_on(void);
> +void srelax_off(void);
> +void srelax(void);
> void spreserve(void);
>
> /*
> diff -Napru nmail/list.c nmail.relax/list.c
> --- nmail/list.c 2013-12-09 13:16:52.000000000 +0100
> +++ nmail.relax/list.c 2013-12-09 19:06:33.000000000 +0100
> @@ -845,6 +845,7 @@ match_string(int *markarray, char *str,
> return -1;
>
> rval = 0;
> + srelax_on();
> for (i = 1; i <= msgCount; i++) {
> struct message *mp;
> mp = get_message(i);
> @@ -854,7 +855,9 @@ match_string(int *markarray, char *str,
> if (rval)
> markarray[i - 1] = 1;
> rval = 0;
> + srelax();
> }
> + srelax_off();
>
> free_cmparg(cmparg); /* free any memory allocated by get_cmpfn() */
>
> @@ -1325,9 +1328,13 @@ show_headers_and_exit(int flags)
> (void)signal(SIGINT, SIG_IGN);
>
> flags &= CMMASK;
> + srelax_on();
> for (mp = get_message(1); mp; mp = next_message(mp))
> - if (flags == 0 || !ignore_message(mp->m_flag, flags))
> + if (flags == 0 || !ignore_message(mp->m_flag, flags)) {
> printhead(get_msgnum(mp));
> + srelax();
> + }
> + srelax_off();
>
> exit(0);
> /* NOTREACHED */
> diff -Napru nmail/quit.c nmail.relax/quit.c
> --- nmail/quit.c 2013-12-09 13:16:52.000000000 +0100
> +++ nmail.relax/quit.c 2013-12-09 18:59:56.000000000 +0100
> @@ -95,15 +95,19 @@ writeback(FILE *res)
> }
> }
> #endif
> + srelax_on();
> for (mp = get_message(1); mp; mp = next_message(mp))
> if ((mp->m_flag & MPRESERVE) || (mp->m_flag & MTOUCH)==0) {
> p++;
> if (sendmessage(mp, obuf, NULL, NULL, NULL) < 0) {
> warn("%s", mailname);
> (void)Fclose(obuf);
> + srelax_off();
> return -1;
> }
> + srelax();
> }
> + srelax_off();
> #ifdef APPEND
> if (res != NULL)
> while ((c = getc(res)) != EOF)
> @@ -221,16 +225,20 @@ edstop(jmp_buf jmpbuf)
> }
> trunc(obuf);
> c = 0;
> + srelax_on();
> for (mp = get_message(1); mp; mp = next_message(mp)) {
> if ((mp->m_flag & MDELETED) != 0)
> continue;
> c++;
> if (sendmessage(mp, obuf, NULL, NULL, NULL) < 0) {
> warn("%s", mailname);
> + srelax_off();
> sig_release();
> longjmp(jmpbuf, -1);
> }
> + srelax();
> }
> + srelax_off();
> gotcha = (c == 0 && ibuf == NULL);
> if (ibuf != NULL) {
> while ((c = getc(ibuf)) != EOF)
> @@ -480,17 +488,22 @@ nolock:
> }
> (void)fchmod(fileno(obuf), 0600);
> }
> + srelax_on();
> for (mp = get_message(1); mp; mp = next_message(mp))
> - if (mp->m_flag & MBOX)
> + if (mp->m_flag & MBOX) {
> if (sendmessage(mp, obuf, saveignore, NULL, NULL) <
> 0) {
> warn("%s", mbox);
> if (!append)
> (void)Fclose(ibuf);
> (void)Fclose(obuf);
> (void)Fclose(fbuf);
> + srelax_off();
> dot_unlock(mailname);
> return;
> }
> + srelax();
> + }
> + srelax_off();
>
> /*
> * Copy the user's old mbox contents back
> diff -Napru nmail/strings.c nmail.relax/strings.c
> --- nmail/strings.c 2013-12-09 13:16:52.000000000 +0100
> +++ nmail.relax/strings.c 2013-12-09 20:08:08.000000000 +0100
> @@ -38,6 +38,8 @@ __RCSID("$NetBSD: strings.c,v 1.18 2010/
> #endif
> #endif /* not lint */
>
> +#include <assert.h>
> +
> /*
> * Mail -- a mail program
> *
> @@ -60,10 +62,13 @@ __RCSID("$NetBSD: strings.c,v 1.18 2010/
> #define NSPACE 25 /* Total number of string
> spaces */
> static struct strings {
> char *s_topFree; /* Beginning of this area */
> + char *s_relaxFree; /* Begin of area during relaxation */
> char *s_nextFree; /* Next alloctable place here */
> size_t s_nleft; /* Number of bytes left here */
> } stringdope[NSPACE];
>
> +static int relaxation;
> +
> /*
> * Allocate size more bytes of space and return the address of the
> * first byte to the caller. An even number of bytes are always
> @@ -97,6 +102,7 @@ salloc(size_t size)
> sp->s_topFree = malloc(STRINGSIZE << idx);
> if (sp->s_topFree == NULL)
> errx(EXIT_FAILURE, "No room for space %d", idx);
> + sp->s_relaxFree = NULL;
> sp->s_nextFree = sp->s_topFree;
> sp->s_nleft = STRINGSIZE << idx;
> }
> @@ -131,13 +137,64 @@ sreset(void)
>
> if (noreset)
> return;
> +
> + relaxation = 0;
> +
> idx = 0;
> - for (sp = &stringdope[0]; sp < &stringdope[NSPACE]; sp++) {
> + for (sp = &stringdope[0]; sp < &stringdope[NSPACE]; ++idx, ++sp) {
> if (sp->s_topFree == NULL)
> continue;
> + sp->s_relaxFree = NULL;
> sp->s_nextFree = sp->s_topFree;
> sp->s_nleft = STRINGSIZE << idx;
> - idx++;
> + }
> +}
> +
> +PUBLIC void
> +srelax_on(void)
> +{
> + struct strings *sp;
> + int idx;
> +
> + assert(relaxation == 0);
> +
> + idx = 0;
> + for (sp = &stringdope[0]; sp < &stringdope[NSPACE]; ++idx, ++sp) {
> + if (sp->s_topFree == NULL)
> + continue;
> + sp->s_relaxFree = sp->s_nextFree;
> + }
> +
> + relaxation = 1;
> +}
> +
> +PUBLIC void
> +srelax_off(void)
> +{
> + assert(relaxation == 1);
> +
> + srelax();
> + relaxation = 0;
> +}
> +
> +PUBLIC void
> +srelax(void)
> +{
> + struct strings *sp;
> + int idx;
> +
> + assert(relaxation == 1);
> +
> + idx = 0;
> + for (sp = &stringdope[0]; sp < &stringdope[NSPACE]; ++idx, ++sp) {
> + if (sp->s_topFree == NULL)
> + continue;
> + sp->s_nleft = STRINGSIZE << idx;
> + if ((sp->s_nextFree = sp->s_relaxFree) == NULL)
> + sp->s_nextFree = sp->s_topFree;
> + else
> + sp->s_nleft -= (size_t)(uintptr_t)(sp->s_relaxFree -
> + sp->s_topFree);
> }
> }
>
Home |
Main Index |
Thread Index |
Old Index