@@ -832,6 +832,171 @@ fn s10_leveldb_benchmark() {
832832 }
833833}
834834
835+ #[ test]
836+ fn s10_memcached_benchmark_internal ( ) {
837+ setup_network ( 1 ) ;
838+
839+ let machine = Machine :: determine ( ) ;
840+ let build = BuildArgs :: default ( )
841+ . module ( "rkapps" )
842+ . user_feature ( "rkapps:memcached-bench" )
843+ . release ( )
844+ . build ( ) ;
845+
846+ let threads: Vec < usize > = machine
847+ . thread_defaults_uniform ( )
848+ . into_iter ( )
849+ // Throw out everything above 28 since we have some non-deterministic
850+ // bug on larger machines that leads to threads calling sched_yield and
851+ // no readrandom is performed...
852+ . filter ( |& t| t <= 28 )
853+ . collect ( ) ;
854+
855+ // memcached arguments // currently not there.
856+ let ( qemu_mem, memsize, queries, timeout) = if cfg ! ( feature = "smoke" ) {
857+ ( 16 * 1024 /* MB */ , 16 /* MB */ , 2000000 , 300_000 )
858+ } else {
859+ (
860+ 128 * 1024 , /* MB */
861+ 32 * 1024 , /* MB */
862+ 50000000 ,
863+ 600_000 ,
864+ )
865+ } ;
866+
867+ let file_name = "memcached_benchmark_internal.csv" ;
868+ let _r = std:: fs:: remove_file ( file_name) ;
869+
870+ print ! ( "threads: " ) ;
871+ for thread in threads. iter ( ) {
872+ print ! ( "{thread} " ) ;
873+ }
874+ println ! ( ) ;
875+
876+ for thread in threads. iter ( ) {
877+ println ! ( "Running memcached internal benchmark with {thread} threads, {queries} GETs and {memsize}MB memory. " ) ;
878+
879+ let kernel_cmdline = format ! (
880+ r#"init=memcachedbench.bin initargs={} appcmd='--x-benchmark-mem={} --x-benchmark-queries={}'"# ,
881+ * thread, memsize, queries
882+ ) ;
883+
884+ let cmdline = RunnerArgs :: new_with_build ( "userspace-smp" , & build)
885+ . timeout ( timeout)
886+ . cores ( machine. max_cores ( ) )
887+ . nodes ( 2 )
888+ . use_virtio ( )
889+ . memory ( qemu_mem)
890+ . setaffinity ( Vec :: new ( ) )
891+ . cmd ( kernel_cmdline. as_str ( ) )
892+ . no_network_setup ( ) ;
893+
894+ let mut output = String :: new ( ) ;
895+ let mut qemu_run = || -> Result < WaitStatus > {
896+ let mut dhcp_server = spawn_dhcpd ( ) ?;
897+ let mut p = spawn_nrk ( & cmdline) ?;
898+
899+ output += dhcp_server. exp_string ( DHCP_ACK_MATCH ) ?. as_str ( ) ;
900+
901+ // match the title
902+ let ( prev, matched) = p. exp_regex ( r#"INTERNAL BENCHMARK CONFIGURE"# ) ?;
903+
904+ output += prev. as_str ( ) ;
905+ output += matched. as_str ( ) ;
906+
907+ // x_benchmark_mem = 10 MB
908+ let ( prev, matched) = p. exp_regex ( r#"x_benchmark_mem = (\d+) MB"# ) ?;
909+ println ! ( "> {}" , matched) ;
910+ let b_mem = matched. replace ( "x_benchmark_mem = " , "" ) . replace ( " MB" , "" ) ;
911+
912+ output += prev. as_str ( ) ;
913+ output += matched. as_str ( ) ;
914+
915+ // number of threads: 3
916+ let ( prev, matched) = p. exp_regex ( r#"number of threads: (\d+)"# ) ?;
917+ println ! ( "> {}" , matched) ;
918+ let b_threads = matched. replace ( "number of threads: " , "" ) ;
919+
920+ output += prev. as_str ( ) ;
921+ output += matched. as_str ( ) ;
922+
923+ // number of keys: 131072
924+ let ( prev, matched) = p. exp_regex ( r#"number of keys: (\d+)"# ) ?;
925+ println ! ( "> {}" , matched) ;
926+
927+ output += prev. as_str ( ) ;
928+ output += matched. as_str ( ) ;
929+
930+ let ( prev, matched) = p. exp_regex ( r#"Executing (\d+) queries with (\d+) threads"# ) ?;
931+ println ! ( "> {}" , matched) ;
932+
933+ output += prev. as_str ( ) ;
934+ output += matched. as_str ( ) ;
935+
936+ // benchmark took 129 seconds
937+ let ( prev, matched) = p. exp_regex ( r#"benchmark took (\d+) ms"# ) ?;
938+ println ! ( "> {}" , matched) ;
939+ let b_time = matched. replace ( "benchmark took " , "" ) . replace ( " ms" , "" ) ;
940+
941+ output += prev. as_str ( ) ;
942+ output += matched. as_str ( ) ;
943+
944+ // benchmark took 7937984 queries / second
945+ let ( prev, matched) = p. exp_regex ( r#"benchmark took (\d+) queries / second"# ) ?;
946+ println ! ( "> {}" , matched) ;
947+ let b_thpt = matched
948+ . replace ( "benchmark took " , "" )
949+ . replace ( " queries / second" , "" ) ;
950+
951+ output += prev. as_str ( ) ;
952+ output += matched. as_str ( ) ;
953+
954+ let ( prev, matched) = p. exp_regex ( r#"benchmark executed (\d+)"# ) ?;
955+ println ! ( "> {}" , matched) ;
956+ let b_queries = matched
957+ . replace ( "benchmark executed " , "" )
958+ . split ( ' ' )
959+ . next ( )
960+ . unwrap ( )
961+ . to_string ( ) ;
962+
963+ output += prev. as_str ( ) ;
964+ output += matched. as_str ( ) ;
965+
966+ // Append parsed results to a CSV file
967+ let write_headers = !Path :: new ( file_name) . exists ( ) ;
968+ let mut csv_file = OpenOptions :: new ( )
969+ . append ( true )
970+ . create ( true )
971+ . open ( file_name)
972+ . expect ( "Can't open file" ) ;
973+ if write_headers {
974+ let row = "git_rev,benchmark,nthreads,mem,queries,time,thpt\n " ;
975+ let r = csv_file. write ( row. as_bytes ( ) ) ;
976+ assert ! ( r. is_ok( ) ) ;
977+ }
978+
979+ let r = csv_file. write ( format ! ( "{}," , env!( "GIT_HASH" ) ) . as_bytes ( ) ) ;
980+ assert ! ( r. is_ok( ) ) ;
981+ let out = format ! (
982+ "memcached,{},{},{},{},{}" ,
983+ b_threads, b_mem, b_queries, b_time, b_thpt,
984+ ) ;
985+ let r = csv_file. write ( out. as_bytes ( ) ) ;
986+ assert ! ( r. is_ok( ) ) ;
987+ let r = csv_file. write ( "\n " . as_bytes ( ) ) ;
988+ assert ! ( r. is_ok( ) ) ;
989+
990+ // cleanup
991+ dhcp_server. send_control ( 'c' ) ?;
992+ p. process . kill ( SIGTERM ) ?;
993+ p. process . exit ( )
994+ } ;
995+
996+ check_for_successful_exit ( & cmdline, qemu_run ( ) , output) ;
997+ }
998+ }
999+
8351000/// Tests that basic pmem allocation support is functional.
8361001/// TODO: Store persistent data durably and test it.
8371002#[ test]
0 commit comments