| 131 | } |
| 132 | |
| 133 | void cbm_scale_end(cbm_scale_probe_t *probe) { |
| 134 | if (!probe || probe->total < SCALE_MIN_ITEMS) { |
| 135 | return; |
| 136 | } |
| 137 | int recorded = atomic_load_explicit(&probe->next_cp, memory_order_relaxed); |
| 138 | if (recorded < 2) { |
| 139 | return; /* need two points to speak about growth at all */ |
| 140 | } |
| 141 | long first_us = probe->cp_us[0]; |
| 142 | long first_n = probe->cp_items[0]; |
| 143 | long last_us = probe->cp_us[recorded - 1]; |
| 144 | long last_n = probe->cp_items[recorded - 1]; |
| 145 | if (first_us < SCALE_MIN_FIRST_US || first_n <= 0 || last_n <= first_n || last_us <= 0) { |
| 146 | return; |
| 147 | } |
| 148 | |
| 149 | double k = cbm_scale_fit_k(first_n, first_us, last_n, last_us); |
| 150 | if (k < 0.0) { |
| 151 | return; |
| 152 | } |
| 153 | long us_per_item = last_us / last_n; |
| 154 | |
| 155 | char k_buf[PROF_BUF_LEN]; |
| 156 | char n_buf[PROF_BUF_LEN]; |
| 157 | char per_buf[PROF_BUF_LEN]; |
| 158 | char ms_buf[PROF_BUF_LEN]; |
| 159 | snprintf(k_buf, sizeof(k_buf), "%.2f", k); |
| 160 | snprintf(n_buf, sizeof(n_buf), "%ld", last_n); |
| 161 | snprintf(per_buf, sizeof(per_buf), "%ld", us_per_item); |
| 162 | snprintf(ms_buf, sizeof(ms_buf), "%ld", last_us / PROF_US_PER_MS); |
| 163 | |
| 164 | if (k >= CBM_SCALE_WARN_K) { |
| 165 | /* Unflagged on purpose: this is the alarm the next accidental O(n^2) |
| 166 | * should trip in an ordinary user's log. */ |
| 167 | cbm_log_warn("scaling.superlinear", "phase", probe->phase, "k", k_buf, "items", n_buf, |
| 168 | "elapsed_ms", ms_buf, "us_per_item", per_buf); |
| 169 | } |
| 170 | if (!cbm_profile_active) { |
| 171 | return; |
| 172 | } |
| 173 | char curve[PROF_BUF_LEN * CBM_SCALE_CHECKPOINTS]; |
| 174 | int used = 0; |
| 175 | for (int i = 0; i < recorded && used < (int)sizeof(curve) - 1; i++) { |
| 176 | int wrote = |
| 177 | snprintf(curve + used, sizeof(curve) - (size_t)used, "%s%ld:%ld", i == 0 ? "" : ",", |
| 178 | probe->cp_items[i], probe->cp_us[i] / PROF_US_PER_MS); |
| 179 | if (wrote < 0) { |
| 180 | break; |
| 181 | } |
| 182 | used += wrote; |
| 183 | } |
| 184 | cbm_log_info("scaling", "phase", probe->phase, "k", k_buf, "items", n_buf, "elapsed_ms", ms_buf, |
| 185 | "us_per_item", per_buf, "curve_items_ms", curve); |
| 186 | } |
no test coverage detected