Both RHEL5/RHEL6 encounter the same situation.
Is there any potential bug?
]# g++ testaes.cpp -lcrypto -lz
RHEL6 nake
[r...@djt_10_47 ~]# time ./a.out 1 10000 | head -n 10000 | md5sum
caba4fd0bae809e634b5cd8acd3424f2 -
real 0m5.778s
user 0m5.774s
sys 0m0.014s
RHEL6 KVM
[r...@djt_10_199 ~]# time ./a.out 1 10000 | head -n 10000 | md5sum
51722dcdf339f131a89eb2dc106d8dbe -
real 0m3.272s
user 0m3.266s
sys 0m0.032s
RHEL5 nake
[...@djt_10_48 ~]# time ./a.out 1 10000 | head -n 10000 | md5sum
51722dcdf339f131a89eb2dc106d8dbe -
real 0m5.786s
user 0m5.780s
sys 0m0.008s
RHEL5 KVM
[...@djt_10_192 ~]# time ./a.out 1 10000 | head -n 10000 | md5sum
51722dcdf339f131a89eb2dc106d8dbe -
real 0m3.243s
user 0m2.864s
sys 0m0.387s
Regards
Kirby Zhou
#define _XOPEN_SOURCE 500
#define __STDC_FORMAT_MACROS 1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/time.h>
#include <malloc.h>
#include <stdint.h>
#include <inttypes.h>
#include <getopt.h>
#include <vector>
#include <algorithm>
#include <signal.h>
#include <assert.h>
#include <zlib.h>
#include <openssl/aes.h>
#include <dlfcn.h>
#define PAGE_SIZE 4096
void print_usage()
{
fprintf(stderr, "usage:\n");
fprintf(stderr, " [options] <loop_number> <total_request>\n");
fprintf(stderr, " -v verbose\n");
fprintf(stderr, "\n");
}
struct TestCaseDesc {
unsigned thr_number;
unsigned long long total_io;
int verbose;
};
struct iorequest {
int io_op;
int flags;
off64_t io_off;
size_t io_size;
};
bool iorequest_less(const iorequest& a, const iorequest& b)
{
return a.io_off < b.io_off;
}
struct ioqueue {
std::vector<iorequest> data;
size_t pos;
};
#define IO_TYPES 4
struct routine_context {
int id;
const TestCaseDesc* testcase;
ioqueue* queue;
// for stat
timeval begin, end;
uint64_t io_count[IO_TYPES];
uint64_t io_sum[IO_TYPES];
};
volatile bool g_quit = false;
void sig_doquit_handler(int) {
g_quit = true;
}
static void do_cpu(const TestCaseDesc& testcase, const iorequest* req, void*
const buf, void* const jobbuf)
{
// fill data
const uintmax_t tmp = req->io_off / 257;
for (size_t i = 0; i < req->io_size; i+= sizeof(uintmax_t) ) {
((uintmax_t*)buf)[i/sizeof(uintmax_t)] = (i + tmp) & 0xf00fff;
}
AES_KEY key = {};
uint8_t iv[AES_BLOCK_SIZE] = {};
AES_set_encrypt_key((const uint8_t*)"hollyshitgodfather", 128, &key);
AES_cbc_encrypt((const uint8_t*)buf, (uint8_t*)jobbuf, req->io_size,
&key, iv, AES_ENCRYPT);
uint32_t c = crc32(0, (const uint8_t*)jobbuf, req->io_size);
fprintf(stdout, "%llu %u\n", req->io_off, c);
}
void* io_routine(void* _arg)
{
routine_context* arg = (routine_context*) _arg;
const TestCaseDesc testcase = *arg->testcase;
const size_t ringbuf_caps = 5*1024*1024ul;
void* const ringbuf = memalign(PAGE_SIZE, ringbuf_caps);
void* buf = ringbuf;
void* const jobbuf = memalign(PAGE_SIZE, ringbuf_caps);
gettimeofday(&arg->begin, NULL);
while (!g_quit) {
// adjust buf
(uint8_t*&)buf += PAGE_SIZE;
// get pos
size_t pos;
pos = arg->queue->pos;
if (pos < arg->queue->data.size()) {
arg->queue->pos += 1;
}
if (pos >= arg->queue->data.size())
break;
// run io request
const iorequest* req = &arg->queue->data[pos];
if ((uint8_t*)buf + req->io_size > (uint8_t*)ringbuf +
ringbuf_caps)
{
buf = ringbuf;
}
arg->io_count[req->io_op] += 1;
arg->io_sum[req->io_op] += req->io_size;
do_cpu(testcase, req, buf, jobbuf);
}
gettimeofday(&arg->end, NULL);
}
void process_arguments(int argc, char* argv[], TestCaseDesc* result)
{
TestCaseDesc testcase = { };
int c;
bool opt_flag[256] = { };
char* perr_strto = NULL;
while ( -1 != (c = getopt(argc, argv, "v")) ) {
opt_flag[c] = true;
switch (c) {
case 'v':
testcase.verbose += 1;
break;
default:
fprintf(stderr, "Invalid: -%c %s\n", c, optarg);
print_usage();
exit(1);
}
if (perr_strto && *perr_strto) {
fprintf(stderr, "Invalid number: %s\n", optarg);
print_usage();
exit(1);
}
}
if (argc - optind != 2) {
print_usage();
exit(1);
}
testcase.thr_number = strtoul(argv[optind++], NULL, 0);
testcase.total_io = strtoull(argv[optind++], NULL, 0);
*result = testcase;
}
void generate_requests(const TestCaseDesc& testcase, routine_context context[],
ioqueue** pqueue)
{
ioqueue* queue;
queue = new ioqueue[testcase.thr_number];
queue[0].data.reserve(testcase.total_io);
for (int i = 0; i < testcase.thr_number; ++i) {
context[i].queue = &queue[i];
}
*pqueue = queue;
off64_t off = 0;
for (int j = 0; j < testcase.total_io; ++j) {
int i = j % testcase.thr_number;
iorequest req = {0, 0, off, 32768};
off += 32768;
context[i].queue->data.push_back(req);
}
for (int i = 0; i < testcase.thr_number; ++i) {
std::sort(queue[i].data.begin(), queue[i].data.end(),
iorequest_less);
}
}
int main(int argc, char* argv[])
{
int rt;
TestCaseDesc testcase = { };
process_arguments(argc, argv, &testcase);
// initializer io_routine context
routine_context context0 = { };
routine_context* context = new routine_context[testcase.thr_number];
ioqueue* queue = NULL;
for (int i = 0; i < testcase.thr_number; ++i) {
context[i].testcase = &testcase;
context[i].id = i;
}
generate_requests(testcase, context, &queue);
fprintf(stdout, "all requests generated\n");
signal(SIGINT, &sig_doquit_handler);
signal(SIGTERM, &sig_doquit_handler);
signal(SIGQUIT, SIG_IGN);
// start io_routine
for (int i = 0; i < testcase.thr_number; ++i) {
io_routine(&context[i]);
}
// wait for all io_routine
gettimeofday(&context0.begin, NULL);
gettimeofday(&context0.end, NULL);
delete[] queue;
if (testcase.verbose > 0)
fprintf(stderr, "[] main done\n");
}
_______________________________________________
rhelv5-list mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/rhelv5-list