]> Sergey Matveev's repositories - nnn.git/commitdiff
Use exact number of bytes for each filename.
authorArun Prakash Jana <engineerarun@gmail.com>
Mon, 18 Dec 2017 19:46:03 +0000 (01:16 +0530)
committerArun Prakash Jana <engineerarun@gmail.com>
Mon, 18 Dec 2017 19:46:03 +0000 (01:16 +0530)
Results in even less memory usage. The names are appended one after another.
The offsets are reset when the location of the memory changes die to realloc().

Other changes:

1. Use a debug mode print to measure time.
2. Remove redundant prefix when printing pointers in debug mode.

nnn.c

diff --git a/nnn.c b/nnn.c
index 4fe5ebbe37b63ad7c4094800d68455f71baf0d27..62fb2f3d3d0c2e1da28ff2ebe3b3d408f7da816c 100644 (file)
--- a/nnn.c
+++ b/nnn.c
@@ -129,7 +129,7 @@ disabledbg()
 #define DPRINTF_D(x) xprintf(DEBUG_FD, #x "=%d\n", x)
 #define DPRINTF_U(x) xprintf(DEBUG_FD, #x "=%u\n", x)
 #define DPRINTF_S(x) xprintf(DEBUG_FD, #x "=%s\n", x)
-#define DPRINTF_P(x) xprintf(DEBUG_FD, #x "=0x%p\n", x)
+#define DPRINTF_P(x) xprintf(DEBUG_FD, #x "=%p\n", x)
 #else
 #define DPRINTF_D(x)
 #define DPRINTF_U(x)
@@ -140,6 +140,7 @@ disabledbg()
 /* Macro definitions */
 #define VERSION "1.5"
 #define GENERAL_INFO "License: BSD 2-Clause\nWebpage: https://github.com/jarun/nnn"
+
 #define LEN(x) (sizeof(x) / sizeof(*(x)))
 #undef MIN
 #define MIN(x, y) ((x) < (y) ? (x) : (y))
@@ -154,6 +155,8 @@ disabledbg()
 #define FILTER '/'
 #define REGEX_MAX 128
 #define BM_MAX 10
+#define ENTRY_INCR 64 /* Number of dir 'entry' structures to allocate per shot */
+#define NAMEBUF_INCR 0x1000 /* 64 dir entries at a time, avg. 64 chars per filename = 64*64B = 4KB */
 
 /* Macros to define process spawn behaviour as flags */
 #define F_NONE     0x00  /* no flag set */
@@ -192,13 +195,10 @@ typedef struct entry {
        time_t t;
        off_t size;
        blkcnt_t blocks; /* number of 512B blocks allocated */
+       size_t noff;
        mode_t mode;
 } *pEntry;
 
-typedef struct {
-       char pname[NAME_MAX + 1];
-} namebuf;
-
 /* Bookmark */
 typedef struct {
        char *key;
@@ -225,7 +225,7 @@ typedef struct {
 static settings cfg = {0, 0, 0, 0, 0, 1, 1, 0, 0, 4};
 
 static struct entry *dents;
-static namebuf *pnamebuf;
+static char *pnamebuf;
 static int ndents, cur, total_dents;
 static uint idle;
 static uint idletimeout;
@@ -1765,12 +1765,14 @@ dentfill(char *path, struct entry **dents,
 {
        static DIR *dirp;
        static struct dirent *dp;
-       static struct stat sb_path, sb;
-       static int fd, n, count;
-       static char *namep;
-       static ulong num_saved;
+       static char *namep, *pnb;
        static struct entry *dentp;
-       static namebuf *pnb;
+       static size_t off, namebuflen = NAMEBUF_INCR;
+       static ulong num_saved;
+       static int fd, n, count;
+       static struct stat sb_path, sb;
+
+       off = 0;
 
        dirp = opendir(path);
        if (dirp == NULL)
@@ -1836,28 +1838,41 @@ dentfill(char *path, struct entry **dents,
                }
 
                if (n == total_dents) {
-                       total_dents += 64;
+                       total_dents += ENTRY_INCR;
                        *dents = realloc(*dents, total_dents * sizeof(**dents));
-                       if (*dents == NULL)
+                       if (*dents == NULL) {
+                               if (pnamebuf)
+                                       free(pnamebuf);
                                errexit();
+                       }
+               }
+
+               /* If there's not enough bytes left to copy a file name of length NAME_MAX, re-allocate */
+               if (namebuflen - off < NAME_MAX + 1) {
+                       namebuflen += NAMEBUF_INCR;
 
                        pnb = pnamebuf;
-                       pnamebuf = (namebuf *)realloc(pnamebuf, total_dents * sizeof(namebuf));
+                       pnamebuf = (char *)realloc(pnamebuf, namebuflen);
+                       DPRINTF_P(pnamebuf);
                        if (pnamebuf == NULL) {
                                free(*dents);
                                errexit();
                        }
 
                        /* realloc() may result in memory move, we must re-adjust if that happens */
-                       if (pnb && pnb != pnamebuf)
+                       if (pnb != pnamebuf)
                                for (count = 0; count < n; ++count)
-                                       (&(*dents)[count])->name = pnamebuf[count].pname;
+                                       (*dents + count)->name = pnamebuf + (*dents + count)->noff;
                }
 
-               dentp = &(*dents)[n];
-               xstrlcpy(pnamebuf[n].pname, namep, NAME_MAX + 1);
-               dentp->name = pnamebuf[n].pname;
+               dentp = *dents + n;
+
+               /* Copy file name */
+               dentp->name = pnamebuf + off;
+               dentp->noff = off;
+               off += xstrlcpy(dentp->name, namep, NAME_MAX + 1);
 
+               /* Copy other fields */
                dentp->mode = sb.st_mode;
                dentp->t = sb.st_mtime;
                dentp->size = sb.st_size;
@@ -1947,10 +1962,20 @@ populate(char *path, char *oldpath, char *fltr)
                refresh();
        }
 
+#ifdef DEBUGMODE
+       struct timespec ts1, ts2;
+       clock_gettime(CLOCK_REALTIME, &ts1); /* Use CLOCK_MONOTONIC on FreeBSD */
+#endif
+
        ndents = dentfill(path, &dents, visible, &re);
 
        qsort(dents, ndents, sizeof(*dents), entrycmp);
 
+#ifdef DEBUGMODE
+       clock_gettime(CLOCK_REALTIME, &ts2);
+       DPRINTF_U(ts2.tv_nsec - ts1.tv_nsec);
+#endif
+
        /* Find cur from history */
        cur = dentfind(dents, ndents, oldpath);
        return 0;
@@ -2103,6 +2128,11 @@ browse(char *ipath, char *ifilter)
        else
                presel = 0;
 
+       /* Allocate buffer to hold names */
+       pnamebuf = (char *)malloc(NAMEBUF_INCR);
+       if (pnamebuf == NULL)
+               errexit();
+
 begin:
 #ifdef LINUX_INOTIFY
        if (dir_changed && inotify_wd >= 0) {