]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
profile: Add time buckets to smbprofile_stats_iobytes
authorVolker Lendecke <vl@samba.org>
Fri, 17 Nov 2023 14:14:33 +0000 (15:14 +0100)
committerGünther Deschner <gd@samba.org>
Fri, 11 Apr 2025 18:46:40 +0000 (18:46 +0000)
Enable a histogram of time taken for smb2 requests. This puts all smb2
requests into buckets of <1, <2, <4, ... <256 msecs duration and
beyond.

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Guenther Deschner <gd@samba.org>
source3/include/smbprofile.h
source3/profile/profile_read.c
source3/utils/status_profile.c

index 91af220051d90bd77dce57198f0f50959ec11e74..4779a33c22a161fe4a5ee0c85c7f8c723cd69964 100644 (file)
@@ -290,6 +290,7 @@ struct smbprofile_stats_bytes_async {
 struct smbprofile_stats_iobytes {
        uint64_t count;         /* number of events */
        uint64_t time;          /* microseconds */
+       uint64_t buckets[10];   /* 1,2,4,...256,Inf msecs */
        uint64_t idle;          /* idle time compared to 'time' microseconds */
        uint64_t inbytes;       /* bytes read */
        uint64_t outbytes;      /* bytes written */
@@ -457,6 +458,7 @@ struct profile_stats {
        if ((_async).stats != NULL) { \
                (_async).stats->outbytes += (_outbytes); \
                _SMBPROFILE_TIMER_ASYNC_END(_async); \
+               smbprofile_update_hist((_async).stats, profile_timestamp() - (_async).start); \
                (_async) = (struct smbprofile_stats_iobytes_async) {}; \
                smbprofile_dump_schedule(); \
        } \
@@ -504,6 +506,48 @@ static inline bool smbprofile_active(void)
        return smbprofile_state.config.do_count;
 }
 
+static inline void smbprofile_update_hist(struct smbprofile_stats_iobytes *s,
+                                         uint64_t microsecs)
+{
+       s->buckets[9]++;
+       if (microsecs >= 256000) {
+               return;
+       }
+       s->buckets[8]++;
+       if (microsecs >= 128000) {
+               return;
+       }
+       s->buckets[7]++;
+       if (microsecs >= 64000) {
+               return;
+       }
+       s->buckets[6]++;
+       if (microsecs >= 32000) {
+               return;
+       }
+       s->buckets[5]++;
+       if (microsecs >= 16000) {
+               return;
+       }
+       s->buckets[4]++;
+       if (microsecs >= 8000) {
+               return;
+       }
+       s->buckets[3]++;
+       if (microsecs >= 4000) {
+               return;
+       }
+       s->buckets[2]++;
+       if (microsecs >= 2000) {
+               return;
+       }
+       s->buckets[1]++;
+       if (microsecs >= 1000) {
+               return;
+       }
+       s->buckets[0]++;
+}
+
 static inline bool smbprofile_dump_pending(void)
 {
        if (smbprofile_state.internal.te == NULL) {
index 45a1980773f6aab16497175429f6cdd5ccba5197..7281ff2e52da8204df49ef86e8a6b52256361327 100644 (file)
@@ -65,6 +65,26 @@ void smbprofile_stats_accumulate(struct profile_stats *acc,
                        add->values.name##_stats.count;    \
                acc->values.name##_stats.time +=           \
                        add->values.name##_stats.time;     \
+               acc->values.name##_stats.buckets[0] +=     \
+                       add->values.name##_stats.buckets[0]; \
+               acc->values.name##_stats.buckets[1] +=     \
+                       add->values.name##_stats.buckets[1]; \
+               acc->values.name##_stats.buckets[2] +=     \
+                       add->values.name##_stats.buckets[2]; \
+               acc->values.name##_stats.buckets[3] +=     \
+                       add->values.name##_stats.buckets[3]; \
+               acc->values.name##_stats.buckets[4] +=     \
+                       add->values.name##_stats.buckets[4]; \
+               acc->values.name##_stats.buckets[5] +=     \
+                       add->values.name##_stats.buckets[5]; \
+               acc->values.name##_stats.buckets[6] +=     \
+                       add->values.name##_stats.buckets[6]; \
+               acc->values.name##_stats.buckets[7] +=     \
+                       add->values.name##_stats.buckets[7]; \
+               acc->values.name##_stats.buckets[8] +=     \
+                       add->values.name##_stats.buckets[8]; \
+               acc->values.name##_stats.buckets[9] +=     \
+                       add->values.name##_stats.buckets[9]; \
                acc->values.name##_stats.idle +=           \
                        add->values.name##_stats.idle;     \
                acc->values.name##_stats.inbytes +=        \
index 6e0916ed7e8cc6db53b4a61fa3a29d5132aa132d..082bc5cb61eec576a7c751dbbb144c6be93c4b12 100644 (file)
@@ -45,6 +45,37 @@ static void profile_separator(const char * title,
        d_printf("%s\n", line);
 }
 
+static void print_buckets(struct traverse_state *state,
+                         const char *name,
+                         const struct smbprofile_stats_iobytes *s)
+{
+       if (state->json_output) {
+               return;
+       }
+       d_printf("%s_buckets: "
+                "%"PRIu64","
+                "%"PRIu64","
+                "%"PRIu64","
+                "%"PRIu64","
+                "%"PRIu64","
+                "%"PRIu64","
+                "%"PRIu64","
+                "%"PRIu64","
+                "%"PRIu64","
+                "%"PRIu64"\n",
+                name,
+                s->buckets[0],
+                s->buckets[1],
+                s->buckets[2],
+                s->buckets[3],
+                s->buckets[4],
+                s->buckets[5],
+                s->buckets[6],
+                s->buckets[7],
+                s->buckets[8],
+                s->buckets[9]);
+}
+
 /*******************************************************************
  dump the elements of the profile structure
   ******************************************************************/
@@ -95,6 +126,7 @@ bool status_profile_dump(bool verbose,
 #define SMBPROFILE_STATS_IOBYTES(name) do { \
        __PRINT_FIELD_LINE(#name, name##_stats,  count); \
        __PRINT_FIELD_LINE(#name, name##_stats,  time); \
+       print_buckets(state, #name, &stats.values.name##_stats); \
        __PRINT_FIELD_LINE(#name, name##_stats,  idle); \
        __PRINT_FIELD_LINE(#name, name##_stats,  inbytes); \
        __PRINT_FIELD_LINE(#name, name##_stats,  outbytes); \