static uint64_t run_test(struct Test *test) { unsigned i; const unsigned THREADS = 1; memset(test, 0, sizeof(*test)); /* Generate producer threads */ for (i=0; i<THREADS; i++) { pixie_begin_thread(test_producer_thread, 0, test); } /* Wait for threads to start */ while (test->producer_started < THREADS) pixie_usleep(10); /* Now start consuming */ pixie_begin_thread(test_consumer_thread, 0, test); /* Wait for producer threads to end */ while (test->producer_done < THREADS) pixie_usleep(10); /* Tell consumer thread to end */ test->not_active = 1; /* Wait for consumer thread to end */ while (!test->consumer_done) pixie_usleep(10); return test->total_count; }
static void thread_worker_start(struct Core *core) { struct CoreWorkerThread *t; t = malloc(sizeof(*t)); if (t == 0) return; memset(t, 0, sizeof(*t)); t->core = core; t->index = core->workers_count; t->handle = pixie_begin_thread(thread_worker, 0, t); if (t->handle == 0) { LOG_ERR(C_GENERAL, "can't start worker thread %u\n", errno); free(t); return; } /* * Append to our list of worker threads */ core->workers = REALLOC2(core->workers, core->workers_count + 1, sizeof(core->workers[0])); core->workers[core->workers_count] = t; core->workers_count++; }
int perftest(int argc, char *argv[]) { struct PerfTest perftest[1]; struct ZoneFileParser *parser; struct Catalog *db; size_t i; perftest->loop_count = 10000000; /* * Create a pseudo-network subsystem for generating packets */ perftest->server.parent = perftest; perftest->server.adapter = adapter_create( perftest_alloc_packet, perftest_server_to_client_response, &perftest->server); adapter_add_ipv4(perftest->server.adapter, 0xC0A80101, 0xFFFFffff); /* create a catalog/database, this is where all the parsed zonefile * records will be put */ perftest->db = catalog_create(); perftest->thread->catalog = perftest->db; db = perftest->db; /* * Parse a sample zone */ parser = zonefile_begin( example_origin, /* origin */ 60, /* TTL */ 10000, /* filesize */ "<perftest>", /* filename */ zonefile_load, /* callback */ db, /* callback data */ 0 ); zonefile_set_singlestep(parser); for (i=0; perftest_zone[i]; i++) { zonefile_parse(parser, (const unsigned char*)perftest_zone[i], strlen(perftest_zone[i]) ); } zonefile_end(parser); /* * Send packets. This creates one thread per CPU processing requests. */ { unsigned threads_desired = pixie_cpu_get_count(); uint64_t start, stop; double requests_per_second; fprintf(stderr, "running %u threads\n", threads_desired); start = pixie_gettime(); for (i=0; i<threads_desired; i++) { __sync_fetch_and_add(&threads_running, 1); pixie_begin_thread((void(*)(void*))run_perf, 0, perftest); } while (threads_running) pixie_usleep(1000); stop = pixie_gettime(); requests_per_second = 1000000.0 * (1.0 * threads_desired * perftest->loop_count) / (stop - start); fprintf(stderr, "queries = %u\n", (unsigned)(threads_desired * perftest->loop_count)); fprintf(stderr, "seconds = %5.3f\n", (stop - start)/1000000.0); fprintf(stderr, "queries/second = %5.3f\n", requests_per_second); } exit(1); return 0; }
enum SuccessFailure conf_zonefiles_parse( struct Catalog *db_load, struct Configuration *cfg, uint64_t *out_total_files, uint64_t *out_total_bytes) { struct XParseThread p[16]; size_t exit_code; size_t parse_thread_count = 4; size_t i; size_t start_index; enum SuccessFailure status = Success; size_t in_total_files; //LOG(2, "loading %llu zonefiles\n", conf->zonefiles.total_files); /* * Make sure we have some zonefiles to parse */ in_total_files = cfg->zones_length + cfg->zonedirs_filecount; if (in_total_files == 0) return Failure; /* none found */ /* The parser threads are heavy-weight, so therefore * we shouldn't have a lot of them unless we have * a lot of files to parse */ if (in_total_files < 10) parse_thread_count = 1; else if (in_total_files < 5000) parse_thread_count = 2; else parse_thread_count = 4; /* * Divide the list of names into equal sized chunks, * and launch a parsing thread for each one. The primary * optimization that's happening here is that that each * of the threads will stall waiting for file I/O, during * which time other threads can be active. Each individual * file can be parsed with only a single thread, of course, * because zonefiles are stateful. However, two unrelated * files can be parsed at the same time. */ start_index = 0; for (i=0; i<parse_thread_count; i++) { size_t end_index; if (start_index >= in_total_files) { parse_thread_count = i; break; } /* * Figure out the index */ end_index = start_index + in_total_files/parse_thread_count; p[i].db_load = db_load; p[i].start_index = start_index; p[i].end_index = end_index; p[i].cfg = cfg; p[i].total_bytes = 0; p[i].total_files = 0; if (parse_thread_count > 1) { p[i].thread_handle = pixie_begin_thread(conf_zonefiles_parse_thread, 0, &p[i]); } else { p[i].thread_handle = 0; conf_zonefiles_parse_thread(p); } start_index = end_index; } /* * Wait for them all to end, and collect statistics. */ for (i=0; i<parse_thread_count; i++) { pixie_join(p[i].thread_handle, &exit_code); *out_total_bytes += p[i].total_bytes; *out_total_files = p[i].total_files; if (p[i].status != Success) status = Failure; } return status; }