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