// File: chahk0129[P]hash_bench/./bench/benchmark.hpp
// Function: benchmark_t<char [32]>::microbench(int, Pair<char [32]>*, int, bool)
inline void benchmark_t<Key_t>::microbench(int index_type, Pair<Key_t>* init_kv, int init_num, bool insert_only){
    Hash<Key_t>* hashtable = getInstance<Key_t>(index_type);
    gen_input(init_kv, init_num);
    /*
    if constexpr(sizeof(Key_t) > 8){
    }
    else{
	for(int i=0; i<init_num; i++){
	    init_kv[i].key = i+1;
	    init_kv[i].value = i+1;
	}
    }*/
    std::random_shuffle(init_kv, init_kv+init_num);
    clear_cache();
    struct timespec start, end;
    clock_gettime(CLOCK_MONOTONIC, &start);
    for(int i=0; i<init_num; i++){
	hashtable->Insert(init_kv[i].key, init_kv[i].value);
    }
    clock_gettime(CLOCK_MONOTONIC, &end);
    uint64_t elapsed = end.tv_nsec - start.tv_nsec + (end.tv_sec - start.tv_sec)*1000000000;
    uint64_t throughput = (uint64_t)init_num / (elapsed/1000.0) * 1000000;
    std::cout << "\033[1;32m";
    std::cout << "Insert Throughput(Ops/sec): " << throughput << std::endl;
#ifdef BREAKDOWN
    std::cout << "Elapsed time(msec): " << elapsed/1000000.0 << "\033[0m" << std::endl;;
    std::cout << "split_time(msec): " << split_time/1000000.0 << std::endl;
    std::cout << "cuckoo_time(msec): " << cuckoo_time/1000000.0 << std::endl;
    std::cout << "traversal_time(msec): " << (elapsed - split_time - cuckoo_time)/1000000.0 << std::endl;
#endif
    if(insert_only)
	return;

    clear_cache();
    clock_gettime(CLOCK_MONOTONIC, &start);
    for(int i=0; i<init_num; i++){
	auto ret = hashtable->Get(init_kv[i].key);
	assert((uint64_t)ret == init_kv[i].value);
    }
    clock_gettime(CLOCK_MONOTONIC, &end);
    elapsed = end.tv_nsec - start.tv_nsec + (end.tv_sec - start.tv_sec)*1000000000;
    throughput = (uint64_t)init_num / (elapsed/1000.0) * 1000000;
    std::cout << "\033[1;32m";
    std::cout << "Search Throughput(Ops/sec): " << throughput << "\033[0m" << std::endl;

    clear_cache();
    clock_gettime(CLOCK_MONOTONIC, &start);
    for(int i=0; i<init_num/30; i++){
	auto ret = hashtable->Update(init_kv[i].key, init_kv[i].value);
	assert(ret);
    }
    clock_gettime(CLOCK_MONOTONIC, &end);
    elapsed = end.tv_nsec - start.tv_nsec + (end.tv_sec - start.tv_sec)*1000000000;
    throughput = (uint64_t)init_num/30 / (elapsed/1000.0) * 1000000;
    std::cout << "\033[1;32m";
    std::cout << "Update Throughput(Ops/sec): " << throughput << "\033[0m" << std::endl;

    clear_cache();
    clock_gettime(CLOCK_MONOTONIC, &start);
    for(int i=0; i<init_num/20; i++){
	auto ret = hashtable->Delete(init_kv[i].key);
	assert(ret);
    }
    clock_gettime(CLOCK_MONOTONIC, &end);
    elapsed = end.tv_nsec - start.tv_nsec + (end.tv_sec - start.tv_sec)*1000000000;
    throughput = (uint64_t)(init_num/20) / (elapsed/1000.0) * 1000000;
    std::cout << "\033[1;32m";
    std::cout << "Delete Throughput(Ops/sec): " << throughput << "\033[0m" << std::endl;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xc0, %rsp
movb %r8b, %al
movq %rdi, -0x8(%rbp)
movl %esi, -0xc(%rbp)
movq %rdx, -0x18(%rbp)
movl %ecx, -0x1c(%rbp)
andb $0x1, %al
movb %al, -0x1d(%rbp)
movl -0xc(%rbp), %edi
callq 0x1b2b0
movq %rax, -0x28(%rbp)
movq -0x18(%rbp), %rdi
movl -0x1c(%rbp), %esi
callq 0x1b3f0
movq -0x18(%rbp), %rdi
movq -0x18(%rbp), %rsi
movslq -0x1c(%rbp), %rax
imulq $0x28, %rax, %rax
addq %rax, %rsi
callq 0x1b4c0
callq 0x1b570
movl $0x1, %edi
leaq -0x38(%rbp), %rsi
callq 0x63d0
movl $0x0, -0x4c(%rbp)
movl -0x4c(%rbp), %eax
cmpl -0x1c(%rbp), %eax
jge 0x14db9
movq -0x28(%rbp), %rdi
movq -0x18(%rbp), %rsi
movslq -0x4c(%rbp), %rax
imulq $0x28, %rax, %rax
addq %rax, %rsi
movq -0x18(%rbp), %rax
movslq -0x4c(%rbp), %rcx
imulq $0x28, %rcx, %rcx
addq %rcx, %rax
movq 0x20(%rax), %rdx
movq (%rdi), %rax
callq *(%rax)
movl -0x4c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x4c(%rbp)
jmp 0x14d7b
movl $0x1, %edi
leaq -0x48(%rbp), %rsi
callq 0x63d0
movq -0x48(%rbp), %rcx
movq -0x40(%rbp), %rax
movq -0x38(%rbp), %rdx
movq -0x30(%rbp), %rsi
subq %rsi, %rax
subq %rdx, %rcx
imulq $0x3b9aca00, %rcx, %rcx # imm = 0x3B9ACA00
addq %rcx, %rax
movq %rax, -0x58(%rbp)
movslq -0x1c(%rbp), %rax
movq %rax, %xmm0
movaps 0x2d235(%rip), %xmm3    # 0x42030
movaps %xmm3, -0xa0(%rbp)
punpckldq %xmm3, %xmm0    # xmm0 = xmm0[0],xmm3[0],xmm0[1],xmm3[1]
movapd 0x2d232(%rip), %xmm2    # 0x42040
movaps %xmm2, -0x90(%rbp)
subpd %xmm2, %xmm0
movaps %xmm0, %xmm1
unpckhpd %xmm0, %xmm0            # xmm0 = xmm0[1,1]
addsd %xmm1, %xmm0
movq -0x58(%rbp), %xmm1
punpckldq %xmm3, %xmm1    # xmm1 = xmm1[0],xmm3[0],xmm1[1],xmm3[1]
subpd %xmm2, %xmm1
movaps %xmm1, %xmm2
unpckhpd %xmm1, %xmm1            # xmm1 = xmm1[1,1]
addsd %xmm2, %xmm1
movsd 0x2d1cc(%rip), %xmm2    # 0x42010
divsd %xmm2, %xmm1
divsd %xmm1, %xmm0
movsd 0x2d1b4(%rip), %xmm1    # 0x42008
movsd %xmm1, -0xb8(%rbp)
mulsd %xmm1, %xmm0
movaps %xmm0, %xmm1
cvttsd2si %xmm1, %rax
movq %rax, %rdx
sarq $0x3f, %rdx
movsd 0x2d1a1(%rip), %xmm1    # 0x42018
subsd %xmm1, %xmm0
cvttsd2si %xmm0, %rcx
andq %rdx, %rcx
orq %rcx, %rax
movq %rax, -0x60(%rbp)
movq 0x45127(%rip), %rdi     # 0x59fb8
movq %rdi, -0xa8(%rbp)
leaq 0x2d35e(%rip), %rsi     # 0x421fd
callq 0x6400
movq -0xa8(%rbp), %rdi
leaq 0x2d353(%rip), %rsi     # 0x42205
callq 0x6400
movq %rax, %rdi
movq -0x60(%rbp), %rsi
callq 0x60a0
movq %rax, %rdi
movq 0x450d3(%rip), %rsi     # 0x59fa0
movq %rsi, -0xb0(%rbp)
callq 0x6460
movq -0xa8(%rbp), %rdi
leaq 0x2d33b(%rip), %rsi     # 0x42222
callq 0x6400
movsd -0xb8(%rbp), %xmm1
movaps -0xa0(%rbp), %xmm3
movaps -0x90(%rbp), %xmm2
movq %rax, %rdi
movq -0x58(%rbp), %xmm0
punpckldq %xmm3, %xmm0    # xmm0 = xmm0[0],xmm3[0],xmm0[1],xmm3[1]
subpd %xmm2, %xmm0
movaps %xmm0, %xmm2
unpckhpd %xmm0, %xmm0            # xmm0 = xmm0[1,1]
addsd %xmm2, %xmm0
divsd %xmm1, %xmm0
callq 0x6820
movq %rax, %rdi
leaq 0x2d307(%rip), %rsi     # 0x42237
callq 0x6400
movq -0xb0(%rbp), %rsi
movq %rax, %rdi
callq 0x6460
movq -0xa8(%rbp), %rdi
leaq 0x2d2ea(%rip), %rsi     # 0x4223c
callq 0x6400
movsd -0xb8(%rbp), %xmm1
movaps -0xa0(%rbp), %xmm3
movaps -0x90(%rbp), %xmm2
movq %rax, %rdi
movq 0x45ce8(%rip), %xmm0    # 0x5ac60
punpckldq %xmm3, %xmm0    # xmm0 = xmm0[0],xmm3[0],xmm0[1],xmm3[1]
subpd %xmm2, %xmm0
movaps %xmm0, %xmm2
unpckhpd %xmm0, %xmm0            # xmm0 = xmm0[1,1]
addsd %xmm2, %xmm0
divsd %xmm1, %xmm0
callq 0x6820
movq -0xb0(%rbp), %rsi
movq %rax, %rdi
callq 0x6460
movq -0xa8(%rbp), %rdi
leaq 0x2d29e(%rip), %rsi     # 0x4224f
callq 0x6400
movsd -0xb8(%rbp), %xmm1
movaps -0xa0(%rbp), %xmm3
movaps -0x90(%rbp), %xmm2
movq %rax, %rdi
movq 0x45c91(%rip), %xmm0    # 0x5ac68
punpckldq %xmm3, %xmm0    # xmm0 = xmm0[0],xmm3[0],xmm0[1],xmm3[1]
subpd %xmm2, %xmm0
movaps %xmm0, %xmm2
unpckhpd %xmm0, %xmm0            # xmm0 = xmm0[1,1]
addsd %xmm2, %xmm0
divsd %xmm1, %xmm0
callq 0x6820
movq -0xb0(%rbp), %rsi
movq %rax, %rdi
callq 0x6460
movq -0xa8(%rbp), %rdi
leaq 0x2d253(%rip), %rsi     # 0x42263
callq 0x6400
movaps -0xa0(%rbp), %xmm2
movaps -0x90(%rbp), %xmm1
movq %rax, %rdi
movq -0x58(%rbp), %rax
movq 0x45c2f(%rip), %rcx     # 0x5ac60
subq %rcx, %rax
movq 0x45c2d(%rip), %rcx     # 0x5ac68
subq %rcx, %rax
movq %rax, %xmm0
punpckldq %xmm2, %xmm0    # xmm0 = xmm0[0],xmm2[0],xmm0[1],xmm2[1]
subpd %xmm1, %xmm0
movaps %xmm0, %xmm1
unpckhpd %xmm0, %xmm0            # xmm0 = xmm0[1,1]
addsd %xmm1, %xmm0
movsd 0x2cfaa(%rip), %xmm1    # 0x42008
divsd %xmm1, %xmm0
callq 0x6820
movq %rax, %rdi
movq 0x44f2f(%rip), %rsi     # 0x59fa0
callq 0x6460
testb $0x1, -0x1d(%rbp)
je 0x15081
jmp 0x1556a
callq 0x1b570
movl $0x1, %edi
leaq -0x38(%rbp), %rsi
callq 0x63d0
movl $0x0, -0x64(%rbp)
movl -0x64(%rbp), %eax
cmpl -0x1c(%rbp), %eax
jge 0x15107
movq -0x28(%rbp), %rdi
movq -0x18(%rbp), %rsi
movslq -0x64(%rbp), %rax
imulq $0x28, %rax, %rax
addq %rax, %rsi
movq (%rdi), %rax
callq *0x18(%rax)
movq %rax, -0x70(%rbp)
movq -0x70(%rbp), %rax
movq -0x18(%rbp), %rcx
movslq -0x64(%rbp), %rdx
imulq $0x28, %rdx, %rdx
addq %rdx, %rcx
cmpq 0x20(%rcx), %rax
jne 0x150db
jmp 0x150fa
leaq 0x2d198(%rip), %rdi     # 0x4227a
leaq 0x2d1b3(%rip), %rsi     # 0x4229c
movl $0xcb, %edx
leaq 0x2d1bd(%rip), %rcx     # 0x422b2
callq 0x6260
jmp 0x150fc
movl -0x64(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x64(%rbp)
jmp 0x1509b
movl $0x1, %edi
leaq -0x48(%rbp), %rsi
callq 0x63d0
movq -0x48(%rbp), %rcx
movq -0x40(%rbp), %rax
movq -0x38(%rbp), %rdx
movq -0x30(%rbp), %rsi
subq %rsi, %rax
subq %rdx, %rcx
imulq $0x3b9aca00, %rcx, %rcx # imm = 0x3B9ACA00
addq %rcx, %rax
movq %rax, -0x58(%rbp)
movslq -0x1c(%rbp), %rax
movq %rax, %xmm0
movaps 0x2cee7(%rip), %xmm3    # 0x42030
punpckldq %xmm3, %xmm0    # xmm0 = xmm0[0],xmm3[0],xmm0[1],xmm3[1]
movapd 0x2ceeb(%rip), %xmm2    # 0x42040
subpd %xmm2, %xmm0
movaps %xmm0, %xmm1
unpckhpd %xmm0, %xmm0            # xmm0 = xmm0[1,1]
addsd %xmm1, %xmm0
movq -0x58(%rbp), %xmm1
punpckldq %xmm3, %xmm1    # xmm1 = xmm1[0],xmm3[0],xmm1[1],xmm3[1]
subpd %xmm2, %xmm1
movaps %xmm1, %xmm2
unpckhpd %xmm1, %xmm1            # xmm1 = xmm1[1,1]
addsd %xmm2, %xmm1
movsd 0x2ce8c(%rip), %xmm2    # 0x42010
divsd %xmm2, %xmm1
divsd %xmm1, %xmm0
movsd 0x2ce74(%rip), %xmm1    # 0x42008
mulsd %xmm1, %xmm0
movaps %xmm0, %xmm1
cvttsd2si %xmm1, %rax
movq %rax, %rdx
sarq $0x3f, %rdx
movsd 0x2ce69(%rip), %xmm1    # 0x42018
subsd %xmm1, %xmm0
cvttsd2si %xmm0, %rcx
andq %rdx, %rcx
orq %rcx, %rax
movq %rax, -0x60(%rbp)
movq 0x44def(%rip), %rdi     # 0x59fb8
leaq 0x2d02d(%rip), %rsi     # 0x421fd
callq 0x6400
movq 0x44ddc(%rip), %rdi     # 0x59fb8
leaq 0x2d128(%rip), %rsi     # 0x4230b
callq 0x6400
movq %rax, %rdi
movq -0x60(%rbp), %rsi
callq 0x60a0
movq %rax, %rdi
leaq 0x2d039(%rip), %rsi     # 0x42237
callq 0x6400
movq %rax, %rdi
movq 0x44d93(%rip), %rsi     # 0x59fa0
callq 0x6460
callq 0x1b570
movl $0x1, %edi
leaq -0x38(%rbp), %rsi
callq 0x63d0
movl $0x0, -0x74(%rbp)
movl -0x74(%rbp), %eax
movl %eax, -0xbc(%rbp)
movl -0x1c(%rbp), %eax
movl $0x1e, %ecx
cltd
idivl %ecx
movl %eax, %ecx
movl -0xbc(%rbp), %eax
cmpl %ecx, %eax
jge 0x152b4
movq -0x28(%rbp), %rdi
movq -0x18(%rbp), %rsi
movslq -0x74(%rbp), %rax
imulq $0x28, %rax, %rax
addq %rax, %rsi
movq -0x18(%rbp), %rax
movslq -0x74(%rbp), %rcx
imulq $0x28, %rcx, %rcx
addq %rcx, %rax
movq 0x20(%rax), %rdx
movq (%rdi), %rax
callq *0x8(%rax)
andb $0x1, %al
movb %al, -0x75(%rbp)
testb $0x1, -0x75(%rbp)
je 0x15285
jmp 0x152a4
leaq 0x2d09c(%rip), %rdi     # 0x42328
leaq 0x2d009(%rip), %rsi     # 0x4229c
movl $0xd7, %edx
leaq 0x2d013(%rip), %rcx     # 0x422b2
callq 0x6260
jmp 0x152a6
movl -0x74(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x74(%rbp)
jmp 0x1522c
movl $0x1, %edi
leaq -0x48(%rbp), %rsi
callq 0x63d0
movq -0x48(%rbp), %rcx
movq -0x40(%rbp), %rax
movq -0x38(%rbp), %rdx
movq -0x30(%rbp), %rsi
subq %rsi, %rax
subq %rdx, %rcx
imulq $0x3b9aca00, %rcx, %rcx # imm = 0x3B9ACA00
addq %rcx, %rax
movq %rax, -0x58(%rbp)
movslq -0x1c(%rbp), %rax
movabsq $-0x7777777777777777, %rcx # imm = 0x8888888888888889
mulq %rcx
shrq $0x4, %rdx
cvtsi2sd %rdx, %xmm0
movaps 0x2cd29(%rip), %xmm2    # 0x42030
movq -0x58(%rbp), %xmm1
punpckldq %xmm2, %xmm1    # xmm1 = xmm1[0],xmm2[0],xmm1[1],xmm2[1]
movapd 0x2cd28(%rip), %xmm2    # 0x42040
subpd %xmm2, %xmm1
movaps %xmm1, %xmm2
unpckhpd %xmm1, %xmm1            # xmm1 = xmm1[1,1]
addsd %xmm2, %xmm1
movsd 0x2cce1(%rip), %xmm2    # 0x42010
divsd %xmm2, %xmm1
divsd %xmm1, %xmm0
movsd 0x2ccc9(%rip), %xmm1    # 0x42008
mulsd %xmm1, %xmm0
movaps %xmm0, %xmm1
cvttsd2si %xmm1, %rax
movq %rax, %rdx
sarq $0x3f, %rdx
movsd 0x2ccbe(%rip), %xmm1    # 0x42018
subsd %xmm1, %xmm0
cvttsd2si %xmm0, %rcx
andq %rdx, %rcx
orq %rcx, %rax
movq %rax, -0x60(%rbp)
movq 0x44c44(%rip), %rdi     # 0x59fb8
leaq 0x2ce82(%rip), %rsi     # 0x421fd
callq 0x6400
movq 0x44c31(%rip), %rdi     # 0x59fb8
leaq 0x2cf9e(%rip), %rsi     # 0x4232c
callq 0x6400
movq %rax, %rdi
movq -0x60(%rbp), %rsi
callq 0x60a0
movq %rax, %rdi
leaq 0x2ce8e(%rip), %rsi     # 0x42237
callq 0x6400
movq %rax, %rdi
movq 0x44be8(%rip), %rsi     # 0x59fa0
callq 0x6460
callq 0x1b570
movl $0x1, %edi
leaq -0x38(%rbp), %rsi
callq 0x63d0
movl $0x0, -0x7c(%rbp)
movl -0x7c(%rbp), %eax
movl %eax, -0xc0(%rbp)
movl -0x1c(%rbp), %eax
movl $0x14, %ecx
cltd
idivl %ecx
movl %eax, %ecx
movl -0xc0(%rbp), %eax
cmpl %ecx, %eax
jge 0x15449
movq -0x28(%rbp), %rdi
movq -0x18(%rbp), %rsi
movslq -0x7c(%rbp), %rax
imulq $0x28, %rax, %rax
addq %rax, %rsi
movq (%rdi), %rax
callq *0x10(%rax)
andb $0x1, %al
movb %al, -0x7d(%rbp)
testb $0x1, -0x7d(%rbp)
je 0x1541d
jmp 0x1543c
leaq 0x2cf04(%rip), %rdi     # 0x42328
leaq 0x2ce71(%rip), %rsi     # 0x4229c
movl $0xe3, %edx
leaq 0x2ce7b(%rip), %rcx     # 0x422b2
callq 0x6260
jmp 0x1543e
movl -0x7c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x7c(%rbp)
jmp 0x153d7
movl $0x1, %edi
leaq -0x48(%rbp), %rsi
callq 0x63d0
movq -0x48(%rbp), %rcx
movq -0x40(%rbp), %rax
movq -0x38(%rbp), %rdx
movq -0x30(%rbp), %rsi
subq %rsi, %rax
subq %rdx, %rcx
imulq $0x3b9aca00, %rcx, %rcx # imm = 0x3B9ACA00
addq %rcx, %rax
movq %rax, -0x58(%rbp)
movslq -0x1c(%rbp), %rax
imulq $0x66666667, %rax, %rax # imm = 0x66666667
movq %rax, %rcx
shrq $0x3f, %rcx
sarq $0x23, %rax
addl %ecx, %eax
cltq
movq %rax, %xmm0
movaps 0x2cb8f(%rip), %xmm3    # 0x42030
punpckldq %xmm3, %xmm0    # xmm0 = xmm0[0],xmm3[0],xmm0[1],xmm3[1]
movapd 0x2cb93(%rip), %xmm2    # 0x42040
subpd %xmm2, %xmm0
movaps %xmm0, %xmm1
unpckhpd %xmm0, %xmm0            # xmm0 = xmm0[1,1]
addsd %xmm1, %xmm0
movq -0x58(%rbp), %xmm1
punpckldq %xmm3, %xmm1    # xmm1 = xmm1[0],xmm3[0],xmm1[1],xmm3[1]
subpd %xmm2, %xmm1
movaps %xmm1, %xmm2
unpckhpd %xmm1, %xmm1            # xmm1 = xmm1[1,1]
addsd %xmm2, %xmm1
movsd 0x2cb34(%rip), %xmm2    # 0x42010
divsd %xmm2, %xmm1
divsd %xmm1, %xmm0
movsd 0x2cb1c(%rip), %xmm1    # 0x42008
mulsd %xmm1, %xmm0
movaps %xmm0, %xmm1
cvttsd2si %xmm1, %rax
movq %rax, %rdx
sarq $0x3f, %rdx
movsd 0x2cb11(%rip), %xmm1    # 0x42018
subsd %xmm1, %xmm0
cvttsd2si %xmm0, %rcx
andq %rdx, %rcx
orq %rcx, %rax
movq %rax, -0x60(%rbp)
movq 0x44a97(%rip), %rdi     # 0x59fb8
leaq 0x2ccd5(%rip), %rsi     # 0x421fd
callq 0x6400
movq 0x44a84(%rip), %rdi     # 0x59fb8
leaq 0x2ce0e(%rip), %rsi     # 0x42349
callq 0x6400
movq %rax, %rdi
movq -0x60(%rbp), %rsi
callq 0x60a0
movq %rax, %rdi
leaq 0x2cce1(%rip), %rsi     # 0x42237
callq 0x6400
movq %rax, %rdi
movq 0x44a3b(%rip), %rsi     # 0x59fa0
callq 0x6460
addq $0xc0, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)
nopl (%rax)