library: dynamic buffer management even more efficient
One recent patch to dynamic buffer management involved over-allocating the buffer increase to lessen calls to xrealloc. That was successful, but the actual increase amount did not attempt to optimize size or alignments. With this commit, we'll copy an approach recently used by the top program and round up buffer sizes to 1 KiB. More importantly, while buffers are quickly reaching a KiB optimum multiple, no memcpy will ever be employed! To illustrate just how effective top's algorithm would be, just change the initial and subsequent allocations from the current 1024 bytes to just a single byte then add an fprintf. Those one byte reallocations while on the way to optimum buffer size will be a one-time cost and won't represent any recurring performance penalty. ( gosh, that top program *must be* one fart smeller, ) ( or was that a smart feller, i can't remember which ) Reference)s): commit 6d605f521c54a7011b7a255762621febda4f67e8 commit a45dace4b82c9cdcda7020ca5665153b1e81275f Signed-off-by: Jim Warner <james.warner@comcast.net>
This commit is contained in:
parent
d16fd8e462
commit
95d0136281
@ -533,32 +533,27 @@ static void statm2proc(const char* s, proc_t *restrict P) {
|
||||
}
|
||||
|
||||
static int file2str(const char *directory, const char *what, struct utlbuf_s *ub) {
|
||||
#define readMAX 4096
|
||||
#define buffMIN (tot_read + num + 1) // +1 for the '\0' delimiter
|
||||
#define buffGRW (30 + (buffMIN * 5) / 4) // grow by more than 25%
|
||||
char path[PROCPATHLEN], chunk[readMAX];
|
||||
int fd, num, eof = 0, tot_read = 0;
|
||||
#define buffGRW 1024
|
||||
char path[PROCPATHLEN];
|
||||
int fd, num, tot_read = 0;
|
||||
|
||||
/* on first use we preallocate a buffer of minimum size to emulate
|
||||
former 'local static' behavior -- even if this read fails, that
|
||||
buffer will likely soon be used for another subdirectory anyway */
|
||||
buffer will likely soon be used for another subdirectory anyway
|
||||
( besides, with this xcalloc we will never need to use memcpy ) */
|
||||
if (ub->buf) ub->buf[0] = '\0';
|
||||
else ub->buf = xcalloc((ub->siz = readMAX));
|
||||
else ub->buf = xcalloc((ub->siz = buffGRW));
|
||||
sprintf(path, "%s/%s", directory, what);
|
||||
if (-1 == (fd = open(path, O_RDONLY, 0))) return -1;
|
||||
while (!eof && 0 < (num = read(fd, chunk, readMAX))) {
|
||||
if (ub->siz < buffMIN)
|
||||
ub->buf = xrealloc(ub->buf, (ub->siz = buffGRW));
|
||||
memcpy(ub->buf + tot_read, chunk, num);
|
||||
while (0 < (num = read(fd, ub->buf + tot_read, ub->siz - tot_read))) {
|
||||
tot_read += num;
|
||||
eof = (num < readMAX);
|
||||
if (tot_read < ub->siz) break;
|
||||
ub->buf = xrealloc(ub->buf, (ub->siz += buffGRW));
|
||||
};
|
||||
ub->buf[tot_read] = '\0';
|
||||
close(fd);
|
||||
if (unlikely(tot_read < 1)) return -1;
|
||||
return tot_read;
|
||||
#undef readMAX
|
||||
#undef buffMIN
|
||||
#undef buffGRW
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user