static gboolean get_all_clocks(struct mcap_mcl *mcl, uint32_t *btclock, struct timespec *base_time, uint64_t *timestamp) { int latency; int retry = 5; uint16_t btres; struct timespec t0; if (!caps(mcl)) return FALSE; latency = caps(mcl)->preempt_thresh + 1; while (latency > caps(mcl)->preempt_thresh && --retry >= 0) { clock_gettime(CLK, &t0); if (!read_btclock(mcl, btclock, &btres)) continue; clock_gettime(CLK, base_time); /* Tries to detect preemption between clock_gettime * and read_btclock by measuring transaction time */ latency = time_us(base_time) - time_us(&t0); } *timestamp = mcap_get_timestamp(mcl, base_time); return TRUE; }
static int calibrate(aeEventLoop *loop, long long id, void *data) { thread *thread = data; uint64_t elapsed_ms = (time_us() - thread->start) / 1000; uint64_t req_per_ms = thread->requests / elapsed_ms; if (!req_per_ms) return CALIBRATE_DELAY_MS / 2; thread->rate = (req_per_ms * SAMPLE_INTERVAL_MS) / 10; thread->start = time_us(); thread->requests = 0; stats_reset(thread->latency); aeCreateTimeEvent(loop, SAMPLE_INTERVAL_MS, sample_rate, thread, NULL); return AE_NOMORE; }
uint64_t mcap_get_timestamp(struct mcap_mcl *mcl, struct timespec *given_time) { struct timespec now; uint64_t tmstamp; if (!mcl->csp) return MCAP_TMSTAMP_DONTSET; if (given_time) now = *given_time; else clock_gettime(CLK, &now); tmstamp = time_us(&now) - time_us(&mcl->csp->base_time) + mcl->csp->base_tmstamp; return tmstamp; }
void print_at(uint8_t x, uint8_t y, uint8_t channel){ char buff[17]; buff[16]=0; uint64_t threshold=1000000ULL; //1s LCD_goto(x,y); LCD_putc(time_us()-last_updated_at[channel]<threshold ? 'v' : 'x'); LCD_puts(itoa((int)channels[channel],buff,10)); LCD_putc(' '); LCD_putc(' '); }
void midiMainLoop(void) { fprintf (stderr, "midiMainLoop\n"); jack_midi_event_t input_event; int timeout = 10*1000*1000+time_us(); // 10 seconds in microseconds //int exitMainLoop = 0; while (!exitMainLoop) { jack_nframes_t nframes = jack_cycle_wait(jack_client); /* Get input and output buffer pointers. */ void* input_buf = jack_port_get_buffer (jack_midi_input_port, nframes); //void* output_buf = jack_port_get_buffer (jack_midi_output_port, nframes); jack_nframes_t input_event_count = jack_midi_get_event_count(input_buf); if (input_event_count>0) { unsigned int event_index = 0; for (;event_index<input_event_count;event_index++) { if (0==jack_midi_event_get(&input_event, input_buf, event_index)) { if (input_event.size > 0) { printhex("receive:", input_event.buffer,input_event.size); int i = 0; for (; i < input_event.size; i++) { midiReceive(input_event.buffer[i]); } } } } } if (time_us() > timeout) { fprintf(stderr, "timeout\n"); exit(1); } } jack_end(); fprintf (stderr, "midiMainLoop:end\n"); }
static void socket_writeable(aeEventLoop *loop, int fd, void *data, int mask) { connection *c = data; if (write(fd, c->hash, SHA_LENGTH * 2) < SHA_LENGTH * 2) goto error; c->start = time_us(); aeDeleteFileEvent(loop, fd, AE_WRITABLE); return; error: c->thread->errors.write++; reconnect_socket(c->thread, c); }
static int sample_rate(aeEventLoop *loop, long long id, void *data) { thread *thread = data; uint64_t elapsed_ms = (time_us() - thread->start) / 1000; uint64_t requests = (thread->requests / elapsed_ms) * 1000; uint64_t missed = thread->rate - MIN(thread->rate, thread->latency->limit); uint64_t count = thread->rate - missed; pthread_mutex_lock(&statistics.mutex); stats_sample(statistics.latency, &thread->rand, count, thread->latency); stats_record(statistics.requests, requests); pthread_mutex_unlock(&statistics.mutex); uint64_t max = thread->latency->max; thread->missed += missed; thread->requests = 0; thread->start = time_us(); stats_reset(thread->latency); thread->latency->max = max; return SAMPLE_INTERVAL_MS; }
static int check_timeouts(aeEventLoop *loop, long long id, void *data) { thread *thread = data; connection *c = thread->cs; uint64_t now = time_us(); uint64_t maxAge = now - (cfg.timeout * 1000); for (uint64_t i = 0; i < thread->connections; i++, c++) { if (maxAge > c->start) { thread->errors.timeout++; } } if (stop || now >= thread->stop_at) { aeStop(loop); } return TIMEOUT_INTERVAL_MS; }
static void socket_readable(aeEventLoop *loop, int fd, void *data, int mask) { connection *c = data; thread *thread = c->thread; uint64_t now; ssize_t n; if ((n = read(fd, c->buf, sizeof(c->buf))) <= 0) goto error; c->buf[n] = '\0'; now = time_us(); if (!validate_response(c)) goto invalid; thread->bytes += n; thread->complete++; thread->requests++; stats_record(thread->latency, now - c->start); if (now >= thread->stop_at) { aeStop(thread->loop); close(c->fd); } else { reconnect_socket(c->thread, c); } return; invalid: c->thread->errors.validate++; reconnect_socket(c->thread, c); return; error: c->thread->errors.read++; reconnect_socket(c->thread, c); }
static gboolean initialize_caps(struct mcap_mcl *mcl) { struct timespec t1, t2; int latencies[SAMPLE_COUNT]; int latency, avg, dev; uint32_t btclock; uint16_t btaccuracy; int i; int retries; clock_getres(CLK, &t1); _caps.ts_res = time_us(&t1); if (_caps.ts_res < 1) _caps.ts_res = 1; _caps.ts_acc = 20; /* ppm, estimated */ /* A little exercise before measuing latency */ clock_gettime(CLK, &t1); read_btclock_retry(mcl, &btclock, &btaccuracy); /* Read clock a number of times and measure latency */ avg = 0; i = 0; retries = MAX_RETRIES; while (i < SAMPLE_COUNT && retries > 0) { clock_gettime(CLK, &t1); if (!read_btclock(mcl, &btclock, &btaccuracy)) { retries--; continue; } clock_gettime(CLK, &t2); latency = time_us(&t2) - time_us(&t1); latencies[i] = latency; avg += latency; i++; } if (retries <= 0) return FALSE; /* Calculate average and deviation */ avg /= SAMPLE_COUNT; dev = 0; for (i = 0; i < SAMPLE_COUNT; ++i) dev += abs(latencies[i] - avg); dev /= SAMPLE_COUNT; /* Calculate corrected average, without 'freak' latencies */ latency = 0; for (i = 0; i < SAMPLE_COUNT; ++i) { if (latencies[i] > (avg + dev * 6)) latency += avg; else latency += latencies[i]; } latency /= SAMPLE_COUNT; _caps.latency = latency; _caps.preempt_thresh = latency * 4; _caps.syncleadtime_ms = latency * 50 / 1000; csp_caps_initialized = TRUE; return TRUE; }
int main(int argc, char **argv) { struct addrinfo *addrs, *addr; char *host = "127.0.0.1"; char *port = "1337"; int rc; // for checking that the server's up char poke[SHA_LENGTH * 2]; tinymt64_t rando; if (parse_args(&cfg, &host, &port, argc, argv)) { usage(); exit(1); } struct addrinfo hints = { .ai_family = AF_UNSPEC, .ai_socktype = SOCK_STREAM }; if ((rc = getaddrinfo(host, port, &hints, &addrs)) != 0) { const char *msg = gai_strerror(rc); fprintf(stderr, "unable to resolve %s:%s: %s\n", host, port, msg); exit(1); } for (addr = addrs; addr != NULL; addr = addr->ai_next) { int fd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); if (fd == -1) continue; rc = connect(fd, addr->ai_addr, addr->ai_addrlen); tinymt64_init(&rando, time_us()); random_hash(&rando, poke); if (rc == 0 && write(fd, poke, SHA_LENGTH * 2) == SHA_LENGTH * 2) { read(fd, poke, SHA_LENGTH * 2); close(fd); break; } close(fd); } if (addr == NULL) { char *msg = strerror(errno); fprintf(stderr, "unable to connect to %s:%s: %s\n", host, port, msg); exit(1); } signal(SIGPIPE, SIG_IGN); signal(SIGINT, SIG_IGN); cfg.addr = *addr; pthread_mutex_init(&statistics.mutex, NULL); statistics.latency = stats_alloc(SAMPLES); statistics.requests = stats_alloc(SAMPLES); thread *threads = zcalloc(cfg.threads * sizeof(thread)); uint64_t connections = cfg.connections / cfg.threads; uint64_t stop_at = time_us() + (cfg.duration * 1000000); for (uint64_t i = 0; i < cfg.threads; i++) { thread *t = &threads[i]; t->connections = connections; t->stop_at = stop_at; if (pthread_create(&t->thread, NULL, &thread_main, t)) { char *msg = strerror(errno); fprintf(stderr, "unable to create thread %"PRIu64" %s\n", i, msg); exit(2); } } struct sigaction sa = { .sa_handler = handler, .sa_flags = 0, }; sigfillset(&sa.sa_mask); sigaction(SIGINT, &sa, NULL); char *time = format_time_s(cfg.duration); printf("Running %s test @ %s:%s\n", time, host, port); printf(" %"PRIu64" threads and %"PRIu64" connections\n", cfg.threads, cfg.connections); uint64_t start = time_us(); uint64_t complete = 0; uint64_t bytes = 0; errors errors = { 0 }; for (uint64_t i = 0; i < cfg.threads; i++) { thread *t = &threads[i]; pthread_join(t->thread, NULL); complete += t->complete; bytes += t->bytes; errors.connect += t->errors.connect; errors.handshake += t->errors.handshake; errors.read += t->errors.read; errors.validate += t->errors.validate; errors.write += t->errors.write; errors.timeout += t->errors.timeout; } uint64_t runtime_us = time_us() - start; long double runtime_s = runtime_us / 1000000.0; long double req_per_s = complete / runtime_s; long double bytes_per_s = bytes / runtime_s; print_stats_header(); print_stats("Latency", statistics.latency, format_time_us); print_stats("Req/Sec", statistics.requests, format_metric); if (cfg.latency) print_stats_latency(statistics.latency); char *runtime_msg = format_time_us(runtime_us); printf(" %"PRIu64" requests in %s, %sB read\n", complete, runtime_msg, format_binary(bytes)); if (errors.connect || errors.read || errors.write || errors.timeout) { printf(" Socket errors: connect %d, read %d, write %d, timeout %d\n", errors.connect, errors.read, errors.write, errors.timeout); } if (errors.handshake) { printf(" Bad handshakes from server: %d\n", errors.handshake); } if (errors.validate) { printf(" %d proofs failed verification.\n", errors.validate); } printf("Requests/sec: %9.2Lf\n", req_per_s); printf("Transfer/sec: %10sB\n", format_binary(bytes_per_s)); return 0; } void *thread_main(void *arg) { thread *thread = arg; aeEventLoop *loop = aeCreateEventLoop(10 + cfg.connections * 3); thread->cs = zmalloc(thread->connections * sizeof(connection)); thread->loop = loop; tinymt64_init(&thread->rand, time_us()); thread->latency = stats_alloc(100000); connection *c = thread->cs; for (uint64_t i = 0; i < thread->connections; i++, c++) { c->thread = thread; random_hash(&thread->rand, c->hash); connect_socket(thread, c); } aeCreateTimeEvent(loop, CALIBRATE_DELAY_MS, calibrate, thread, NULL); aeCreateTimeEvent(loop, TIMEOUT_INTERVAL_MS, check_timeouts, thread, NULL); thread->start = time_us(); aeMain(loop); aeDeleteEventLoop(loop); zfree(thread->cs); uint64_t max = thread->latency->max; stats_free(thread->latency); pthread_mutex_lock(&statistics.mutex); for (uint64_t i = 0; i < thread->missed; i++) { stats_record(statistics.latency, max); } pthread_mutex_unlock(&statistics.mutex); return NULL; }