int main(int argc, char **argv) { int fd = drm_open_any(); int size = 0; int busy = 0; int reps = 13; int c, n, s; while ((c = getopt (argc, argv, "bs:r:")) != -1) { switch (c) { case 's': size = atoi(optarg); break; case 'r': reps = atoi(optarg); if (reps < 1) reps = 1; break; case 'b': busy = true; break; default: break; } } if (size == 0) { for (s = 4096; s <= OBJECT_SIZE; s <<= 1) { igt_stats_t stats; igt_stats_init_with_size(&stats, reps); for (n = 0; n < reps; n++) { struct timespec start, end; uint64_t count = 0; clock_gettime(CLOCK_MONOTONIC, &start); do { for (c = 0; c < 1000; c++) { uint32_t handle; handle = gem_create(fd, s); gem_set_domain(fd, handle, I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT); if (busy) make_busy(fd, handle); gem_close(fd, handle); } count += c; clock_gettime(CLOCK_MONOTONIC, &end); } while (end.tv_sec - start.tv_sec < 2); igt_stats_push_float(&stats, count / elapsed(&start, &end)); } printf("%f\n", igt_stats_get_trimean(&stats)); igt_stats_fini(&stats); } } else { for (n = 0; n < reps; n++) { struct timespec start, end; uint64_t count = 0; clock_gettime(CLOCK_MONOTONIC, &start); do { for (c = 0; c < 1000; c++) { uint32_t handle; handle = gem_create(fd, size); gem_set_domain(fd, handle, I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT); if (busy) make_busy(fd, handle); gem_close(fd, handle); } count += c; clock_gettime(CLOCK_MONOTONIC, &end); } while (end.tv_sec - start.tv_sec < 2); printf("%f\n", count / elapsed(&start, &end)); } } return 0; }
static void rtprio(pthread_attr_t *attr, int prio) { #ifdef PTHREAD_EXPLICIT_SCHED struct sched_param param = { .sched_priority = 99 }; pthread_attr_setinheritsched(attr, PTHREAD_EXPLICIT_SCHED); pthread_attr_setschedpolicy(attr, SCHED_FIFO); pthread_attr_setschedparam(attr, ¶m); #endif } static double l_estimate(igt_stats_t *stats) { if (stats->n_values > 9) return igt_stats_get_trimean(stats); else if (stats->n_values > 5) return igt_stats_get_median(stats); else return igt_stats_get_mean(stats); } static double min_measurement_error(void) { struct timespec start, end; int n; clock_gettime(CLOCK_MONOTONIC, &start); for (n = 0; n < 1024; n++) clock_gettime(CLOCK_MONOTONIC, &end); return elapsed(&start, &end) / n; } int main(int argc, char **argv) { struct gem_busyspin *busy; struct sys_wait *wait; pthread_attr_t attr; int ncpus = sysconf(_SC_NPROCESSORS_ONLN); igt_stats_t cycles, mean, max; double min; int time = 10; int field = -1; int enable_gem_sysbusy = 1; int n, c; while ((c = getopt(argc, argv, "t:f:n")) != -1) { switch (c) { case 'n': /* dry run, measure baseline system latency */ enable_gem_sysbusy = 0; break; case 't': /* How long to run the benchmark for (seconds) */ time = atoi(optarg); if (time < 0) time = INT_MAX; break; case 'f': /* Select an output field */ field = atoi(optarg); break; default: break; } } /* Prevent CPU sleeps so that busy and idle loads are consistent. */ force_low_latency(); min = min_measurement_error(); busy = calloc(ncpus, sizeof(*busy)); pthread_attr_init(&attr); if (enable_gem_sysbusy) { for (n = 0; n < ncpus; n++) { bind_cpu(&attr, n); pthread_create(&busy[n].thread, &attr, gem_busyspin, &busy[n]); } } wait = calloc(ncpus, sizeof(*wait)); pthread_attr_init(&attr); rtprio(&attr, 99); for (n = 0; n < ncpus; n++) { igt_mean_init(&wait[n].mean); bind_cpu(&attr, n); pthread_create(&wait[n].thread, &attr, sys_wait, &wait[n]); } sleep(time); done = 1; igt_stats_init_with_size(&cycles, ncpus); if (enable_gem_sysbusy) { for (n = 0; n < ncpus; n++) { pthread_join(busy[n].thread, NULL); igt_stats_push(&cycles, busy[n].count); } } igt_stats_init_with_size(&mean, ncpus); igt_stats_init_with_size(&max, ncpus); for (n = 0; n < ncpus; n++) { pthread_join(wait[n].thread, NULL); igt_stats_push_float(&mean, wait[n].mean.mean); igt_stats_push_float(&max, wait[n].mean.max); } switch (field) { default: printf("gem_syslatency: cycles=%.0f, latency mean=%.3fus max=%.0fus\n", igt_stats_get_mean(&cycles), (igt_stats_get_mean(&mean) - min)/ 1000, (l_estimate(&max) - min) / 1000); break; case 0: printf("%.0f\n", igt_stats_get_mean(&cycles)); break; case 1: printf("%.3f\n", (igt_stats_get_mean(&mean) - min) / 1000); break; case 2: printf("%.0f\n", (l_estimate(&max) - min) / 1000); break; } return 0; }