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