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