lkml.org 
[lkml]   [2023]   [Nov]   [27]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    Subject[PATCH v5 04/50] tools api fs: Switch filename__read_str to use io.h
    From
    filename__read_str has its own string reading code that allocates
    memory before reading into it. The memory allocated is sized at BUFSIZ
    that is 8kb. Most strings are short and so most of this 8kb is
    wasted.

    Refactor io__getline, as io__getdelim, so that the newline character
    can be configurable and ignored in the case of filename__read_str.

    Code like build_caches_for_cpu in perf's header.c will read many
    strings and hold them in a data structure, in this case multiple
    strings per cache level per CPU. Using io.h's io__getline avoids the
    wasted memory as strings are temporarily read into a buffer on the
    stack before being copied to a buffer that grows 128 bytes at a time
    and is never sized larger than the string.

    For a 16 hyperthread system the memory consumption of "perf record
    true" is reduced by 180kb, primarily through saving memory when
    reading the cache information.

    Signed-off-by: Ian Rogers <irogers@google.com>
    ---
    tools/lib/api/fs/fs.c | 56 +++++++++++--------------------------------
    tools/lib/api/io.h | 11 ++++++---
    2 files changed, 22 insertions(+), 45 deletions(-)

    diff --git a/tools/lib/api/fs/fs.c b/tools/lib/api/fs/fs.c
    index 5cb0eeec2c8a..004f2af5504b 100644
    --- a/tools/lib/api/fs/fs.c
    +++ b/tools/lib/api/fs/fs.c
    @@ -16,6 +16,7 @@
    #include <sys/mount.h>

    #include "fs.h"
    +#include "../io.h"
    #include "debug-internal.h"

    #define _STR(x) #x
    @@ -344,53 +345,24 @@ int filename__read_ull(const char *filename, unsigned long long *value)
    return filename__read_ull_base(filename, value, 0);
    }

    -#define STRERR_BUFSIZE 128 /* For the buffer size of strerror_r */
    -
    int filename__read_str(const char *filename, char **buf, size_t *sizep)
    {
    - size_t size = 0, alloc_size = 0;
    - void *bf = NULL, *nbf;
    - int fd, n, err = 0;
    - char sbuf[STRERR_BUFSIZE];
    + struct io io;
    + char bf[128];
    + int err;

    - fd = open(filename, O_RDONLY);
    - if (fd < 0)
    + io.fd = open(filename, O_RDONLY);
    + if (io.fd < 0)
    return -errno;
    -
    - do {
    - if (size == alloc_size) {
    - alloc_size += BUFSIZ;
    - nbf = realloc(bf, alloc_size);
    - if (!nbf) {
    - err = -ENOMEM;
    - break;
    - }
    -
    - bf = nbf;
    - }
    -
    - n = read(fd, bf + size, alloc_size - size);
    - if (n < 0) {
    - if (size) {
    - pr_warn("read failed %d: %s\n", errno,
    - strerror_r(errno, sbuf, sizeof(sbuf)));
    - err = 0;
    - } else
    - err = -errno;
    -
    - break;
    - }
    -
    - size += n;
    - } while (n > 0);
    -
    - if (!err) {
    - *sizep = size;
    - *buf = bf;
    + io__init(&io, io.fd, bf, sizeof(bf));
    + *buf = NULL;
    + err = io__getdelim(&io, buf, sizep, /*delim=*/-1);
    + if (err < 0) {
    + free(*buf);
    + *buf = NULL;
    } else
    - free(bf);
    -
    - close(fd);
    + err = 0;
    + close(io.fd);
    return err;
    }

    diff --git a/tools/lib/api/io.h b/tools/lib/api/io.h
    index a77b74c5fb65..a28157d2ebee 100644
    --- a/tools/lib/api/io.h
    +++ b/tools/lib/api/io.h
    @@ -140,8 +140,8 @@ static inline int io__get_dec(struct io *io, __u64 *dec)
    }
    }

    -/* Read up to and including the first newline following the pattern of getline. */
    -static inline ssize_t io__getline(struct io *io, char **line_out, size_t *line_len_out)
    +/* Read up to and including the first delim. */
    +static inline ssize_t io__getdelim(struct io *io, char **line_out, size_t *line_len_out, int delim)
    {
    char buf[128];
    int buf_pos = 0;
    @@ -151,7 +151,7 @@ static inline ssize_t io__getline(struct io *io, char **line_out, size_t *line_l

    /* TODO: reuse previously allocated memory. */
    free(*line_out);
    - while (ch != '\n') {
    + while (ch != delim) {
    ch = io__get_char(io);

    if (ch < 0)
    @@ -184,4 +184,9 @@ static inline ssize_t io__getline(struct io *io, char **line_out, size_t *line_l
    return -ENOMEM;
    }

    +static inline ssize_t io__getline(struct io *io, char **line_out, size_t *line_len_out)
    +{
    + return io__getdelim(io, line_out, line_len_out, /*delim=*/'\n');
    +}
    +
    #endif /* __API_IO__ */
    --
    2.43.0.rc1.413.gea7ed67945-goog
    \
     
     \ /
      Last update: 2023-11-27 23:10    [W:2.151 / U:0.004 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site