zstdcli_trace.c 4.8 KB

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