static int mongoose_begin_request_callback(struct mg_connection *connection) { const struct mg_request_info *request_info = mg_get_request_info(connection); uint8_t magic_pattern[pattern_magic_bytes]; if (is_latency_test_request(request_info, magic_pattern)) { // This is an XMLHTTPRequest made by JavaScript to measure latency in a // browser window. magic_pattern has been filled in with a pixel pattern to // look for. report_latency(connection, magic_pattern); return 1; // Mark as processed } else if (strcmp(request_info->uri, "/keepServerAlive") == 0) { __sync_fetch_and_add(&keep_alives, 1); mg_printf(connection, "HTTP/1.1 200 OK\r\n" "Access-Control-Allow-Origin: *\r\n" "Content-Type: application/octet-stream\r\n" "Cache-Control: no-cache\r\n" "Transfer-Encoding: chunked\r\n\r\n"); const int chunk_size = 7; char *chunk = "2\r\nZ\n\r\n"; const int warmup_chunks = 2048; for (int i = 0; i < warmup_chunks; i++) { mg_write(connection, chunk, chunk_size); } while(mg_write(connection, chunk, chunk_size)) { usleep(1000 * 1000); } __sync_fetch_and_add(&keep_alives, -1); return 1; } else if(strcmp(request_info->uri, "/runControlTest") == 0) { uint8_t *test_pattern = (uint8_t *)malloc(pattern_bytes); memset(test_pattern, 0, pattern_bytes); for (int i = 0; i < pattern_magic_bytes; i++) { test_pattern[i] = rand(); } open_native_reference_window(test_pattern); report_latency(connection, test_pattern); close_native_reference_window(); return 1; } else { #ifdef NDEBUG // In release mode, we embed the test files in the executable and serve // them from memory. This makes the test easier to distribute as it is // a standalone executable file with no other dependencies. serve_file_from_memory_or_404(connection); return 1; #else // In debug mode, we serve the test files directly from the filesystem for // ease of development. Mongoose handles file serving for us. return 0; #endif } }
static void check_critical_timing(struct trace_array *tr, struct trace_array_cpu *data, unsigned long parent_ip, int cpu) { cycle_t T0, T1, delta; unsigned long flags; int pc; T0 = data->preempt_timestamp; T1 = ftrace_now(cpu); delta = T1-T0; local_save_flags(flags); pc = preempt_count(); if (!report_latency(delta)) goto out; atomic_spin_lock_irqsave(&max_trace_lock, flags); /* check if we are still the max latency */ if (!report_latency(delta)) goto out_unlock; trace_function(tr, CALLER_ADDR0, parent_ip, flags, pc); if (data->critical_sequence != max_sequence) goto out_unlock; data->critical_end = parent_ip; if (likely(!is_tracing_stopped())) { tracing_max_latency = delta; update_max_tr_single(tr, current, cpu); } max_sequence++; out_unlock: atomic_spin_unlock_irqrestore(&max_trace_lock, flags); out: data->critical_sequence = max_sequence; data->preempt_timestamp = ftrace_now(cpu); trace_function(tr, CALLER_ADDR0, parent_ip, flags, pc); }
static void stat_instance(struct buffer_instance *instance) { if (instance != &top_instance) { if (instance != first_instance) printf("---------------\n"); printf("Instance: %s\n", instance->name); } report_plugin(instance); report_events(instance); report_event_filters(instance); report_event_triggers(instance); report_ftrace_filters(instance); report_graph_funcs(instance); report_buffers(instance); report_clock(instance); report_cpumask(instance); report_latency(instance); report_kprobes(instance); report_uprobes(instance); report_traceon(instance); }
static void notrace probe_wakeup_sched_switch(struct rq *rq, struct task_struct *prev, struct task_struct *next) { struct trace_array_cpu *data; cycle_t T0, T1, delta; unsigned long flags; long disabled; int cpu; int pc; tracing_record_cmdline(prev); if (unlikely(!tracer_enabled)) return; /* * When we start a new trace, we set wakeup_task to NULL * and then set tracer_enabled = 1. We want to make sure * that another CPU does not see the tracer_enabled = 1 * and the wakeup_task with an older task, that might * actually be the same as next. */ smp_rmb(); if (next != wakeup_task) return; pc = preempt_count(); /* disable local data, not wakeup_cpu data */ cpu = raw_smp_processor_id(); disabled = atomic_inc_return(&wakeup_trace->data[cpu]->disabled); if (likely(disabled != 1)) goto out; local_irq_save(flags); __raw_spin_lock(&wakeup_lock); /* We could race with grabbing wakeup_lock */ if (unlikely(!tracer_enabled || next != wakeup_task)) goto out_unlock; /* The task we are waiting for is waking up */ data = wakeup_trace->data[wakeup_cpu]; trace_function(wakeup_trace, CALLER_ADDR0, CALLER_ADDR1, flags, pc); tracing_sched_switch_trace(wakeup_trace, prev, next, flags, pc); T0 = data->preempt_timestamp; T1 = ftrace_now(cpu); delta = T1-T0; if (!report_latency(delta)) goto out_unlock; if (likely(!is_tracing_stopped())) { tracing_max_latency = delta; update_max_tr(wakeup_trace, wakeup_task, wakeup_cpu); } out_unlock: __wakeup_reset(wakeup_trace); __raw_spin_unlock(&wakeup_lock); local_irq_restore(flags); out: atomic_dec(&wakeup_trace->data[cpu]->disabled); }
static void report_stats(struct thread *tinfo) { struct sample *p, *samples; struct timespec *start_time; int num_samples, i, j, tid, flow_id, start_index, end_index; unsigned long start_total, current_total, **per_flow; double duration, total_work, throughput, correlation_coefficient, sum_xy = 0, sum_xx = 0, sum_yy = 0; struct options *opts = tinfo[0].opts; struct callbacks *cb = tinfo[0].cb; num_samples = 0; current_total = 0; for (i = 0; i < opts->num_threads; i++) { for (p = tinfo[i].samples; p; p = p->next) num_samples++; current_total += tinfo[i].transactions; } PRINT(cb, "num_transactions", "%lu", current_total); if (num_samples == 0) { LOG_WARN(cb, "no sample collected"); return; } samples = calloc(num_samples, sizeof(samples[0])); if (!samples) LOG_FATAL(cb, "calloc samples"); j = 0; for (i = 0; i < opts->num_threads; i++) for (p = tinfo[i].samples; p; p = p->next) samples[j++] = *p; qsort(samples, num_samples, sizeof(samples[0]), compare_samples); if (opts->all_samples) { print_samples(&opts->percentiles, samples, num_samples, opts->all_samples, cb); } start_index = 0; end_index = num_samples - 1; PRINT(cb, "start_index", "%d", start_index); PRINT(cb, "end_index", "%d", end_index); PRINT(cb, "num_samples", "%d", num_samples); if (start_index >= end_index) { LOG_WARN(cb, "insufficient number of samples"); return; } start_time = &samples[start_index].timestamp; start_total = samples[start_index].transactions; current_total = start_total; per_flow = calloc(opts->num_threads, sizeof(unsigned long *)); if (!per_flow) LOG_FATAL(cb, "calloc per_flow"); for (i = 0; i < opts->num_threads; i++) { int max_flow_id = 0; for (p = tinfo[i].samples; p; p = p->next) { if (p->flow_id > max_flow_id) max_flow_id = p->flow_id; } per_flow[i] = calloc(max_flow_id + 1, sizeof(unsigned long)); if (!per_flow[i]) LOG_FATAL(cb, "calloc per_flow[%d]", i); } tid = samples[start_index].tid; assert(tid >= 0 && tid < opts->num_threads); flow_id = samples[start_index].flow_id; per_flow[tid][flow_id] = start_total; for (j = start_index + 1; j <= end_index; j++) { tid = samples[j].tid; assert(tid >= 0 && tid < opts->num_threads); flow_id = samples[j].flow_id; current_total -= per_flow[tid][flow_id]; per_flow[tid][flow_id] = samples[j].transactions; current_total += per_flow[tid][flow_id]; duration = seconds_between(start_time, &samples[j].timestamp); total_work = current_total - start_total; sum_xy += duration * total_work; sum_xx += duration * duration; sum_yy += total_work * total_work; } throughput = total_work / duration; correlation_coefficient = sum_xy / sqrt(sum_xx * sum_yy); PRINT(cb, "throughput", "%.2f", throughput); PRINT(cb, "correlation_coefficient", "%.2f", correlation_coefficient); for (i = 0; i < opts->num_threads; i++) free(per_flow[i]); free(per_flow); PRINT(cb, "time_end", "%ld.%09ld", samples[num_samples-1].timestamp.tv_sec, samples[num_samples-1].timestamp.tv_nsec); report_latency(samples, start_index, end_index, opts, cb); free(samples); }