Home | History | Annotate | Line # | Download | only in programs
      1 /*
      2  * Copyright (c) Meta Platforms, Inc. and affiliates.
      3  * All rights reserved.
      4  *
      5  * This source code is licensed under both the BSD-style license (found in the
      6  * LICENSE file in the root directory of this source tree) and the GPLv2 (found
      7  * in the COPYING file in the root directory of this source tree).
      8  * You may select, at your option, one of the above-listed licenses.
      9  */
     10 
     11 #include "zstdcli_trace.h"
     12 
     13 #include <stdio.h>
     14 #include <stdlib.h>
     15 
     16 #include "timefn.h"
     17 #include "util.h"
     18 
     19 #define ZSTD_STATIC_LINKING_ONLY
     20 #include "../lib/zstd.h"
     21 /* We depend on the trace header to avoid duplicating the ZSTD_trace struct.
     22  * But, we check the version so it is compatible with dynamic linking.
     23  */
     24 #include "../lib/common/zstd_trace.h"
     25 /* We only use macros from threading.h so it is compatible with dynamic linking */
     26 #include "../lib/common/threading.h"
     27 
     28 #if ZSTD_TRACE
     29 
     30 static FILE* g_traceFile = NULL;
     31 static int g_mutexInit = 0;
     32 static ZSTD_pthread_mutex_t g_mutex;
     33 static UTIL_time_t g_enableTime = UTIL_TIME_INITIALIZER;
     34 
     35 void TRACE_enable(char const* filename)
     36 {
     37     int const writeHeader = !UTIL_isRegularFile(filename);
     38     if (g_traceFile)
     39         fclose(g_traceFile);
     40     g_traceFile = fopen(filename, "a");
     41     if (g_traceFile && writeHeader) {
     42         /* Fields:
     43         * algorithm
     44         * version
     45         * method
     46         * streaming
     47         * level
     48         * workers
     49         * dictionary size
     50         * uncompressed size
     51         * compressed size
     52         * duration nanos
     53         * compression ratio
     54         * speed MB/s
     55         */
     56         fprintf(g_traceFile, "Algorithm, Version, Method, Mode, Level, Workers, Dictionary Size, Uncompressed Size, Compressed Size, Duration Nanos, Compression Ratio, Speed MB/s\n");
     57     }
     58     g_enableTime = UTIL_getTime();
     59     if (!g_mutexInit) {
     60         if (!ZSTD_pthread_mutex_init(&g_mutex, NULL)) {
     61             g_mutexInit = 1;
     62         } else {
     63             TRACE_finish();
     64         }
     65     }
     66 }
     67 
     68 void TRACE_finish(void)
     69 {
     70     if (g_traceFile) {
     71         fclose(g_traceFile);
     72     }
     73     g_traceFile = NULL;
     74     if (g_mutexInit) {
     75         ZSTD_pthread_mutex_destroy(&g_mutex);
     76         g_mutexInit = 0;
     77     }
     78 }
     79 
     80 static void TRACE_log(char const* method, PTime duration, ZSTD_Trace const* trace)
     81 {
     82     int level = 0;
     83     int workers = 0;
     84     double const ratio = (double)trace->uncompressedSize / (double)trace->compressedSize;
     85     double const speed = ((double)trace->uncompressedSize * 1000) / (double)duration;
     86     if (trace->params) {
     87         ZSTD_CCtxParams_getParameter(trace->params, ZSTD_c_compressionLevel, &level);
     88         ZSTD_CCtxParams_getParameter(trace->params, ZSTD_c_nbWorkers, &workers);
     89     }
     90     assert(g_traceFile != NULL);
     91 
     92     ZSTD_pthread_mutex_lock(&g_mutex);
     93     /* Fields:
     94      * algorithm
     95      * version
     96      * method
     97      * streaming
     98      * level
     99      * workers
    100      * dictionary size
    101      * uncompressed size
    102      * compressed size
    103      * duration nanos
    104      * compression ratio
    105      * speed MB/s
    106      */
    107     fprintf(g_traceFile,
    108         "zstd, %u, %s, %s, %d, %d, %llu, %llu, %llu, %llu, %.2f, %.2f\n",
    109         trace->version,
    110         method,
    111         trace->streaming ? "streaming" : "single-pass",
    112         level,
    113         workers,
    114         (unsigned long long)trace->dictionarySize,
    115         (unsigned long long)trace->uncompressedSize,
    116         (unsigned long long)trace->compressedSize,
    117         (unsigned long long)duration,
    118         ratio,
    119         speed);
    120     ZSTD_pthread_mutex_unlock(&g_mutex);
    121 }
    122 
    123 /**
    124  * These symbols override the weak symbols provided by the library.
    125  */
    126 
    127 ZSTD_TraceCtx ZSTD_trace_compress_begin(ZSTD_CCtx const* cctx)
    128 {
    129     (void)cctx;
    130     if (g_traceFile == NULL)
    131         return 0;
    132     return (ZSTD_TraceCtx)UTIL_clockSpanNano(g_enableTime);
    133 }
    134 
    135 void ZSTD_trace_compress_end(ZSTD_TraceCtx ctx, ZSTD_Trace const* trace)
    136 {
    137     PTime const beginNanos = (PTime)ctx;
    138     PTime const endNanos = UTIL_clockSpanNano(g_enableTime);
    139     PTime const durationNanos = endNanos > beginNanos ? endNanos - beginNanos : 0;
    140     assert(g_traceFile != NULL);
    141     assert(trace->version == ZSTD_VERSION_NUMBER); /* CLI version must match. */
    142     TRACE_log("compress", durationNanos, trace);
    143 }
    144 
    145 ZSTD_TraceCtx ZSTD_trace_decompress_begin(ZSTD_DCtx const* dctx)
    146 {
    147     (void)dctx;
    148     if (g_traceFile == NULL)
    149         return 0;
    150     return (ZSTD_TraceCtx)UTIL_clockSpanNano(g_enableTime);
    151 }
    152 
    153 void ZSTD_trace_decompress_end(ZSTD_TraceCtx ctx, ZSTD_Trace const* trace)
    154 {
    155     PTime const beginNanos = (PTime)ctx;
    156     PTime const endNanos = UTIL_clockSpanNano(g_enableTime);
    157     PTime const durationNanos = endNanos > beginNanos ? endNanos - beginNanos : 0;
    158     assert(g_traceFile != NULL);
    159     assert(trace->version == ZSTD_VERSION_NUMBER); /* CLI version must match. */
    160     TRACE_log("decompress", durationNanos, trace);
    161 }
    162 
    163 #else /* ZSTD_TRACE */
    164 
    165 void TRACE_enable(char const* filename)
    166 {
    167     (void)filename;
    168 }
    169 
    170 void TRACE_finish(void) {}
    171 
    172 #endif /* ZSTD_TRACE */
    173