This patch does two things...
First, it replaces new_realloc() with one that actually calls realloc(),
using new_malloc() as a template. This has a big impact on performance
for string append functions because realloc typically does a whole lot
of good stuff to prevent the block being copied when it doesn't have to
be.
Secondly, it renames the 4 m_*3cat* functions with a new argument to
point to the end of the string, and #defines the old names to point to
the new with a token extra argument.
The impact of both of these is that the performance of certain functions
which call them repeatedly is greatly improved.
The design of the last one isn't so great. Instead of 4 3cat functions,
there are now 8. Hop has expressed that it would be a better idea to go
right through the source altering their use for the new functions, then
remove the old. I am happy to do this if need be.
This alias demonstrates the improvement:
alias purge {
# revw does actually improve performance due to the way
# variables are stored.
@:list=revw($aliasctl(assign pmatch "\\[$*\\]"))
fe ($list) bar {
^assign -$bar
}
if (functioncall()) {
return $#list
} else {
echo $#list purged.
}
}
One other thing in the patch not covered by all this is that it turns
variable storage size checking for the delete case on again. I can only
guess that this was originally turned off because new_realloc was so
slow.
diff -ruN ../epic4-1.0.1/include/ircaux.h ./include/ircaux.h
--- ../epic4-1.0.1/include/ircaux.h Thu Mar 8 05:03:23 2001
+++ ./include/ircaux.h Tue Aug 28 04:36:52 2001
@@ -24,6 +24,10 @@
fatal_malloc_check ((void *)(x), (y), __FILE__, __LINE__)
#define RESIZE(x, y, z) new_realloc ((void **)& (x), sizeof(y) * (z))
#define LOCAL_COPY(y) strcpy(alloca(strlen((y)) + 1), y)
+#define m_e3cat(x,y,z) m_ec3cat((x),(y),(z),NULL)
+#define m_s3cat(x,y,z) m_sc3cat((x),(y),(z),NULL)
+#define m_s3cat_s(x,y,z) m_sc3cat_s((x),(y),(z),NULL)
+#define m_3cat(x,y,z) m_c3cat((x),(y),(z),NULL)
extern int need_delayed_free;
void fatal_malloc_check (void *, const char *, char *, int);
@@ -37,7 +41,7 @@
char * new_next_arg (char *, char **);
char * new_new_next_arg (char *, char **, char *);
char * s_next_arg (char **);
-char * last_arg (char **);
+char * last_arg (char **, size_t *cluep);
char * expand_twiddle (char *);
char * upper (char *);
char * lower (char *);
@@ -48,10 +52,10 @@
char * malloc_strcpy (char **, const char *);
char * malloc_strcat (char **, const char *);
char * malloc_str2cpy (char **, const char *, const char *);
-char * m_s3cat_s (char **, const char *, const char *);
-char * m_s3cat (char **, const char *, const char *);
-char * m_3cat (char **, const char *, const char *);
-char * m_e3cat (char **, const char *, const char *);
+char * m_sc3cat_s (char **, const char *, const char *, size_t *clue);
+char * m_sc3cat (char **, const char *, const char *, size_t *clue);
+char * m_c3cat (char **, const char *, const char *, size_t *clue);
+char * m_ec3cat (char **, const char *, const char *, size_t *clue);
char * m_2dup (const char *, const char *);
char * m_3dup (const char *, const char *, const char *);
char * m_opendup (const char *, ...) __A(1);
diff -ruN ../epic4-1.0.1/source/alias.c ./source/alias.c
--- ../epic4-1.0.1/source/alias.c Tue Dec 5 11:11:57 2000
+++ ./source/alias.c Tue Aug 28 04:38:35 2001
@@ -2354,6 +2354,7 @@
{
char **mlist = NULL;
char *mylist = NULL;
+ size_t mylistclue = 0;
int num = 0, ctr;
if (!my_stricmp(listc, "*"))
@@ -2368,7 +2369,7 @@
for (ctr = 0; ctr < num; ctr++)
{
- m_s3cat(&mylist, space, mlist[ctr]);
+ m_sc3cat(&mylist, space, mlist[ctr], &mylistclue);
new_free((char **)&mlist[ctr]);
}
new_free((char **)&mlist);
@@ -2380,6 +2381,7 @@
{
char ** mlist = NULL;
char * mylist = NULL;
+ size_t mylistclue = 0;
int num = 0,
ctr;
@@ -2390,7 +2392,7 @@
for (ctr = 0; ctr < num; ctr++)
{
- m_s3cat(&mylist, space, mlist[ctr]);
+ m_sc3cat(&mylist, space, mlist[ctr], &mylistclue);
new_free((char **)&mlist[ctr]);
}
new_free((char **)&mlist);
diff -ruN ../epic4-1.0.1/source/alist.c ./source/alist.c
--- ../epic4-1.0.1/source/alist.c Tue Dec 5 11:11:57 2000
+++ ./source/alist.c Tue Aug 28 04:36:52 2001
@@ -124,6 +124,7 @@
ret = ARRAY_ITEM(array, which);
move_array_items(array, which + 1, array->max, -1);
array->max--;
+ check_array_size(array);
return ret;
}
diff -ruN ../epic4-1.0.1/source/functions.c ./source/functions.c
--- ../epic4-1.0.1/source/functions.c Wed Mar 21 06:42:58 2001
+++ ./source/functions.c Tue Aug 28 04:36:52 2001
@@ -1149,6 +1149,7 @@
if (input && *input)
{
char *retval = NULL;
+ size_t rvclue=0;
char *nick;
const char *userhost;
@@ -1156,9 +1157,9 @@
{
GET_STR_ARG(nick, input);
if ((userhost = fetch_userhost(from_server, nick)))
- m_s3cat(&retval, space, userhost);
+ m_sc3cat(&retval, space, userhost, &rvclue);
else
- m_s3cat(&retval, space, unknown_userhost);
+ m_sc3cat(&retval, space, unknown_userhost, &rvclue);
}
RETURN_MSTR(retval);
}
@@ -1414,6 +1415,7 @@
{
int count;
char *retval = NULL;
+ size_t rvclue=0;
if (!input || !*input)
{
@@ -1424,7 +1426,7 @@
for (count = 0; count < number_of_servers; count++)
{
if (is_server_connected(count))
- m_s3cat(&retval, space, ltoa(count));
+ m_sc3cat(&retval, space, ltoa(count), &rvclue);
}
if (!retval)
RETURN_EMPTY;
@@ -1784,6 +1786,7 @@
*right = (char *) 0, **rightw = NULL, *booya = NULL;
int leftc, lefti,
rightc, righti;
+ size_t rvclue=0;
left = word;
if (!(right = strchr(word,'/')))
@@ -1799,7 +1802,7 @@
{
if (rightw[righti] && !my_stricmp(leftw[lefti],
rightw[righti]))
{
- m_s3cat(&booya, space, leftw[lefti]);
+ m_sc3cat(&booya, space, leftw[lefti], &rvclue);
rightw[righti] = NULL;
}
}
@@ -1825,6 +1828,7 @@
int lefti, leftc,
righti, rightc;
int found;
+ size_t rvclue=0;
left = word;
if ((right = strchr(word, '/')) == (char *) 0)
@@ -1834,7 +1838,7 @@
leftc = splitw(left, &leftw);
rightc = splitw(right, &rightw);
- for (lefti = 0; lefti < leftc; lefti++)
+ for (rvclue = lefti = 0; lefti < leftc; lefti++)
{
found = 0;
for (righti = 0; righti < rightc; righti++)
@@ -1846,13 +1850,13 @@
}
}
if (!found)
- m_s3cat(&booya, space, leftw[lefti]);
+ m_sc3cat(&booya, space, leftw[lefti], &rvclue);
}
- for (righti = 0; righti < rightc; righti++)
+ for (rvclue = righti = 0; righti < rightc; righti++)
{
if (rightw[righti])
- m_s3cat(&booya, space, rightw[righti]);
+ m_sc3cat(&booya, space, rightw[righti], &rvclue);
}
new_free((char **)&leftw);
@@ -1874,12 +1878,13 @@
char *blah;
char *booya = NULL;
char *pattern;
+ size_t rvclue=0;
GET_STR_ARG(pattern, word)
while (((blah = new_next_arg(word, &word)) != NULL))
{
if (wild_match(pattern, blah))
- m_s3cat(&booya, space, blah);
+ m_sc3cat(&booya, space, blah, &rvclue);
}
RETURN_MSTR(booya);
}
@@ -1894,12 +1899,13 @@
char *blah;
char *booya = NULL;
char *pattern;
+ size_t rvclue=0;
GET_STR_ARG(pattern, word)
while ((blah = new_next_arg(word, &word)) != NULL)
{
if (!wild_match(pattern, blah))
- m_s3cat(&booya, space, blah);
+ m_sc3cat(&booya, space, blah, &rvclue);
}
RETURN_MSTR(booya);
}
@@ -1915,13 +1921,14 @@
char *blah;
char *booya = NULL;
char *pattern;
+ size_t rvclue=0;
GET_STR_ARG(blah, word)
while ((pattern = new_next_arg(word, &word)) != NULL)
{
if (wild_match(pattern, blah))
- m_s3cat(&booya, space, pattern);
+ m_sc3cat(&booya, space, pattern, &rvclue);
}
RETURN_MSTR(booya);
}
@@ -1937,12 +1944,13 @@
char *blah;
char *booya = NULL;
char *pattern;
+ size_t rvclue=0;
GET_STR_ARG(blah, word)
while ((pattern = new_next_arg(word, &word)) != NULL)
{
if (!wild_match(pattern, blah))
- m_s3cat(&booya, space, pattern);
+ m_sc3cat(&booya, space, pattern, &rvclue);
}
RETURN_MSTR(booya);
}
@@ -1963,6 +1971,7 @@
*firstl = (char *) 0, *firstlist = (char *) 0, *firstel = (char *) 0,
*secondl = (char *) 0, *secondlist = (char *) 0, *secondel = (char *)
0;
char *sfirstl, *ssecondl;
+ size_t rvclue=0;
GET_STR_ARG(pattern, word);
GET_STR_ARG(firstlist, word);
@@ -1979,7 +1988,7 @@
break;
if (wild_match(pattern, firstel))
- m_s3cat(&booya, space, secondel);
+ m_sc3cat(&booya, space, secondel, &rvclue);
}
new_free(&sfirstl);
new_free(&ssecondl);
@@ -2200,6 +2209,7 @@
char *channel;
char *booya = (char *) 0;
const char *key;
+ size_t rvclue=0;
do
{
@@ -2208,7 +2218,7 @@
break;
key = get_channel_key(channel, current_window->server);
- m_s3cat(&booya, space, (key && *key) ? key : "*");
+ m_sc3cat(&booya, space, (key && *key) ? key : "*", &rvclue);
}
while (word && *word);
@@ -2224,6 +2234,7 @@
char *channel;
char *booya = (char *) 0;
char *mode;
+ size_t rvclue=0;
do
{
@@ -2232,7 +2243,7 @@
break;
mode = get_channel_mode(channel, current_window->server);
- m_s3cat(&booya, space, (mode && *mode) ? mode : "*");
+ m_sc3cat(&booya, space, (mode && *mode) ? mode : "*", &rvclue);
}
while (word && *word);
@@ -2244,9 +2255,10 @@
BUILT_IN_FUNCTION(function_revw, words)
{
char *booya = NULL;
+ size_t rvclue=0, wclue=0;
while (words && *words)
- m_s3cat(&booya, space, last_arg(&words));
+ m_sc3cat(&booya, space, last_arg(&words, &wclue), &rvclue);
if (!booya)
RETURN_EMPTY;
@@ -2450,6 +2462,7 @@
char * retval = NULL;
char * (*func) (const char *, const char *) = strstr;
int variable = 0, global = 0;
+ size_t rvclue=0;
/*
* Scan the leading part of the argument list, slurping up any
@@ -2546,7 +2559,7 @@
* is before the string to be replaced, and also
* the string that is to be doing the replacing.
*/
- m_e3cat(&retval, keep_text, replace_with);
+ m_ec3cat(&retval, keep_text, replace_with, &rvclue);
/*
* And now we want to step over the string and get
@@ -2639,13 +2652,14 @@
BUILT_IN_FUNCTION(function_ascii, word)
{
char *aboo = NULL;
+ size_t rvclue=0;
if (!word || !*word)
RETURN_EMPTY;
aboo = m_strdup(ltoa((long)(unsigned char)*word));
while (*++word)
- m_3cat(&aboo, space, ltoa((long)(unsigned char)*word));
+ m_c3cat(&aboo, space, ltoa((long)(unsigned char)*word), &rvclue);
return aboo;
}
@@ -3414,6 +3428,7 @@
*path2,
*retval = NULL;
int numglobs, i;
+ size_t rvclue=0;
glob_t globbers;
memset(&globbers, 0, sizeof(glob_t));
@@ -3435,10 +3450,10 @@
{
char *b = alloca(strlen(globbers.gl_pathv[i]) + 4);
sprintf(b, "\"%s\"", globbers.gl_pathv[i]);
- m_s3cat(&retval, space, b);
+ m_sc3cat(&retval, space, b, &rvclue);
}
else
- m_s3cat(&retval, space, globbers.gl_pathv[i]);
+ m_sc3cat(&retval, space, globbers.gl_pathv[i],
+&rvclue);
}
globfree(&globbers);
new_free(&path2);
@@ -3454,6 +3469,7 @@
*path2,
*retval = NULL;
int numglobs, i;
+ size_t rvclue=0;
glob_t globbers;
memset(&globbers, 0, sizeof(glob_t));
@@ -3476,10 +3492,10 @@
{
char *b = alloca(strlen(globbers.gl_pathv[i]) + 4);
sprintf(b, "\"%s\"", globbers.gl_pathv[i]);
- m_s3cat(&retval, space, b);
+ m_sc3cat(&retval, space, b, &rvclue);
}
else
- m_s3cat(&retval, space, globbers.gl_pathv[i]);
+ m_sc3cat(&retval, space, globbers.gl_pathv[i],
+&rvclue);
}
bsd_globfree(&globbers);
new_free(&path2);
@@ -3578,6 +3594,7 @@
int listc, listi;
char *tval;
char *input;
+ size_t rvclue=0;
RETURN_IF_EMPTY(word);
listc = splitw(word, &list);
@@ -3600,7 +3617,7 @@
tval = function_findw(input);
if (my_atol(tval) == -1)
- m_s3cat(&booya, space, list[listi]);
+ m_sc3cat(&booya, space, list[listi], &rvclue);
new_free(&tval);
}
@@ -4560,9 +4577,10 @@
{
Window *w = NULL;
char *retval = NULL;
+ size_t rvclue=0;
while (traverse_all_windows(&w))
- m_s3cat(&retval, space, ltoa(w->refnum));
+ m_sc3cat(&retval, space, ltoa(w->refnum), &rvclue);
RETURN_MSTR(retval);
}
@@ -4859,6 +4877,7 @@
rightc,
righti;
int found = 0;
+ size_t rvclue=0;
left = word;
if (!(right = strchr(word,'/')))
@@ -4881,7 +4900,7 @@
}
}
if (!found)
- m_s3cat(&booya, space, rhs[righti]);
+ m_sc3cat(&booya, space, rhs[righti], &rvclue);
rhs[righti] = NULL;
}
@@ -5717,12 +5736,13 @@
BUILT_IN_FUNCTION(function_notifywindows, input)
{
char * retval = NULL;
+ size_t rvclue=0;
Window *window;
window = NULL;
while (traverse_all_windows(&window))
if (window->miscflags & WINDOW_NOTIFIED)
- m_s3cat(&retval, space, ltoa(window->refnum));
+ m_sc3cat(&retval, space, ltoa(window->refnum), &rvclue);
RETURN_MSTR(retval);
}
diff -ruN ../epic4-1.0.1/source/ircaux.c ./source/ircaux.c
--- ../epic4-1.0.1/source/ircaux.c Thu Mar 15 07:01:46 2001
+++ ./source/ircaux.c Tue Aug 28 04:36:52 2001
@@ -191,9 +191,32 @@
return ((*ptr = NULL));
}
+#if 1
+
+/* really_new_malloc in disguise */
+void * new_realloc (void **ptr, size_t size)
+{
+ if (*ptr) {*ptr -= sizeof(MO);};
+ if (!(*ptr = (char *)realloc(*ptr, size + sizeof(MO))))
+ panic("realloc() failed, giving up!");
+
+ /* Store the size of the allocation in the buffer. */
+ *ptr += sizeof(MO);
+ magic(*ptr) = ALLOC_MAGIC;
+ alloc_size(*ptr) = size;
+ return *ptr;
+}
+
+#else
+
void * new_realloc (void **ptr, size_t size)
{
char *ptr2 = NULL;
+ size_t foo,bar;
+
+ /* Yes the function is ifdefed out, but this serves as a proof of concept. */
+ for (foo=1, bar=size+sizeof(MO); bar; foo<<=1, bar>>=1) /* Nothing */ ;
+ if (foo) {size=foo;}
if (*ptr)
{
@@ -215,6 +238,8 @@
return ((*ptr = ptr2));
}
+#endif
+
/*
* malloc_strcpy: Mallocs enough space for src to be copied in to where
* ptr points to.
@@ -250,6 +275,7 @@
char * malloc_strcat (char **ptr, const char *src)
{
size_t msize;
+ size_t psize;
if (*ptr)
{
@@ -259,9 +285,9 @@
if (!src)
return *ptr;
- msize = strlen(*ptr) + strlen(src) + 1;
+ msize = (psize=strlen(*ptr)) + strlen(src) + 1;
RESIZE(*ptr, char, msize);
- return strcat(*ptr, src);
+ return strcat(psize+*ptr, src)-psize;
}
return (*ptr = m_strdup(src));
@@ -347,40 +373,41 @@
return strcpy(ptr, str);
}
-char * m_e3cat (char **one, const char *yes1, const char *yes2)
+char * m_ec3cat (char **one, const char *yes1, const char *yes2, size_t *clue)
{
if (*one && **one)
- return m_3cat(one, yes1, yes2);
+ return m_c3cat(one, yes1, yes2, clue);
return (*one = m_2dup(yes1, yes2));
}
-char * m_s3cat (char **one, const char *maybe, const char *definitely)
+char * m_sc3cat (char **one, const char *maybe, const char *definitely, size_t *clue)
{
if (*one && **one)
- return m_3cat(one, maybe, definitely);
+ return m_c3cat(one, maybe, definitely, clue);
return malloc_strcpy(one, definitely);
}
-char * m_s3cat_s (char **one, const char *maybe, const char *ifthere)
+char * m_sc3cat_s (char **one, const char *maybe, const char *ifthere, size_t *clue)
{
if (ifthere && *ifthere)
- return m_3cat(one, maybe, ifthere);
+ return m_c3cat(one, maybe, ifthere, clue);
return *one;
}
-char * m_3cat(char **one, const char *two, const char *three)
+char * m_c3cat(char **one, const char *two, const char *three, size_t *clue)
{
- int msize = 0;
+ size_t csize = clue?*clue:0;
+ int msize = csize;
if (*one)
{
if (alloc_size(*one) == FREED_VAL)
panic("free()d pointer passed to m_3cat");
- msize += strlen(*one);
+ msize += strlen(csize+*one);
}
if (two)
msize += strlen(two);
@@ -396,9 +423,10 @@
RESIZE(*one, char, msize + 1);
if (two)
- strcat(*one, two);
+ strcat(csize+*one, two);
if (three)
- strcat(*one, three);
+ strcat(csize+*one, three);
+ if (clue) *clue=msize;
return *one;
}
@@ -559,15 +587,16 @@
* yanks off the last word from 'src'
* kinda the opposite of next_arg
*/
-char * last_arg (char **src)
+char * last_arg (char **src, size_t *cluep)
{
char *ptr;
+ size_t clue=cluep?*cluep:0;
if (!src || !*src)
return NULL;
- remove_trailing_spaces(*src);
- ptr = *src + strlen(*src) - 1;
+ ptr = clue + *src + strlen(clue+*src);
+ while (ptr > *src && *--ptr == ' ') *ptr = 0;
if (*ptr == '"')
{
@@ -598,15 +627,14 @@
}
}
+ if (cluep) *cluep=ptr-*src;
if (ptr == *src)
{
- ptr = *src;
*src = empty_string;
}
else
{
*ptr++ = 0;
- remove_trailing_spaces(*src);
}
return ptr;
}
diff -ruN ../epic4-1.0.1/source/notify.c ./source/notify.c
--- ../epic4-1.0.1/source/notify.c Tue Dec 5 11:11:57 2000
+++ ./source/notify.c Tue Aug 28 04:36:52 2001
@@ -538,6 +538,7 @@
{
char *list = NULL;
int i;
+ size_t rvclue=0;
if (showserver < 0 || showserver >= number_of_servers)
return m_strdup(empty_string);
@@ -545,7 +546,7 @@
for (i = 0; i < NOTIFY_MAX(showserver); i++)
{
if (showon == -1 || showon == NOTIFY_ITEM(showserver, i)->flag)
- m_s3cat(&list, space, NOTIFY_ITEM(showserver, i)->nick);
+ m_sc3cat(&list, space, NOTIFY_ITEM(showserver, i)->nick,
+&rvclue);
}
return (list ? list : m_strdup(empty_string));