Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ec1c59cb authored by Mengjiao Yang's avatar Mengjiao Yang Committed by Android (Google) Code Review
Browse files

Merge "Fix percentile calculations"

parents ae79ac98 c88f8bb5
Loading
Loading
Loading
Loading
+109 −51
Original line number Diff line number Diff line
@@ -101,18 +101,21 @@ public:
};

static const uint32_t num_buckets = 128;
static const uint64_t max_time_bucket = 50ull * 1000000;
static const uint64_t time_per_bucket = max_time_bucket / num_buckets;
static constexpr float time_per_bucket_ms = time_per_bucket / 1.0E6;
static uint64_t max_time_bucket = 50ull * 1000000;
static uint64_t time_per_bucket = max_time_bucket / num_buckets;

struct ProcResults {
    uint64_t m_best = max_time_bucket;
    uint64_t m_worst = 0;
    uint32_t m_buckets[num_buckets] = {0};
    uint64_t m_transactions = 0;
    uint64_t m_long_transactions = 0;
    uint64_t m_total_time = 0;
    uint64_t m_best = max_time_bucket;

    void add_time(uint64_t time) {
        if (time > max_time_bucket) {
            m_long_transactions++;
        }
        m_buckets[min(time, max_time_bucket-1) / time_per_bucket] += 1;
        m_best = min(time, m_best);
        m_worst = max(time, m_worst);
@@ -127,16 +130,24 @@ struct ProcResults {
        ret.m_worst = max(a.m_worst, b.m_worst);
        ret.m_best = min(a.m_best, b.m_best);
        ret.m_transactions = a.m_transactions + b.m_transactions;
        ret.m_long_transactions = a.m_long_transactions + b.m_long_transactions;
        ret.m_total_time = a.m_total_time + b.m_total_time;
        return ret;
    }
    void dump() {
        if (m_long_transactions > 0) {
            cout << (double)m_long_transactions / m_transactions << "% of transactions took longer "
                "than estimated max latency. Consider setting -m to be higher than "
                 << m_worst / 1000 << " microseconds" << endl;
        }

        double best = (double)m_best / 1.0E6;
        double worst = (double)m_worst / 1.0E6;
        double average = (double)m_total_time / m_transactions / 1.0E6;
        cout << "average:" << average << "ms worst:" << worst << "ms best:" << best << "ms" << endl;

        uint64_t cur_total = 0;
        float time_per_bucket_ms = time_per_bucket / 1.0E6;
        for (int i = 0; i < num_buckets; i++) {
            float cur_time = time_per_bucket_ms * i + 0.5f * time_per_bucket_ms;
            if ((cur_total < 0.5f * m_transactions) && (cur_total + m_buckets[i] >= 0.5f * m_transactions)) {
@@ -154,7 +165,6 @@ struct ProcResults {
            cur_total += m_buckets[i];
        }
        cout << endl;

    }
};

@@ -166,8 +176,7 @@ String16 generateServiceName(int num)
    return serviceName;
}

void worker_fx(
    int num,
void worker_fx(int num,
               int worker_count,
               int iterations,
               int payload_size,
@@ -264,47 +273,19 @@ void signal_all(vector<Pipe>& v)
    }
}

int main(int argc, char *argv[])
void run_main(int iterations,
              int workers,
              int payload_size,
              int cs_pair,
              bool training_round=false)
{
    int workers = 2;
    int iterations = 10000;
    int payload_size = 0;
    bool cs_pair = false;
    (void)argc;
    (void)argv;
    vector<Pipe> pipes;

    // Parse arguments.
    for (int i = 1; i < argc; i++) {
        if (string(argv[i]) == "-w") {
            workers = atoi(argv[i+1]);
            i++;
            continue;
        }
        if (string(argv[i]) == "-i") {
            iterations = atoi(argv[i+1]);
            i++;
            continue;
        }
        if (string(argv[i]) == "-s") {
            payload_size = atoi(argv[i+1]);
	    i++;
	}
        if (string(argv[i]) == "-p") {
		// client/server pairs instead of spreading
		// requests to all workers. If true, half
		// the workers become clients and half servers
		cs_pair = true;
	}
    }

    // Create all the workers and wait for them to spawn.
    for (int i = 0; i < workers; i++) {
        pipes.push_back(make_worker(i, iterations, workers, payload_size, cs_pair));
    }
    wait_all(pipes);


    // Run the workers and wait for completion.
    chrono::time_point<chrono::high_resolution_clock> start, end;
    cout << "waiting for workers to complete" << endl;
@@ -326,7 +307,6 @@ int main(int argc, char *argv[])
        pipes[i].recv(tmp_results);
        tot_results = ProcResults::combine(tot_results, tmp_results);
    }
    tot_results.dump();

    // Kill all the workers.
    cout << "killing workers" << endl;
@@ -338,5 +318,83 @@ int main(int argc, char *argv[])
            cout << "nonzero child status" << status << endl;
        }
    }
    if (training_round) {
        // sets max_time_bucket to 2 * m_worst from the training round.
        // Also needs to adjust time_per_bucket accordingly.
        max_time_bucket = 2 * tot_results.m_worst;
        time_per_bucket = max_time_bucket / num_buckets;
        cout << "Max latency during training: " << tot_results.m_worst / 1.0E6 << "ms" << endl;
    } else {
            tot_results.dump();
    }
}

int main(int argc, char *argv[])
{
    int workers = 2;
    int iterations = 10000;
    int payload_size = 0;
    bool cs_pair = false;
    bool training_round = false;
    (void)argc;
    (void)argv;

    // Parse arguments.
    for (int i = 1; i < argc; i++) {
        if (string(argv[i]) == "--help") {
            cout << "Usage: binderThroughputTest [OPTIONS]" << endl;
            cout << "\t-i N    : Specify number of iterations." << endl;
            cout << "\t-m N    : Specify expected max latency in microseconds." << endl;
            cout << "\t-p      : Split workers into client/server pairs." << endl;
            cout << "\t-s N    : Specify payload size." << endl;
            cout << "\t-t N    : Run training round." << endl;
            cout << "\t-w N    : Specify total number of workers." << endl;
            return 0;
        }
        if (string(argv[i]) == "-w") {
            workers = atoi(argv[i+1]);
            i++;
            continue;
        }
        if (string(argv[i]) == "-i") {
            iterations = atoi(argv[i+1]);
            i++;
            continue;
        }
        if (string(argv[i]) == "-s") {
            payload_size = atoi(argv[i+1]);
            i++;
        }
        if (string(argv[i]) == "-p") {
            // client/server pairs instead of spreading
            // requests to all workers. If true, half
            // the workers become clients and half servers
            cs_pair = true;
        }
        if (string(argv[i]) == "-t") {
            // Run one training round before actually collecting data
            // to get an approximation of max latency.
            training_round = true;
        }
        if (string(argv[i]) == "-m") {
            // Caller specified the max latency in microseconds.
            // No need to run training round in this case.
            if (atoi(argv[i+1]) > 0) {
                max_time_bucket = strtoull(argv[i+1], (char **)NULL, 10) * 1000;
                i++;
            } else {
                cout << "Max latency -m must be positive." << endl;
                exit(EXIT_FAILURE);
            }
        }
    }

    if (training_round) {
        cout << "Start training round" << endl;
        run_main(iterations, workers, payload_size, cs_pair, training_round=true);
        cout << "Completed training round" << endl << endl;
    }

    run_main(iterations, workers, payload_size, cs_pair);
    return 0;
}