Beispiel #1
0
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);
}
Beispiel #3
0
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);
}
Beispiel #4
0
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);
}
Beispiel #5
0
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);
}