// File: yangwanyuan[P]HLKVDS/tools/Benchmark.cc
// Function: Bench_Insert(hlkvds::KVDS*, int, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>>&, int, LatMgr*)
double Bench_Insert(KVDS *db, int record_num, vector<string> &key_list,
                    int thread_num, LatMgr *total_lat_mgr = NULL) {
    cout << "Start Benchmark Test: Insert , record_num = " << record_num << ", Please wait ..." << endl;

    string data = string(VALUE_SIZE, 'v');

    thread_arg arglist[thread_num];
    pthread_t pidlist[thread_num];
    for (int i = 0; i < thread_num; i++) {
        int start = (record_num / thread_num) * i;
        int end = (record_num / thread_num) * (i + 1) - 1;
        arglist[i].db = db;
        arglist[i].key_start = start;
        arglist[i].key_end = end;
        arglist[i].key_list = &key_list;
        arglist[i].data = &data;
        arglist[i].latency = new uint64_t[end - start + 1];
    }

    KVTime tv_start;
    for (int i = 0; i < thread_num; i++) {
        pthread_create(&pidlist[i], NULL, fun_insert, &arglist[i]);
    }
    //db->printDbStates();
    for (int i=0; i<thread_num; i++) {
        pthread_join(pidlist[i], NULL);
    }

    KVTime tv_end;
    double diff_time = (tv_end - tv_start) / 1000000.0;

    LatMgr lat_mgr;
    for (int i = 0; i < thread_num; i++) {
        lat_mgr.Push_back_batch(arglist[i].latency, record_num/thread_num);

        //if overwrite, save to total_lat_mgr
        if (total_lat_mgr) {
            total_lat_mgr->Push_back_batch(arglist[i].latency, record_num/thread_num);
        }

        delete[] arglist[i].latency;
    }

    Lat_Stats lat_stats;
    lat_mgr.GetStatistics(lat_stats);

    double iops = record_num / diff_time;

    uint64_t total_size = (uint64_t)record_num * (KEY_SIZE + VALUE_SIZE);
    double throughput = total_size / (diff_time * 1024 * 1024);

    uint64_t avg = lat_mgr.GetAvg();
    uint64_t min = lat_mgr.GetMin();
    uint64_t max = lat_mgr.GetMax();

    cout << "Insert Bench Finish. Total time: " << diff_time << "s" <<endl;
    cout << "Performance Report     :   IOPS = " <<  iops << ", Average Latency = "
            << avg << "us, Throughput = " << throughput << "MB/s." << endl;
    cout << "Latency Report(usec)   :   Min = " << min << ", Max = "
            << max << ", Med = " << lat_stats.med << "." << endl;
    cout << "Latency Statistic(usec):   P50 = " << lat_stats.P_50 << ", P75 = "
            << lat_stats.P_75 << ", P99 = " << lat_stats.P_99 << ", P999 = "
            << lat_stats.P_999 << ", P9999 = " << lat_stats.P_9999 << endl;

    return diff_time;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x260, %rsp            # imm = 0x260
movq %rdi, -0x8(%rbp)
movl %esi, -0xc(%rbp)
movq %rdx, -0x18(%rbp)
movl %ecx, -0x1c(%rbp)
movq %r8, -0x28(%rbp)
movq 0x6e78c(%rip), %rdi     # 0x77fd0
leaq 0x4d980(%rip), %rsi     # 0x571cb
callq 0x8520
movq %rax, %rdi
movl -0xc(%rbp), %esi
callq 0x8870
movq %rax, %rdi
leaq 0x4d8e9(%rip), %rsi     # 0x5714e
callq 0x8520
movq %rax, %rdi
movq 0x6e72c(%rip), %rsi     # 0x77fa0
callq 0x8560
leaq -0x49(%rbp), %rdi
movq %rdi, -0x140(%rbp)
callq 0x8890
movq -0x140(%rbp), %rcx
leaq -0x48(%rbp), %rdi
movl $0x1000, %esi           # imm = 0x1000
movl $0x76, %edx
callq 0x8330
jmp 0x98a5
leaq -0x49(%rbp), %rdi
callq 0x8580
movl -0x1c(%rbp), %eax
movq %rsp, %rcx
movq %rcx, -0x68(%rbp)
leaq (%rax,%rax,4), %rcx
leaq 0xf(,%rcx,8), %rdx
andq $-0x10, %rdx
movq %rsp, %rcx
subq %rdx, %rcx
movq %rcx, -0x150(%rbp)
movq %rcx, %rsp
movq %rax, -0x70(%rbp)
movl -0x1c(%rbp), %eax
leaq 0xf(,%rax,8), %rdx
andq $-0x10, %rdx
movq %rsp, %rcx
subq %rdx, %rcx
movq %rcx, -0x148(%rbp)
movq %rcx, %rsp
movq %rax, -0x78(%rbp)
movl $0x0, -0x7c(%rbp)
movl -0x7c(%rbp), %eax
cmpl -0x1c(%rbp), %eax
jge 0x9a22
movl -0xc(%rbp), %eax
movl -0x1c(%rbp), %ecx
cltd
idivl %ecx
movl -0x7c(%rbp), %ecx
imull %ecx, %eax
movl %eax, -0x80(%rbp)
movl -0xc(%rbp), %eax
movl -0x1c(%rbp), %ecx
cltd
idivl %ecx
movl %eax, %ecx
movq -0x150(%rbp), %rax
movl -0x7c(%rbp), %edx
incl %edx
imull %edx, %ecx
decl %ecx
movl %ecx, -0x84(%rbp)
movq -0x8(%rbp), %rdx
movslq -0x7c(%rbp), %rcx
leaq (%rcx,%rcx,4), %rcx
movq %rdx, (%rax,%rcx,8)
movl -0x80(%rbp), %edx
movslq -0x7c(%rbp), %rcx
leaq (%rcx,%rcx,4), %rcx
movl %edx, 0x8(%rax,%rcx,8)
movl -0x84(%rbp), %edx
movslq -0x7c(%rbp), %rcx
leaq (%rcx,%rcx,4), %rcx
movl %edx, 0xc(%rax,%rcx,8)
movq -0x18(%rbp), %rdx
movslq -0x7c(%rbp), %rcx
leaq (%rcx,%rcx,4), %rcx
movq %rdx, 0x10(%rax,%rcx,8)
movslq -0x7c(%rbp), %rcx
leaq (%rcx,%rcx,4), %rcx
leaq -0x48(%rbp), %rdx
movq %rdx, 0x18(%rax,%rcx,8)
movl -0x84(%rbp), %eax
movl -0x80(%rbp), %ecx
subl %ecx, %eax
incl %eax
cltq
movl $0x8, %ecx
mulq %rcx
movq %rax, %rdi
movq $-0x1, %rax
cmovoq %rax, %rdi
callq 0x8040
movq %rax, -0x158(%rbp)
jmp 0x99cc
movq -0x158(%rbp), %rcx
movq -0x150(%rbp), %rax
movslq -0x7c(%rbp), %rdx
imulq $0x28, %rdx, %rdx
addq %rdx, %rax
movq %rcx, 0x20(%rax)
movl -0x7c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x7c(%rbp)
jmp 0x9906
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
leaq -0x49(%rbp), %rdi
callq 0x8580
jmp 0xa0e5
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
jmp 0xa0dc
leaq -0x98(%rbp), %rdi
callq 0x555c0
jmp 0x9a30
movl $0x0, -0x9c(%rbp)
movl -0x9c(%rbp), %eax
cmpl -0x1c(%rbp), %eax
jge 0x9a90
movq -0x150(%rbp), %rcx
movq -0x148(%rbp), %rdi
movslq -0x9c(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rdi
movslq -0x9c(%rbp), %rax
imulq $0x28, %rax, %rax
addq %rax, %rcx
xorl %eax, %eax
movl %eax, %esi
leaq -0x58a(%rip), %rdx      # 0x94f0
callq 0x88f0
movl -0x9c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x9c(%rbp)
jmp 0x9a3a
movl $0x0, -0xa0(%rbp)
movl -0xa0(%rbp), %eax
cmpl -0x1c(%rbp), %eax
jge 0x9ae6
movq -0x148(%rbp), %rax
movslq -0xa0(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x84c0
jmp 0x9ac2
jmp 0x9ac4
movl -0xa0(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xa0(%rbp)
jmp 0x9a9a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
jmp 0xa0d0
leaq -0xb0(%rbp), %rdi
callq 0x555c0
jmp 0x9af4
leaq -0xb0(%rbp), %rdi
leaq -0x98(%rbp), %rsi
callq 0x55770
movq %rax, -0x160(%rbp)
jmp 0x9b10
movq -0x160(%rbp), %rax
cvtsi2sd %rax, %xmm0
movsd 0x4d4e4(%rip), %xmm1    # 0x57008
divsd %xmm1, %xmm0
movsd %xmm0, -0xb8(%rbp)
leaq -0xd0(%rbp), %rdi
callq 0xcf10
movl $0x0, -0xd4(%rbp)
movl -0xd4(%rbp), %eax
cmpl -0x1c(%rbp), %eax
jge 0x9c31
movq -0x150(%rbp), %rax
movslq -0xd4(%rbp), %rcx
leaq (%rcx,%rcx,4), %rcx
movq 0x20(%rax,%rcx,8), %rsi
movl -0xc(%rbp), %eax
movl -0x1c(%rbp), %ecx
cltd
idivl %ecx
movl %eax, %edx
leaq -0xd0(%rbp), %rdi
callq 0xcf20
jmp 0x9b85
cmpq $0x0, -0x28(%rbp)
je 0x9be9
movq -0x150(%rbp), %rax
movq -0x28(%rbp), %rdi
movslq -0xd4(%rbp), %rcx
leaq (%rcx,%rcx,4), %rcx
movq 0x20(%rax,%rcx,8), %rsi
movl -0xc(%rbp), %eax
movl -0x1c(%rbp), %ecx
cltd
idivl %ecx
movl %eax, %edx
callq 0xcf20
jmp 0x9bb9
jmp 0x9be9
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
jmp 0xa0c4
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
leaq -0xd0(%rbp), %rdi
callq 0xd260
jmp 0xa0c4
movq -0x150(%rbp), %rax
movslq -0xd4(%rbp), %rcx
imulq $0x28, %rcx, %rcx
addq %rcx, %rax
movq 0x20(%rax), %rax
movq %rax, -0x168(%rbp)
cmpq $0x0, %rax
je 0x9c1b
movq -0x168(%rbp), %rdi
callq 0x8650
jmp 0x9c1d
movl -0xd4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xd4(%rbp)
jmp 0x9b46
leaq -0xd0(%rbp), %rdi
leaq -0x108(%rbp), %rsi
callq 0xcf80
jmp 0x9c46
cvtsi2sdl -0xc(%rbp), %xmm0
movsd -0xb8(%rbp), %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, -0x110(%rbp)
movslq -0xc(%rbp), %rax
imulq $0x100a, %rax, %rax     # imm = 0x100A
movq %rax, -0x118(%rbp)
movaps 0x4d3c8(%rip), %xmm1    # 0x57040
movq -0x118(%rbp), %xmm0
punpckldq %xmm1, %xmm0    # xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1]
movapd 0x4d3c4(%rip), %xmm1    # 0x57050
subpd %xmm1, %xmm0
movaps %xmm0, %xmm1
unpckhpd %xmm0, %xmm0            # xmm0 = xmm0[1,1]
addsd %xmm1, %xmm0
movsd -0xb8(%rbp), %xmm1
movsd 0x4d365(%rip), %xmm2    # 0x57010
mulsd %xmm2, %xmm1
mulsd %xmm2, %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, -0x120(%rbp)
leaq -0xd0(%rbp), %rdi
callq 0xd110
movq %rax, -0x170(%rbp)
jmp 0x9cd4
movq -0x170(%rbp), %rax
movq %rax, -0x128(%rbp)
leaq -0xd0(%rbp), %rdi
callq 0xd1c0
movq %rax, -0x178(%rbp)
jmp 0x9cf7
movq -0x178(%rbp), %rax
movq %rax, -0x130(%rbp)
leaq -0xd0(%rbp), %rdi
callq 0xd210
movq %rax, -0x180(%rbp)
jmp 0x9d1a
movq -0x180(%rbp), %rax
movq %rax, -0x138(%rbp)
movq 0x6e2a1(%rip), %rdi     # 0x77fd0
leaq 0x4d4c2(%rip), %rsi     # 0x571f8
callq 0x8520
movq %rax, -0x188(%rbp)
jmp 0x9d44
movq -0x188(%rbp), %rdi
movsd -0xb8(%rbp), %xmm0
callq 0x8940
movq %rax, -0x190(%rbp)
jmp 0x9d61
movq -0x190(%rbp), %rdi
leaq 0x4d668(%rip), %rsi     # 0x573d7
callq 0x8520
movq %rax, -0x198(%rbp)
jmp 0x9d7d
movq -0x198(%rbp), %rdi
movq 0x6e215(%rip), %rsi     # 0x77fa0
callq 0x8560
jmp 0x9d92
movq 0x6e237(%rip), %rdi     # 0x77fd0
leaq 0x4d47a(%rip), %rsi     # 0x5721a
callq 0x8520
movq %rax, -0x1a0(%rbp)
jmp 0x9dae
movq -0x1a0(%rbp), %rdi
movsd -0x110(%rbp), %xmm0
callq 0x8940
movq %rax, -0x1a8(%rbp)
jmp 0x9dcb
movq -0x1a8(%rbp), %rdi
leaq 0x4d464(%rip), %rsi     # 0x5723d
callq 0x8520
movq %rax, -0x1b0(%rbp)
jmp 0x9de7
movq -0x1b0(%rbp), %rdi
movq -0x128(%rbp), %rsi
callq 0x80f0
movq %rax, -0x1b8(%rbp)
jmp 0x9e03
movq -0x1b8(%rbp), %rdi
leaq 0x4d441(%rip), %rsi     # 0x57252
callq 0x8520
movq %rax, -0x1c0(%rbp)
jmp 0x9e1f
movq -0x1c0(%rbp), %rdi
movsd -0x120(%rbp), %xmm0
callq 0x8940
movq %rax, -0x1c8(%rbp)
jmp 0x9e3c
movq -0x1c8(%rbp), %rdi
leaq 0x4d41a(%rip), %rsi     # 0x57264
callq 0x8520
movq %rax, -0x1d0(%rbp)
jmp 0x9e58
movq -0x1d0(%rbp), %rdi
movq 0x6e13a(%rip), %rsi     # 0x77fa0
callq 0x8560
jmp 0x9e6d
movq 0x6e15c(%rip), %rdi     # 0x77fd0
leaq 0x4d3ef(%rip), %rsi     # 0x5726a
callq 0x8520
movq %rax, -0x1d8(%rbp)
jmp 0x9e89
movq -0x1d8(%rbp), %rdi
movq -0x130(%rbp), %rsi
callq 0x80f0
movq %rax, -0x1e0(%rbp)
jmp 0x9ea5
movq -0x1e0(%rbp), %rdi
leaq 0x4d3d9(%rip), %rsi     # 0x5728c
callq 0x8520
movq %rax, -0x1e8(%rbp)
jmp 0x9ec1
movq -0x1e8(%rbp), %rdi
movq -0x138(%rbp), %rsi
callq 0x80f0
movq %rax, -0x1f0(%rbp)
jmp 0x9edd
movq -0x1f0(%rbp), %rdi
leaq 0x4d3aa(%rip), %rsi     # 0x57295
callq 0x8520
movq %rax, -0x1f8(%rbp)
jmp 0x9ef9
movq -0x1f8(%rbp), %rdi
movq -0x108(%rbp), %rsi
callq 0x80f0
movq %rax, -0x200(%rbp)
jmp 0x9f15
movq -0x200(%rbp), %rdi
leaq 0x4d23b(%rip), %rsi     # 0x5715e
callq 0x8520
movq %rax, -0x208(%rbp)
jmp 0x9f31
movq -0x208(%rbp), %rdi
movq 0x6e061(%rip), %rsi     # 0x77fa0
callq 0x8560
jmp 0x9f46
movq 0x6e083(%rip), %rdi     # 0x77fd0
leaq 0x4d34a(%rip), %rsi     # 0x5729e
callq 0x8520
movq %rax, -0x210(%rbp)
jmp 0x9f62
movq -0x210(%rbp), %rdi
movq -0x100(%rbp), %rsi
callq 0x80f0
movq %rax, -0x218(%rbp)
jmp 0x9f7e
movq -0x218(%rbp), %rdi
leaq 0x4d334(%rip), %rsi     # 0x572c0
callq 0x8520
movq %rax, -0x220(%rbp)
jmp 0x9f9a
movq -0x220(%rbp), %rdi
movq -0xf8(%rbp), %rsi
callq 0x80f0
movq %rax, -0x228(%rbp)
jmp 0x9fb6
movq -0x228(%rbp), %rdi
leaq 0x4d305(%rip), %rsi     # 0x572c9
callq 0x8520
movq %rax, -0x230(%rbp)
jmp 0x9fd2
movq -0x230(%rbp), %rdi
movq -0xf0(%rbp), %rsi
callq 0x80f0
movq %rax, -0x238(%rbp)
jmp 0x9fee
movq -0x238(%rbp), %rdi
leaq 0x4d2d6(%rip), %rsi     # 0x572d2
callq 0x8520
movq %rax, -0x240(%rbp)
jmp 0xa00a
movq -0x240(%rbp), %rdi
movq -0xe8(%rbp), %rsi
callq 0x80f0
movq %rax, -0x248(%rbp)
jmp 0xa026
movq -0x248(%rbp), %rdi
leaq 0x4d2a8(%rip), %rsi     # 0x572dc
callq 0x8520
movq %rax, -0x250(%rbp)
jmp 0xa042
movq -0x250(%rbp), %rdi
movq -0xe0(%rbp), %rsi
callq 0x80f0
movq %rax, -0x258(%rbp)
jmp 0xa05e
movq -0x258(%rbp), %rdi
movq 0x6df34(%rip), %rsi     # 0x77fa0
callq 0x8560
jmp 0xa073
movsd -0xb8(%rbp), %xmm0
movsd %xmm0, -0x260(%rbp)
leaq -0xd0(%rbp), %rdi
callq 0xd260
leaq -0xb0(%rbp), %rdi
callq 0x557b0
leaq -0x98(%rbp), %rdi
callq 0x557b0
movq -0x68(%rbp), %rax
movq %rax, %rsp
leaq -0x48(%rbp), %rdi
callq 0x8998
movsd -0x260(%rbp), %xmm0
movq %rbp, %rsp
popq %rbp
retq
leaq -0xb0(%rbp), %rdi
callq 0x557b0
leaq -0x98(%rbp), %rdi
callq 0x557b0
leaq -0x48(%rbp), %rdi
callq 0x8998
movq -0x58(%rbp), %rdi
callq 0x8880
nop