github.com/stealthrocket/wzprof@v0.2.1-0.20230830205924-5fa86be5e5b3/testdata/c/bench.c (about)

     1  #include <stdio.h>
     2  #include <stdlib.h>
     3  #include <string.h>
     4  #include <sys/time.h>
     5  
     6  int64_t now() {
     7    struct timeval tv;
     8    gettimeofday(&tv, NULL);
     9    return ((int64_t)(tv.tv_sec))*1e9 + ((int64_t)(tv.tv_usec))*1e3;
    10  }
    11  
    12  int isAbs(const char *path) {
    13    return *path == '/';
    14  }
    15  
    16  int isDir(const char *path) {
    17    const int n = strlen(path);
    18    return (n > 0) && path[n-1] == '/';
    19  }
    20  
    21  int appendCleanPath(char *buf, int bufLen, const char *path, int *lookupParent) {
    22    while (*path) {
    23      while (*path && *path == '/') {
    24        path++;
    25      }
    26  
    27      const char *ptr = path;
    28      const char *end = path;
    29      while (*end && *end != '/') {
    30        end++;
    31      }
    32      path = end;
    33  
    34      const int len = end - ptr;
    35      if (len == 0) {
    36        continue;
    37      }
    38  
    39      if (len == 1 && ptr[0] == '.') {
    40        continue;
    41      }
    42  
    43      if (len == 2 && ptr[0] == '.' && ptr[1] == '.') {
    44        if (!*lookupParent) {
    45          int k = bufLen;
    46          while (k > 0 && buf[k-1] != '/') {
    47            k--;
    48          }
    49          while (k > 1 && buf[k-1] == '/') {
    50            k--;
    51          }
    52          bufLen = k;
    53          if (k == 0) {
    54            *lookupParent = 1;
    55          } else {
    56            continue;
    57          }
    58        }
    59      } else {
    60        *lookupParent = 0;
    61      }
    62  
    63      if (bufLen > 0 && buf[bufLen-1] != '/') {
    64        buf[bufLen] = '/';
    65        bufLen++;
    66      }
    67      memmove(buf + bufLen, ptr, len);
    68      bufLen += len;
    69    }
    70    return bufLen;
    71  }
    72  
    73  char *joinPath(const char *dir, const char *file) {
    74    int bufSize = strlen(dir) + strlen(file) + 8;
    75    int bufLen = 0;
    76    char *buf = malloc(bufSize);
    77    memset(buf, 0, bufSize);
    78    if (isAbs(dir)) {
    79      buf[0] = '/';
    80      bufLen++;
    81    }
    82    int lookupParent = 0;
    83    bufLen = appendCleanPath(buf, bufLen, dir, &lookupParent);
    84    bufLen = appendCleanPath(buf, bufLen, file, &lookupParent);
    85    if (bufLen == 0) {
    86      buf[0] = '.';
    87      bufLen++;
    88    }
    89    if (buf[bufLen-1] != '/' && isDir(file)) {
    90      buf[bufLen] = '/';
    91    }
    92    return buf;
    93  }
    94  
    95  int main(int argc, char **argv) {
    96    if (argc > 4) {
    97      puts("usage: join [dir] [file]");
    98      return 2;
    99    }
   100  
   101    const char *cmd = "join";
   102    const char *dir = ".";
   103    const char *file = ".";
   104    if (argc > 1) {
   105      cmd = argv[1];
   106    }
   107    if (argc > 2) {
   108      dir = argv[2];
   109    }
   110    if (argc > 3) {
   111      file = argv[3];
   112    }
   113  
   114    if (strcmp(cmd, "join") == 0) {
   115      puts(joinPath(dir, file));
   116    } else if (strcmp(cmd, "test") == 0) {
   117      const int n = atoi(argv[2]);
   118      puts("goos:");
   119      puts("goarch:");
   120      puts("pkg:");
   121  
   122      for (int i = 0; i < n; i++) {
   123        const int64_t start = now();
   124        const int64_t count = 20e6;
   125  
   126        for (int64_t j = 0; j < count; j++) {
   127          free(joinPath(dir, file));
   128        }
   129  
   130        const int64_t end = now();
   131        printf("BenchmarkJoinPath/#00        %lld\t% 10.2f ns/op\n", count, ((double)(end - start))/count);
   132        fflush(stdout);
   133      }
   134  
   135      puts("PASS");
   136    } else {
   137      puts("usage: join|test");
   138      return 2;
   139    }
   140    return 0;
   141  }