├── .gitignore ├── .gitmodules ├── Makefile ├── README.md ├── TODO ├── all_the_graphs ├── avg_data.pl ├── batch ├── bench_commands.c ├── bench_commands.h ├── bzip2_wrapper ├── cacheperf ├── catbench.c ├── clients ├── .gitignore ├── Makefile ├── csvcombine ├── dist_a_mask_setup ├── dpdk_wrapper.c ├── dpdk_wrapper.h ├── llc.c ├── llc.h ├── lockclient.c ├── lockserver-ng.c ├── movnt.h ├── movnt.s ├── pcm.cpp_v2.10.patch ├── perf_poll.c ├── perf_poll.h ├── rdtscp.h ├── realtime.c ├── realtime.h ├── rng.c ├── rng.h ├── rng_test.c ├── square_evictions.c ├── square_evictions_csv ├── square_evictions_wrapper ├── summarize_helpers.sh ├── summarize_slobro ├── summarize_square_evictions ├── summarize_square_wave ├── syscallers.h └── tocsv_pcm ├── combine-json.py ├── cost-analysis-result.py ├── csvify ├── csvmerge ├── csvmergecheck ├── data_analysis ├── README ├── graph-cat.py ├── jaguar ├── largescale_and_cdf ├── make-cdf ├── mica2_tables ├── network_rawnums ├── network_slowdown ├── postprocess.sh ├── pres_graphs └── timescale_and_cdf ├── dist_a.c ├── driver ├── external ├── dpdk.patch ├── modules.mk └── pqos.patch ├── factors.sh ├── find_zipf_N.py ├── flags.mk ├── generate_hadoop_input.sh ├── graph-bar.py ├── graph-cat.py ├── graph-double.py ├── graph_helper.py ├── gzip_wrapper ├── hadoop_wrapper ├── jagoff ├── jaguar ├── arrcsv ├── jaguar ├── notes_json_format.txt ├── template.json ├── template_postprocessed.json └── test.json ├── lepton_wrapper ├── lockserver-driver ├── locksmith.c ├── log.c ├── log.h ├── network_rawnums ├── network_rtt ├── network_slowdown ├── networked ├── .sh ├── bzip2.sh ├── contender_duration.sh ├── fixed_duration.sh ├── grpc_interval.sh ├── gunzip.sh ├── gzip.sh ├── hadoop.sh ├── hadoop_short.sh ├── lepton.sh ├── lepton_long.sh ├── lockserver.sh ├── mica.sh ├── mica_interval.sh ├── mica_sqlite.sh ├── mica_wss_percentage.sh ├── square_evictions.sh ├── tensorflow_mnist_long.sh └── tensorflow_mnist_short.sh ├── onmycommand.c ├── perfexpl.c ├── post-process.py ├── postprocess.sh ├── prep_system.c ├── prep_system.h ├── proc_manip.c ├── proc_manip.h ├── rdtscp.h ├── run-benchmark ├── run-extended-benchmark ├── setpgrp.c ├── setup ├── after_reboot ├── after_reboot_module ├── after_reboot_router └── package ├── slowbro.c ├── square_evictions-vary-allocation ├── strip ├── syscallers.h ├── tensorflow_blt ├── tensorflow_mnist_long ├── tensorflow_mnist_short └── test-pmd ├── .gitignore ├── Makefile ├── cmdline.c ├── config.c ├── csumonly.c ├── flowgen.c ├── icmpecho.c ├── ieee1588fwd.c ├── iofwd.c ├── macfwd-retry.c ├── macfwd.c ├── macswap.c ├── mempool_anon.c ├── mempool_osdep.h ├── parameters.c ├── rxonly.c ├── testpmd.c ├── testpmd.h └── txonly.c /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | 3 | /.network_rtt_pw 4 | /catbench 5 | /dist_a 6 | /locksmith 7 | /onmycommand 8 | /perfexpl 9 | /setpgrp 10 | /slowbro 11 | /rtt_client 12 | /rtt_server 13 | /rtt_contender_* 14 | /rtt_perf 15 | /rtt_perf_duration 16 | /rtt_client_pipe_in 17 | /rtt_client_pipe_out 18 | /perf.data* 19 | 20 | # by /networked/{gzip,gunzip}.sh 21 | /linux-*.tar 22 | /linux-*.tar.gz 23 | # by /networked/lepton.sh 24 | /images 25 | # by /networked/tensorflow_mnist_short.sh 26 | /tensorflow_mnist_data 27 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "external/dpdk"] 2 | path = external/dpdk 3 | url = git://dpdk.org/dpdk 4 | branch = releases 5 | ignore = untracked 6 | [submodule "external/pqos"] 7 | path = external/pqos 8 | url = git://github.com/01org/intel-cmt-cat 9 | ignore = untracked 10 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | include flags.mk 2 | 3 | CPPFLAGS += \ 4 | -DLOG_DEFAULT_VERBOSITY=LOG_VERBOSE \ 5 | -D_GNU_SOURCE \ 6 | 7 | CFLAGS += \ 8 | 9 | .PHONY: all 10 | all: catbench-setcap dist_a slowbro locksmith 11 | 12 | .PHONY: clean 13 | clean: 14 | git clean -fX $(wildcard *) 15 | 16 | .PHONY: clean-recursive 17 | clean-recursive: clean 18 | $(RM) -r external/dpdk/build 19 | $(RM) external/pqos/lib/libpqos.a.dep external/pqos/lib/libpqos.so.1 external/pqos/lib/libpqos.so.1.0.1 external/pqos/pqos 20 | git submodule foreach '[ -f "../`basename $$PWD`.patch" ] && git apply -R "../`basename $$PWD`.patch"; true' 21 | git submodule foreach git clean -fX 22 | git submodule deinit $(DEINIT_FLAGS) . 23 | 24 | include external/modules.mk 25 | 26 | .PHONY: catbench-setcap 27 | 28 | catbench-setcap: catbench 29 | sudo setcap cap_sys_nice+ep $< 30 | 31 | # external/pqos/lib/libpqos.a should be at the end of these lines to compile correctly 32 | catbench: log.o proc_manip.o syscallers.h prep_system.o bench_commands.o external/pqos/lib/libpqos.a 33 | dist_a: rdtscp.h log.o proc_manip.o prep_system.o bench_commands.o external/pqos/lib/libpqos.a 34 | slowbro: bench_commands.o log.o prep_system.o proc_manip.o external/pqos/lib/libpqos.a 35 | locksmith: bench_commands.o log.o prep_system.o proc_manip.o external/pqos/lib/libpqos.a 36 | 37 | perfexpl: syscallers.h 38 | 39 | bench_commands.o: bench_commands.h syscallers.h 40 | log.o: log.h 41 | prep_system.o: external/pqos/lib/libpqos.a 42 | proc_manip.o: proc_manip.h 43 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | Ways to extend our 712 benchmarks 2 | --------------------------------- 3 | Remember to tasket the test driver programs when running them so they don't end up on a core we didn't want! Might want to automate this or at least issue a warning! In general, warnings for the things we're messing up repeatedly might be in order. 4 | 5 | Sanity check 6 | ============ 7 | - Try rerunning square_evictions prototype driver to see whether it does the expected miss things with hugepages enabled. I seeem to recall it was doing something weird and/or not doing anything as we varied the percentage? Might need to try turning off randomization and/or manually prime factorizing some numbers to get custom percentages without rng-cycling overhead. 8 | 9 | Recording page mappings 10 | ======================= 11 | - We should do this for better reproducability/understanding of past results, and to try to understand why we got the flat line for square_evictions without hugepages. 12 | 13 | Slo* 14 | ==== 15 | - Verify the global/interprocess coherency of Linux clock_gettime() calls 16 | - Tighten upper bound without code changes: Run a bunch of trials looking for favorable interleavings and Birthday Problems. Each run gives us a tighter bound under the conditions of the test, and we only have to chase the latency into libpqos and/or the kernel if we are able to get the bound small enough that it falls below the 9-10 us interval. 17 | - If needed, try using statistics to try to determine where within the interval events fall? Probably less promising... 18 | 19 | Lock* 20 | ===== 21 | - Is the LLC locked globally: try changing the non--memory-bound CPU to different CoSes from the active CPU and mutually-exclusive masks vs. the active CPU. 22 | - Are all memory accesses stalled (incl. LLC misses): try an memory-bound CPU load that has a high percentage of cache misses. 23 | 24 | Future work 25 | ----------- 26 | Read the last section of the 712 paper! 27 | 28 | Kernel dynamic process-level allocation 29 | ======================================= 30 | - When we're forced to move one process's cache between ways, is there a way for the kernel to migrate its contents to avoid deferring the repopulation to the task itself? If we cannot accomplish this, the kernel shouldn't bother to allocate the "victim" process any new cache space until it is rescheduled; otherwise, that will become wasted/dead space until the process can make use of it. This doesn't *seem* to be a deal-breaker, because you're more likely to have to move small guys who'll be faster at repopulating their lost cache space than the huge ones would... 31 | -------------------------------------------------------------------------------- /avg_data.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # TODO: calculate average time per memory access? 4 | open($infile, "<", "$ARGV[0]"); 5 | 6 | $unit = "seconds"; 7 | if($ARGV[1] ne "") { 8 | $unit = $ARGV[1]; 9 | } 10 | 11 | @data_arr; 12 | while(my $line = <$infile>) { 13 | if($line =~ /([\d\.]+)\s*$unit/) { 14 | push(@data_arr, $1); 15 | } 16 | } 17 | 18 | $sum = 0; 19 | foreach(@data_arr) { 20 | $sum += $_; 21 | } 22 | 23 | print($sum / @data_arr); 24 | print("\n"); 25 | 26 | -------------------------------------------------------------------------------- /batch: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | trap "" TERM 4 | 5 | if [ $# -ne 1 ] 6 | then 7 | cat <<-tac 8 | USAGE: $0 9 | 10 | names a job list file, each line of which consists of a set of arguments to the driver script. 11 | 12 | NB: "arguments to the driver script" means you should NOT start the lines with '`dirname "$0"`/driver'! 13 | 14 | Note that, although this file may be modified while experiments are running, lines 15 | corresponding to completed or currently-running jobs should not be removed, 16 | reordered, or otherwise displaced in this case. Such lines are identifiable by 17 | the progress comments automatically added at the end of their lines. 18 | tac 19 | exit 1 20 | fi 21 | file="$1" 22 | set -e 23 | 24 | confirm() { 25 | if [ $# -ne 2 ] 26 | then 27 | return 2 28 | fi 29 | local prompt="$1" 30 | local default="$2" 31 | set -e 32 | 33 | case "$default" in 34 | y) 35 | local suffix=" (Y/n)" 36 | ;; 37 | n) 38 | local suffix=" (y/N)" 39 | ;; 40 | *) 41 | false 42 | ;; 43 | esac 44 | 45 | while true 46 | do 47 | printf %s "$prompt$suffix? " 48 | read response 49 | case "$response" in 50 | "") 51 | return "`[ "$default" = "y" ] && echo 0 || echo 1`" 52 | ;; 53 | [yY]) 54 | return 0 55 | ;; 56 | [nN]) 57 | return 1 58 | ;; 59 | esac 60 | done 61 | } 62 | 63 | oneline() { 64 | if [ $# -lt 1 -o $# -gt 2 ] 65 | then 66 | return 1 67 | fi 68 | local linenum="$1" 69 | local mode="-n" 70 | local after=";p" 71 | if [ $# -eq 2 ] 72 | then 73 | mode="-i" 74 | after="" 75 | if [ -n "$2" ] 76 | then 77 | after=";s/$/ # $2/" 78 | fi 79 | fi 80 | set -e 81 | 82 | sed "$mode" "$linenum{s/ \?#.*//$after}" "$file" 83 | } 84 | 85 | timestamp() { 86 | date +"%F at %H:%M:%S %Z" 87 | } 88 | 89 | if [ ! -e "$file" ] 90 | then 91 | echo "$file: No such batch file" >&2 92 | exit 2 93 | fi 94 | 95 | if grep "#" "$file" >/dev/null 96 | then 97 | cat <<-tac 98 | +-----------------------------------------------------------------------------------------+ 99 | | | 100 | | IMPORTANT: That batch queue already has commented lines, indicating that it may already | 101 | | be running or have been run! Please take a moment to confirm your intent: | 102 | | | 103 | +-----------------------------------------------------------------------------------------+ 104 | 105 | tac 106 | 107 | if confirm "Do you want to abort" y 108 | then 109 | exit 3 110 | elif confirm "Do you want me to remove all comments from the file" n 111 | then 112 | sed -i 's/ \?#.*//' "$file" 113 | fi 114 | fi 115 | 116 | cat <<-tac 117 | ------------------------ 118 | STARTING BATCH RUN FROM: $file 119 | ------------------------ 120 | 121 | tac 122 | 123 | line="1" 124 | while [ "$line" -le "`wc -l "$file" | cut -d" " -f1`" ] 125 | do 126 | args="`oneline "$line"`" 127 | cat <<-tac 128 | 129 | 130 | --------------------- 131 | STARTING BATCH JOB $line: ./driver $args 132 | --------------------- 133 | 134 | tac 135 | 136 | comment="launching" 137 | for time in `seq 3` 138 | do 139 | comment="$comment." 140 | oneline "$line" "$comment" 141 | sleep 2 142 | done 143 | 144 | oneline "$line" "running since `timestamp`" 145 | ( trap - TERM && eval '"'"`dirname "$0"`/driver"'"' $args ) || true 146 | 147 | oneline "$line" "completed at `timestamp`" 148 | line="$((line + 1))" 149 | done 150 | 151 | cat <<-tac 152 | 153 | ------------------------ 154 | COMPLETED BATCH FUN RUN! 155 | ------------------------ 156 | tac 157 | -------------------------------------------------------------------------------- /bench_commands.c: -------------------------------------------------------------------------------- 1 | #include "bench_commands.h" 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "log.h" 13 | #include "syscallers.h" 14 | 15 | // TODO better solution for this 16 | #define NUM_CPUS 8 17 | 18 | #define SELF_PID 0 19 | 20 | static sigset_t block_signal(int signal) { 21 | sigset_t mask; 22 | sigemptyset(&mask); 23 | sigaddset(&mask, signal); 24 | sigprocmask(SIG_BLOCK, &mask, NULL); 25 | return mask; 26 | } 27 | 28 | static void await_signal(int signal) { 29 | int received; 30 | sigset_t await = block_signal(signal); 31 | sigwait(&await, &received); 32 | assert(received == signal); 33 | } 34 | 35 | int parse_common_args(int argc, char** argv, args_t* args) { 36 | int ret = 0; 37 | // Get dem opts 38 | int c, has_p = 0; 39 | while ((c = getopt(argc, argv, "hqup:")) != -1) { 40 | switch (c) { 41 | case 'u': 42 | args->unpin_procs = 1; 43 | break; 44 | case 'p': 45 | args->procs_go_where = atoi(optarg); 46 | has_p = 1; 47 | break; 48 | case 'q': 49 | args->quit = 1; 50 | break; 51 | case 'h': 52 | log_msg(LOG_INFO, 53 | "Usage: \n" 54 | " -p CORE: Pin system processes to CORE\n" 55 | " -u: Unpin all system processes\n" 56 | " -q: Quit after migrating, before benchmarks\n" 57 | " -h: Print this message and exit\n"); 58 | return 0; 59 | } 60 | } 61 | 62 | if (has_p && args->unpin_procs) { 63 | log_msg(LOG_FATAL, "Cannot specify both -p and -u"); 64 | } 65 | return ret; 66 | } 67 | 68 | static test_proc_t* childpids = NULL; 69 | static int num_childpids = 0; 70 | 71 | bool run_benchmarks(const test_prog_t* test_progs, const int num_test_progs) { 72 | log_msg(LOG_INFO, "On your mark\n"); 73 | bool ret = true; 74 | childpids = malloc(num_test_progs * sizeof(*childpids)); 75 | if(childpids == NULL) { 76 | perror("malloc"); 77 | /* If this happens we're pretty screwed and probably dead anyways, not much need to go to cleanup */ 78 | goto cleanup; 79 | } 80 | num_childpids = num_test_progs; 81 | memset(childpids, 1, sizeof *childpids); 82 | 83 | for(int prog = 0; prog < num_test_progs; ++prog) { 84 | block_signal(SIG_CHILD_PROC_UP); 85 | pid_t pid = fork(); 86 | switch(pid) { 87 | case -1: 88 | perror("Forking child"); 89 | ret = false; 90 | goto cleanup; 91 | case 0: { 92 | cpu_set_t* cpuset; 93 | int num_cpus = get_nprocs_conf(); 94 | cpuset = CPU_ALLOC(num_cpus); 95 | if(cpuset == NULL) { 96 | log_msg(LOG_FATAL, "CPU_ALLOC for setaffinity failed"); 97 | ret = false; 98 | goto cleanup; 99 | } 100 | int size = CPU_ALLOC_SIZE(num_cpus); 101 | if(size <= 0) { 102 | ret = false; 103 | log_msg(LOG_FATAL, "CPU_ALLOC_SIZE failed\n"); 104 | goto cleanup; 105 | } 106 | if(test_progs[prog].target_cpu >= num_cpus) { 107 | ret = false; 108 | log_msg(LOG_FATAL, "Invalid CPU number\n"); 109 | goto cleanup; 110 | } 111 | CPU_ZERO_S(size, cpuset); 112 | CPU_SET_S(test_progs[prog].target_cpu, size, cpuset); 113 | int err = sched_setaffinity(SELF_PID, size, cpuset); 114 | if(err == -1) { 115 | perror("sched_setaffinity"); 116 | ret = false; 117 | goto cleanup; 118 | } 119 | CPU_FREE(cpuset); 120 | kill(getppid(), SIG_CHILD_PROC_UP); 121 | await_signal(SIG_EXEC_TEST_PROG); 122 | exec_v(test_progs[prog].cmdline[0], test_progs[prog].cmdline); 123 | 124 | perror("Executing test program"); 125 | ret = false; 126 | goto cleanup; 127 | } 128 | default: 129 | await_signal(SIG_CHILD_PROC_UP); 130 | 131 | childpids[prog].pid = pid; 132 | 133 | // TODO: Initialize performance counters 134 | // No longer necessary because this function returns after all children start (?) 135 | } 136 | } 137 | 138 | for(int prog = 0; prog < num_test_progs; ++prog) 139 | if(kill(childpids[prog].pid, SIG_EXEC_TEST_PROG)) { 140 | ret = false; 141 | goto cleanup; 142 | } 143 | 144 | cleanup: 145 | return ret; 146 | } 147 | 148 | /* TODO: Error checking and failure behavior seems incorrect here */ 149 | int wait_benchmarks() { 150 | int ret = 0; 151 | if(childpids == NULL) 152 | return 0; 153 | for(int prog = 0; prog < num_childpids; ++prog) { 154 | if(waitpid(childpids[prog].pid, NULL, 0) < 0) { 155 | perror("Awaiting child"); 156 | ret = -1; 157 | } 158 | // TODO: Collect and output results. <-- Does this go in this function or in main? 159 | } 160 | childpids = NULL; 161 | return ret; 162 | } 163 | -------------------------------------------------------------------------------- /bench_commands.h: -------------------------------------------------------------------------------- 1 | #ifndef BENCH_COMMANDS_H_ 2 | #define BENCH_COMMANDS_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #define MAX_TEST_PROG_CMDLINE_WORDS 8 10 | 11 | typedef struct { 12 | int unpin_procs; 13 | int procs_go_where; 14 | int quit; 15 | } args_t; 16 | 17 | typedef struct { 18 | const char *cmdline[MAX_TEST_PROG_CMDLINE_WORDS]; 19 | const char *const null; 20 | const int target_cpu; 21 | } test_prog_t; 22 | 23 | #undef MAX_TEST_PROG_CMDLINE_WORDS 24 | 25 | #define SIG_CHILD_PROC_UP SIGUSR1 26 | #define SIG_EXEC_TEST_PROG SIGUSR1 27 | 28 | typedef struct { 29 | pid_t pid; 30 | // TODO: Store per-process performance data handles here. 31 | } test_proc_t; 32 | 33 | bool run_benchmarks(const test_prog_t* test_progs, const int num_test_progs); 34 | 35 | /* If wait_benchmarks is run without first running run_benchmarks, wait_benchmark will return immediately with return value 0 */ 36 | int wait_benchmarks(void); 37 | 38 | // Upon any error will return a negative value 39 | // Upon success returns 0 40 | int parse_common_args(int argc, char** argv, args_t* args); 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /bzip2_wrapper: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # bzip2_wrapper IN-PATH OUT-PATH [BZIP2-OPTIONS] 4 | 5 | input_path=$1 6 | shift 7 | output_path=$1 8 | shift 9 | 10 | input_size=$(stat --printf="%s" "$input_path") 11 | echo "input size: $input_size" 12 | 13 | output_size=$(bzip2 "$@" -c "$input_path" | tee "$output_path" | wc -c) 14 | echo "output size: $output_size" 15 | 16 | -------------------------------------------------------------------------------- /cacheperf: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | readonly COUNTERS="`echo " 4 | cpu-cycles:cpu-cycles 5 | instructions:instructions 6 | cpu/event=0x0e,umask=0x01,cmask=0x01,inv,any/:stalled-cycles (UOPS_ISSUED.ANY) 7 | L1-dcache-load-misses:L1-dcache-load-misses (L1D.REPLACEMENT) 8 | L1-icache-load-misses:L1-icache-load-misses (ICACHE.MISSES) 9 | dTLB-load-misses:dTLB-load-misses (DTLB_LOAD_MISSES.MISS_CAUSES_A_WALK) 10 | iTLB-load-misses:iTLB-load-misses (ITLB_MISSES.MISS_CAUSES_A_WALK) 11 | r81d0:MEM_UOPS_RETIRED.ALL_LOADS (i.e. L1-dcache-loads, dTLB-load-misses) 12 | r08d1:MEM_LOAD_UOPS_RETIRED.L1_MISS 13 | r10d1:MEM_LOAD_UOPS_RETIRED.L2_MISS 14 | r20d1:MEM_LOAD_UOPS_RETIRED.L3_MISS (BDE70) 15 | r2124:L2_RQSTS.DEMAND_DATA_RD_MISS 16 | re124:L2_RQSTS.ALL_DEMAND_DATA_RD 17 | re424:L2_RQSTS.ALL_CODE_RD 18 | r01f0:L2_TRANS.DEMAND_DATA_RD 19 | r04f0:L2_TRANS.CODE_RD 20 | r2424:L2_RQSTS.CODE_RD_MISS (HSW) 21 | r2724:L2_RQSTS.ALL_DEMAND_MISS (HSW) 22 | re724:L2_RQSTS.ALL_DEMAND_REFERENCES (HSW) 23 | r3f24:L2_RQSTS.MISS (HSW) 24 | rff24:L2_RQSTS.REFERENCES (HSW) 25 | r4f2e:LLC_REFERENCE (BDE70) 26 | r412e:LLC_MISS (BDE70) 27 | " | tail -n+2 | tr -d '\t'`" 28 | 29 | if [ $# -ne 2 -a \( $# -ne 1 -o "$1" != "end" \) ] 30 | then 31 | cat <<-tac 32 | USAGE: $0 <-r|-s> < | end> 33 | 34 | -r means record a perf.data file 35 | -s means only output aggregate statistics 36 | 37 | Records cache-related performance counters on the specified cores 38 | until called again with the 'end' argument. 39 | Multiple invocations "stack." 40 | tac 41 | exit 1 42 | fi 43 | 44 | cores="$2" 45 | case "$1" in 46 | -r) 47 | mode="record" 48 | ;; 49 | -s) 50 | mode="stat" 51 | ;; 52 | end) 53 | cores="$1" 54 | ;; 55 | *) 56 | printf "%s\n" "$1: Unknown switch (expected -r or -s)" >&2 57 | exit 1 58 | ;; 59 | esac 60 | set -e 61 | 62 | launch_record() { 63 | rm -f "perf.data.$cores" 64 | ln -sf "perf.data.$cores" perf.data 65 | sudo perf record -se"`echo "$COUNTERS" | cut -d: -f1 | paste -sd,`" --call-graph lbr -aC"$cores" -o perf.data time -f" %e seconds time elapsed" sleep inf 2>&1 & 66 | } 67 | 68 | report_record() { 69 | perf report --stdio -iperf.data | grep -A1 '^# Samples:' | grep -v -- -- | sed "s/'//g" | rev | cut -d" " -f1 | rev | paste - - | eval sed `echo "$COUNTERS" | sed 's|.*|-e"s:&:"|'` 70 | } 71 | 72 | launch_stat() { 73 | sudo perf stat -e"`echo "$COUNTERS" | cut -d: -f1 | paste -sd,`" 2>&1 -aC"$cores" | tee "perf.dat.$cores" | tail -n2 | tr -s " " & 74 | } 75 | 76 | report_stat() { 77 | eval sed `echo "$COUNTERS" | sed 's|.*|-e"s:&:"|'` perf.dat | tail -n+4 | head -n-3 | tr -s " " | sed 's/ \([^ ]\+\) \([^#]\+\) .*/\2\t\1/' | tr -d , 78 | } 79 | 80 | findproc() { 81 | local regex="$1" 82 | set -e 83 | 84 | ps -eocomm,pgid,pid,cmd | tr -s " " | grep "$regex" | tail -n1 85 | } 86 | 87 | if [ "$cores" = "end" ] 88 | then 89 | perfline="`findproc "^perf "`" 90 | if [ -z "$perfline" ] 91 | then 92 | echo "No instances left to end" 93 | exit 0 94 | fi 95 | 96 | perfpgid="`printf %s "$perfline" | cut -d" " -f2`" 97 | perfpid="`printf %s "$perfline" | cut -d" " -f3`" 98 | chldpid="`findproc "^sleep $perfpgid .*inf$" | cut -d" " -f3`" 99 | if [ -n "$chldpid" ] 100 | then 101 | targetpid="$chldpid" 102 | else 103 | targetpid="$perfpid" 104 | fi 105 | 106 | sudo kill -int "$targetpid" 107 | while ps -eopid | tr -d " " | grep -x "$perfpid" >/dev/null; do :; done 108 | 109 | mode="`printf %s "$perfline" | sed 's/.\+perf \([^ ]\+\).*/\1/'`" 110 | cores="`printf %s "$perfline" | sed 's/.*-aC\([^ ]\+\).*/\1/'`" 111 | case "$mode" in 112 | record) 113 | ln -sf "perf.data.$cores" perf.data 114 | sudo chown "`whoami`:" perf.data 115 | mode="record" 116 | ;; 117 | stat) 118 | ln -sf "perf.dat.$cores" perf.dat 119 | mode="stat" 120 | ;; 121 | *) 122 | echo "INTERNAL ERROR: Neither record nor stat?!" >&2 123 | exit 2 124 | esac 125 | "report_$mode" 126 | else 127 | "launch_$mode" 128 | fi 129 | -------------------------------------------------------------------------------- /catbench.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "bench_commands.h" 13 | #include "log.h" 14 | #include "prep_system.h" 15 | #include "proc_manip.h" 16 | #include "syscallers.h" 17 | 18 | static const test_prog_t test_progs[] = { 19 | {.cmdline = {"clients/square_evictions", "-n1", "-c0", "-e25", "-r"}}, 20 | }; 21 | 22 | static const int num_test_progs = sizeof test_progs / sizeof *test_progs; 23 | 24 | int main(int argc, char** argv) { 25 | int ret = 0; 26 | args_t args; 27 | parse_common_args(argc, argv, &args); 28 | int unpin_procs = args.unpin_procs; 29 | int procs_go_where = args.procs_go_where; 30 | int quit = args.quit; 31 | ret = prep_system(unpin_procs, procs_go_where); 32 | if(ret < 0) 33 | return ret; 34 | if (quit) 35 | return ret; 36 | run_benchmarks(test_progs, num_test_progs); 37 | ret = cleanup_system(unpin_procs); 38 | return ret; 39 | } 40 | -------------------------------------------------------------------------------- /clients/.gitignore: -------------------------------------------------------------------------------- 1 | /lockclient 2 | /lockserver-ng 3 | /rng_test 4 | /square_evictions 5 | -------------------------------------------------------------------------------- /clients/Makefile: -------------------------------------------------------------------------------- 1 | include ../flags.mk 2 | 3 | CPPFLAGS += \ 4 | -D_DEFAULT_SOURCE \ 5 | -D_POSIX_C_SOURCE=200809L \ 6 | -D_GNU_SOURCE \ 7 | 8 | CFLAGS += \ 9 | 10 | LDLIBS += \ 11 | -lrt \ 12 | 13 | # Add to LDLIBS of targets needing to use the DPDK driver. 14 | LINK_PMD_IXGBE := -Wl,--whole-archive ../external/dpdk/build/lib/librte_pmd_ixgbe.a -Wl,--no-whole-archive ../external/dpdk/build/lib/librte_hash.a 15 | 16 | .PHONY: all 17 | all: square_evictions lockserver-ng lockclient 18 | 19 | include ../external/modules.mk 20 | 21 | lockclient: LDLIBS += ../external/dpdk/build/lib/librte_ethdev.a ../external/dpdk/build/lib/librte_mbuf.a ../external/dpdk/build/lib/librte_eal.a ../external/dpdk/build/lib/librte_mempool.a ../external/dpdk/build/lib/librte_ring.a 22 | lockclient: LDLIBS += $(LINK_PMD_IXGBE) -ldl -lpthread 23 | lockclient: lockclient.o dpdk_wrapper.o realtime.o 24 | lockserver-ng: LDLIBS += ../external/dpdk/build/lib/librte_ethdev.a ../external/dpdk/build/lib/librte_mbuf.a ../external/dpdk/build/lib/librte_eal.a ../external/dpdk/build/lib/librte_mempool.a ../external/dpdk/build/lib/librte_ring.a 25 | lockserver-ng: LDLIBS += $(LINK_PMD_IXGBE) -ldl -lpthread 26 | lockserver-ng: lockserver-ng.o dpdk_wrapper.o realtime.o 27 | rng_test: rng.o 28 | square_evictions: llc.o movnt.o perf_poll.o realtime.o rng.o 29 | 30 | dpdk_wrapper.o: CFLAGS += -std=gnu99 -Wno-cast-qual 31 | dpdk_wrapper.o: CPPFLAGS += -include rte_config.h 32 | dpdk_wrapper.o: ../external/dpdk/build/lib/librte_ethdev.a 33 | dpdk_wrapper.o: dpdk_wrapper.h 34 | llc.o: llc.h 35 | lockclient.o: CFLAGS += -std=gnu99 36 | lockclient.o: CPPFLAGS += -include rte_config.h 37 | lockclient.o: ../external/dpdk/build/lib/librte_ethdev.a 38 | lockclient.o: dpdk_wrapper.h realtime.h 39 | lockserver-ng.o: CFLAGS += -std=gnu99 40 | lockserver-ng.o: CPPFLAGS += -include rte_config.h 41 | lockserver-ng.o: ../external/dpdk/build/lib/librte_ethdev.a 42 | lockserver-ng.o: dpdk_wrapper.h realtime.h 43 | movnt.o: movnt.h 44 | perf_poll.o: perf_poll.h syscallers.h 45 | rng.o: rng.h 46 | square_evictions.o: movnt.h perf_poll.h realtime.h rng.h 47 | 48 | %.s: %.c 49 | $(CC) $(CPPFLAGS) $(CFLAGS) -S $^ -o $@ 50 | -------------------------------------------------------------------------------- /clients/csvcombine: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | # This script is dedicated to Brandon. 4 | 5 | from itertools import zip_longest 6 | from sys import argv 7 | 8 | suffixes = { 9 | 'K': 1000, 10 | 'M': 1000000, 11 | 'G': 1000000000, 12 | 'T': 1000000000000, 13 | } 14 | 15 | def splitzip(iterable, splitfn): 16 | return zip_longest(*[splitfn(elem) for elem in iterable if elem != None]) 17 | 18 | def strmean(iterable, convfn): 19 | return sum([convfn(elem) for elem in iterable]) / len(iterable) 20 | 21 | def sciint(strng): 22 | if strng[-1].isalpha(): 23 | return int(strng[:-1]) * suffixes[strng[-1]] 24 | else: 25 | return int(strng) 26 | 27 | def main(): 28 | if len(argv) <= 2: 29 | print("USAGE: {} ...".format(argv[0])) 30 | exit(1) 31 | 32 | delim = argv[1] 33 | numfiles = len(argv) - 2 34 | fds = [open(fn) for fn in argv[2:]] 35 | files = splitzip([fd.read() for fd in fds], lambda x: x.splitlines()) 36 | for fd in fds: 37 | fd.close() 38 | 39 | for line in files: 40 | res = '' 41 | for col in splitzip(line, lambda x: x.split(delim)): 42 | if col.count(col[0]) == len(col): 43 | res += col[0] 44 | elif '.' in col[0]: 45 | precision = str(len(col[0]) - col[0].index('.') - 1) 46 | res += ('{:.' + precision + 'f}').format(strmean(col, float)) 47 | else: 48 | res += '{:.2f}'.format(strmean(col, sciint)) 49 | res += delim 50 | res = res[:-1] 51 | print(res) 52 | 53 | if __name__ == '__main__': 54 | main() 55 | -------------------------------------------------------------------------------- /clients/dist_a_mask_setup: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | sudo ../external/pqos/pqos -e 'llc:0=0x1;llc:1=0x2;llc:2=0x4;llc:3=0x8;llc:4=0x10;llc:5=0x20;llc:6=0x40;llc:7=0x80;llc:8=0x100;llc:9=0x200;llc:10=0x400;llc:11=0x800' 4 | -------------------------------------------------------------------------------- /clients/dpdk_wrapper.c: -------------------------------------------------------------------------------- 1 | #include "dpdk_wrapper.h" 2 | 3 | #include 4 | #include 5 | 6 | #define LINK_SPEED ETH_LINK_SPEED_10G 7 | #define MBUF_CACHE_SIZE 250 8 | #define NUM_MBUFS 8191 9 | #define RX_RING_SIZE 128 10 | #define TX_RING_SIZE 512 11 | 12 | static const struct rte_eth_conf PORT_CONF = { 13 | .link_speeds = LINK_SPEED, 14 | }; 15 | static const struct rte_eth_rxconf RX_CONF; 16 | static const struct rte_eth_txconf TX_CONF; 17 | static const char *DEFAULT_EAL_ARGS[] = { 18 | "--socket-mem=64", 19 | "--huge-unlink", 20 | }; 21 | #define DEFAULT_EAL_NARGS (sizeof DEFAULT_EAL_ARGS / sizeof *DEFAULT_EAL_ARGS) 22 | 23 | struct rte_mempool *dpdk_start(int argc, char **argv) { 24 | int leftoverc = 1 + argc - optind + DEFAULT_EAL_NARGS; 25 | const char *leftoverv[leftoverc]; 26 | leftoverv[0] = argv[0]; 27 | memcpy(leftoverv + 1, argv + optind, (argc - optind) * sizeof *leftoverv); 28 | memcpy(leftoverv + argc - optind + 1, DEFAULT_EAL_ARGS, DEFAULT_EAL_NARGS * sizeof *leftoverv); 29 | 30 | if(rte_eal_init(leftoverc, (char **) leftoverv) < 0) { 31 | perror_rte("Initializing EAL"); 32 | return NULL; 33 | } 34 | 35 | if(!rte_eth_dev_count()) { 36 | fputs("Error: number of ports must be nonzero\n", stderr); 37 | return NULL; 38 | } 39 | 40 | if(rte_eth_dev_configure(PORT, 1, 1, &PORT_CONF)) { 41 | perror_rte("Configuring Ethernet device"); 42 | return NULL; 43 | } 44 | 45 | struct rte_mempool *pool = rte_pktmbuf_pool_create("", NUM_MBUFS, MBUF_CACHE_SIZE, 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id()); 46 | if(!pool) { 47 | perror_rte("Allocating mbuf pool"); 48 | return NULL; 49 | } 50 | 51 | int errcode; 52 | if((errcode = rte_eth_rx_queue_setup(PORT, 0, RX_RING_SIZE, rte_eth_dev_socket_id(PORT), &RX_CONF, pool))) { 53 | perr("Setting up RX queue", -errcode); 54 | return NULL; 55 | } 56 | 57 | if((errcode = rte_eth_tx_queue_setup(PORT, 0, TX_RING_SIZE, rte_eth_dev_socket_id(PORT), &TX_CONF))) { 58 | perr("Setting up TX queue", -errcode); 59 | return NULL; 60 | } 61 | 62 | if((errcode = rte_eth_dev_start(PORT))) { 63 | perr("Starting Ethernet device", -errcode); 64 | return NULL; 65 | } 66 | 67 | puts("About to wait for init to complete..."); 68 | struct rte_eth_link status = {.link_status = ETH_LINK_DOWN}; 69 | while(status.link_status != ETH_LINK_UP) 70 | rte_eth_link_get(PORT, &status); 71 | printf("Link speed is %u Mbps.\n", status.link_speed); 72 | if(rte_eth_speed_bitflag(status.link_speed, 0) != LINK_SPEED) { 73 | fputs("It's the wrong speed, Gromit!\n", stderr); 74 | return NULL; 75 | } 76 | puts("Initialization complete!"); 77 | 78 | return pool; 79 | } 80 | -------------------------------------------------------------------------------- /clients/dpdk_wrapper.h: -------------------------------------------------------------------------------- 1 | #ifndef DPDK_WRAPPER_H_ 2 | #define DPDK_WRAPPER_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #define DEFAULT_LEN 1 9 | 10 | #define PORT 0 11 | 12 | static inline void perr(const char *s, int no) { 13 | fprintf(stderr, "%s: %s\n", s, rte_strerror(no)); 14 | } 15 | 16 | static inline void perror_rte(const char *s) { 17 | perr(s, rte_errno); 18 | } 19 | 20 | struct rte_mempool *dpdk_start(int argc, char**argv); 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /clients/llc.c: -------------------------------------------------------------------------------- 1 | #include "llc.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | static const char SYS_CACHE_PREFIX[] = "/sys/devices/system/cpu/cpu0/cache/"; 9 | static const char SYS_CACHE_SUFFIX_line_size[] = "/coherency_line_size"; 10 | static const char SYS_CACHE_SUFFIX_num_sets[] = "/number_of_sets"; 11 | static const char SYS_CACHE_SUFFIX_assoc_ways[] = "/ways_of_associativity"; 12 | 13 | static char *basepath = NULL; 14 | static size_t basepath_len = 0; 15 | 16 | static int filter_prefix_index(const struct dirent *candidate) { 17 | const char prefix[] = "index"; 18 | return !strncmp(candidate->d_name, prefix, sizeof prefix - 1); 19 | } 20 | 21 | static inline bool strncat_expand(char **dest, const char *src, size_t *n) { 22 | size_t addllen = strlen(src); 23 | *n += addllen; 24 | *dest = realloc(*dest, *n + 1); 25 | if(!*dest) 26 | return false; 27 | strncat(*dest, src, addllen); 28 | return true; 29 | } 30 | 31 | static inline int llc_accessor_helper(const char *suffix) { 32 | char *path = NULL; 33 | FILE *file = NULL; 34 | int ret; 35 | bool nonreent = false; 36 | 37 | if(!basepath) { 38 | nonreent = true; 39 | if(!llc_init()) { 40 | ret = LLC_ERROR; 41 | goto cleanup; 42 | } 43 | } 44 | 45 | path = strdup(basepath); 46 | if(!path) { 47 | perror("Duplicating shared base path"); 48 | ret = LLC_ERROR; 49 | goto cleanup; 50 | } 51 | 52 | if(!strncat_expand(&path, suffix, &basepath_len)) { 53 | perror("Concatenating onto copy of base path"); 54 | ret = LLC_ERROR; 55 | goto cleanup; 56 | } 57 | 58 | file = fopen(path, "r"); 59 | if(!file) { 60 | perror("Opening sysfs cache file"); 61 | ret = LLC_ERROR; 62 | goto cleanup; 63 | } 64 | 65 | if(fscanf(file, "%d", &ret) != 1) { 66 | perror("Parsing sysfs cache file contents"); 67 | ret = LLC_ERROR; 68 | goto cleanup; 69 | } 70 | 71 | cleanup: 72 | if(file) 73 | fclose(file); 74 | if(path) 75 | free(path); 76 | if(nonreent) 77 | llc_cleanup(); 78 | return ret; 79 | } 80 | 81 | #define GEN_LLC_ACCESSOR(property) \ 82 | int llc_##property(void) { \ 83 | return llc_accessor_helper(SYS_CACHE_SUFFIX_##property); \ 84 | } 85 | 86 | bool llc_init(void) { 87 | struct dirent **subdirs = NULL; 88 | bool ret = true; 89 | 90 | int numdirs = scandir(SYS_CACHE_PREFIX , &subdirs, filter_prefix_index, alphasort); 91 | if(numdirs < 0) { 92 | perror("Scanning sysfs cpu0"); 93 | ret = false; 94 | goto cleanup; 95 | } else if(numdirs == 0) { 96 | fprintf(stderr, "No cache levels for CPU 0\n"); 97 | goto cleanup; 98 | } 99 | 100 | basepath = strdup(SYS_CACHE_PREFIX); 101 | if(!basepath) { 102 | perror("Duplicating string constant"); 103 | ret = false; 104 | goto cleanup; 105 | } 106 | basepath_len = sizeof SYS_CACHE_PREFIX - 1; 107 | 108 | const char *llc_index = subdirs[numdirs - 1]->d_name; 109 | if(!strncat_expand(&basepath, llc_index, &basepath_len)) { 110 | perror("Concatenating on cache level index"); 111 | ret = false; 112 | goto cleanup; 113 | } 114 | 115 | cleanup: 116 | if(subdirs) { 117 | for(int index = 0; index < numdirs; ++index) 118 | free(subdirs[index]); 119 | free(subdirs); 120 | } 121 | return ret; 122 | } 123 | 124 | GEN_LLC_ACCESSOR(line_size) 125 | GEN_LLC_ACCESSOR(num_sets) 126 | GEN_LLC_ACCESSOR(assoc_ways) 127 | 128 | void llc_cleanup(void) { 129 | if(basepath) { 130 | free(basepath); 131 | basepath = NULL; 132 | basepath_len = 0; 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /clients/llc.h: -------------------------------------------------------------------------------- 1 | #ifndef LLC_H_ 2 | #define LLC_H_ 3 | 4 | #include 5 | 6 | #define LLC_ERROR -1 7 | 8 | bool llc_init(void); 9 | 10 | int llc_line_size(void); 11 | int llc_num_sets(void); 12 | int llc_assoc_ways(void); 13 | 14 | void llc_cleanup(void); 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /clients/lockclient.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "dpdk_wrapper.h" 7 | #include "realtime.h" 8 | 9 | //#define AVE_MEDIAN 10 | #define ITERATIONS 2000 11 | #define TIMEOUT_S 120 12 | #define WARMUP 600 13 | 14 | #define NUM_SAVED (ITERATIONS - WARMUP) 15 | 16 | typedef struct { 17 | struct ether_addr mac; 18 | useconds_t sleep; 19 | } args_t; 20 | 21 | static bool timeout; 22 | 23 | static void sigalrm_handler(int ign) { 24 | (void) ign; 25 | timeout = true; 26 | } 27 | 28 | static int experiment(args_t *args, struct rte_mempool *pool) { 29 | struct sigaction action = {.sa_handler = sigalrm_handler}; 30 | if(sigaction(SIGALRM, &action, NULL)) { 31 | perror("sigaction()"); 32 | return 1; 33 | } 34 | 35 | #ifdef AVE_MEDIAN 36 | clock_t samples[NUM_SAVED]; 37 | #else 38 | double ave = 0; 39 | #endif 40 | // Run one extra time and discard the results of the first trial. 41 | for(int times = 0; times < ITERATIONS; ++times) { 42 | struct rte_mbuf *packet = rte_pktmbuf_alloc(pool); 43 | if(!packet) { 44 | fputs("Couldn't allocate packet buffer\n", stderr); 45 | return 2; 46 | } 47 | size_t pkt_size = sizeof(struct ether_hdr); 48 | packet->data_len = pkt_size; 49 | packet->pkt_len = pkt_size; 50 | 51 | struct ether_hdr *frame = rte_pktmbuf_mtod(packet, struct ether_hdr *); 52 | rte_eth_macaddr_get(PORT, &frame->s_addr); 53 | frame->d_addr = args->mac; 54 | frame->ether_type = 0; 55 | 56 | struct rte_eth_dev_tx_buffer *buf = rte_zmalloc_socket("", RTE_ETH_TX_BUFFER_SIZE(1), 0, rte_eth_dev_socket_id(PORT)); 57 | if(rte_eth_tx_buffer_init(buf, RTE_ETH_TX_BUFFER_SIZE(1))) { 58 | fputs("Failed to allocate buffer\n", stderr); 59 | return 3; 60 | } 61 | 62 | while(true) { 63 | clock_t time = realtime(); 64 | if(!rte_eth_tx_buffer(PORT, 0, buf, packet)) { 65 | time = realtime(); 66 | if(!rte_eth_tx_buffer_flush(PORT, 0, buf)) { 67 | fputs("Data was really not actually transmitted\n", stderr); 68 | return 4; 69 | } 70 | } 71 | 72 | timeout = false; 73 | alarm(TIMEOUT_S); 74 | uint16_t got; 75 | while(!(got = rte_eth_rx_burst(PORT, 0, &packet, 1)) && !timeout); 76 | if(got) { 77 | clock_t duration = realtime() - time; 78 | if(times >= WARMUP) 79 | #ifdef AVE_MEDIAN 80 | samples[times - WARMUP] = duration; 81 | #else 82 | ave += duration; 83 | #endif 84 | 85 | printf("Completed after: %ld us\n", duration); 86 | if(args->sleep) 87 | usleep(args->sleep); 88 | break; 89 | } 90 | 91 | puts("Timed out; retrying..."); 92 | // But don't retry after the first trial! 93 | if(times) { 94 | fprintf(stderr, "Timed out on %dth iteration\n", times); 95 | return 5; 96 | } 97 | } 98 | } 99 | 100 | #ifdef AVE_MEDIAN 101 | qsort(samples, NUM_SAVED, sizeof *samples, comparetimes); 102 | double ave = samples[NUM_SAVED / 2]; 103 | #if NUM_SAVED % 2 == 0 104 | ave += samples[NUM_SAVED / 2 - 1]; 105 | ave /= 2; 106 | #endif 107 | #else 108 | ave /= NUM_SAVED; 109 | #endif 110 | printf("Average: %f us\n", ave); 111 | return 0; 112 | } 113 | 114 | int main(int argc, char **argv) { 115 | args_t args = { 116 | .mac = {.addr_bytes = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}, 117 | .sleep = 0, 118 | }; 119 | 120 | int each_arg; 121 | while((each_arg = getopt(argc, argv, "m:s:")) != -1) 122 | switch(each_arg) { 123 | case 'm': 124 | if(sscanf(optarg, "%" SCNx8 ":%" SCNx8 ":%" SCNx8 ":%" SCNx8 ":%" SCNx8 ":%" SCNx8, args.mac.addr_bytes, args.mac.addr_bytes + 1, 125 | args.mac.addr_bytes + 2, args.mac.addr_bytes + 3, args.mac.addr_bytes + 4, args.mac.addr_bytes + 5) != 6) { 126 | perror("Parsing provided MAC"); 127 | return 127; 128 | } 129 | break; 130 | case 's': 131 | if(sscanf(optarg, "%u", &args.sleep) != 1) { 132 | perror("Parsing sleep seconds"); 133 | return 127; 134 | } 135 | break; 136 | default: 137 | printf("USAGE: %s [-m #] [-s #] [-- ...]\n", argv[0]); 138 | printf( 139 | " -m #: destination MAC address\n" 140 | " -s #: microseconds to sleep between successful requests\n" 141 | ); 142 | return 127; 143 | } 144 | 145 | struct rte_mempool *pool = NULL; 146 | if(!(pool = dpdk_start(argc, argv))) 147 | return 127; 148 | 149 | return experiment(&args, pool); 150 | } 151 | -------------------------------------------------------------------------------- /clients/lockserver-ng.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "dpdk_wrapper.h" 13 | #include "realtime.h" 14 | 15 | //#define AVE_MEDIAN 16 | #define TIMING_BUFFER_LEN 5000 17 | #define WARMUP 600 18 | 19 | typedef struct { 20 | int len; 21 | } args_t; 22 | 23 | static bool loop = true; 24 | static int iter = 0; 25 | #ifdef AVE_MEDIAN 26 | static clock_t times[TIMING_BUFFER_LEN]; 27 | #else 28 | static double ave; 29 | #endif 30 | 31 | static void sigterm_handler(int signal) { 32 | (void) signal; 33 | iter -= WARMUP; 34 | if(iter) { 35 | #ifdef AVE_MEDIAN 36 | qsort(times, iter, sizeof *times, comparetimes); 37 | double ave = times[iter / 2]; 38 | if(iter % 2 == 0) { 39 | ave += times[iter / 2 - 1]; 40 | ave /= 2; 41 | } 42 | #else 43 | ave /= iter; 44 | #endif 45 | printf("Average: %f us\n", ave); 46 | } 47 | exit(!iter); 48 | } 49 | 50 | static void sigint_handler(int signal) { 51 | (void) signal; 52 | loop = false; 53 | } 54 | 55 | static void paddr(struct ether_addr *mac) { 56 | printf("%02x:%02x:%02x:%02x:%02x:%02x\n", 57 | mac->addr_bytes[0], mac->addr_bytes[1], mac->addr_bytes[2], 58 | mac->addr_bytes[3], mac->addr_bytes[4], mac->addr_bytes[5]); 59 | } 60 | 61 | static void ptrchase_setup(uintptr_t *arr, int len) { 62 | if(len == 1) { 63 | *arr = (uintptr_t) arr; 64 | return; 65 | } 66 | 67 | #ifndef NDEBUG 68 | for(int idx = 0; idx < len; ++idx) 69 | assert(!arr[idx]); 70 | #endif 71 | 72 | srand(time(NULL)); 73 | uintptr_t *curr = arr; 74 | for(int count = 1; count < len; ++count) { 75 | int idx = curr - arr; 76 | int tgt; 77 | while((tgt = rand() % len) == idx || arr[tgt]); 78 | *curr = (uintptr_t) (arr + tgt); 79 | curr = arr + tgt; 80 | } 81 | *curr = (uintptr_t) arr; 82 | 83 | #ifndef NDEBUG 84 | for(int idx = 0; idx < len; ++idx) { 85 | assert(!(arr[idx] & 0x1)); 86 | assert(arr[idx] >= (uintptr_t) arr); 87 | assert(arr[idx] < (uintptr_t) (arr + len)); 88 | assert(arr[idx] != (uintptr_t) (arr + idx)); 89 | } 90 | 91 | uintptr_t *cur = arr; 92 | for(int count = 1; count < len; ++count) { 93 | cur = (uintptr_t *) *cur; 94 | assert(cur != arr); 95 | } 96 | assert(*cur == (uintptr_t) arr); 97 | #endif 98 | } 99 | 100 | static int experiment(args_t *args) { 101 | int ret = 0; 102 | uintptr_t *arr = mmap(0, args->len * sizeof(*arr), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB | MAP_POPULATE, -1, 0); 103 | if(!arr || arr == MAP_FAILED) { 104 | perror("Allocating array"); 105 | return 1; 106 | } 107 | puts("Setting up pointers for chasing..."); 108 | ptrchase_setup(arr, args->len); 109 | 110 | struct sigaction sigterm = {.sa_handler = sigterm_handler}; 111 | struct sigaction sigint = {.sa_handler = sigint_handler}; 112 | if(sigaction(SIGTERM, &sigterm, NULL) || sigaction(SIGINT, &sigint, NULL)) { 113 | perror("Installing sigint handler"); 114 | ret = 1; 115 | goto cleanup; 116 | } 117 | 118 | struct ether_addr laddr; 119 | rte_eth_macaddr_get(PORT, &laddr); 120 | printf("Listening on MAC: "); 121 | paddr(&laddr); 122 | 123 | while(loop) { 124 | clock_t thistime; 125 | 126 | assert(iter <= TIMING_BUFFER_LEN + 1); 127 | struct rte_mbuf *packet = NULL; 128 | while(true) { 129 | if(!loop) 130 | goto stoploop; 131 | uint16_t ct = rte_eth_rx_burst(PORT, 0, &packet, 1); 132 | if(ct) { 133 | struct ether_hdr *eth = rte_pktmbuf_mtod(packet, struct ether_hdr *); 134 | bool addressed_to_me = false; 135 | addressed_to_me = is_same_ether_addr(ð->d_addr, &laddr); 136 | thistime = realtime(); 137 | 138 | if(addressed_to_me) 139 | break; 140 | } 141 | } 142 | 143 | uintptr_t *cur = arr; 144 | while((cur = (uintptr_t *) *cur) != arr); 145 | 146 | struct ether_hdr *eth = rte_pktmbuf_mtod(packet, struct ether_hdr *); 147 | eth->d_addr = eth->s_addr; 148 | eth->s_addr = laddr; 149 | 150 | clock_t delta = realtime() - thistime; 151 | printf("Computed in: %ld us\n", delta); 152 | if(iter >= WARMUP) { 153 | #ifdef AVE_MEDIAN 154 | assert(iter - WARMUP < TIMING_BUFFER_LEN); 155 | times[iter - WARMUP] = delta; 156 | #else 157 | ave += delta; 158 | #endif 159 | } 160 | ++iter; 161 | 162 | if(!rte_eth_tx_burst(PORT, 0, &packet, 1)) { 163 | fputs("Data wasn't actually transmitted\n", stderr); 164 | ret = 2; 165 | goto cleanup; 166 | } 167 | } 168 | stoploop: 169 | 170 | cleanup: 171 | munmap(arr, args->len); 172 | return ret; 173 | } 174 | 175 | static bool parse_arg_arg(int *dest, char flag, int min) { 176 | int val; 177 | 178 | if(sscanf(optarg, "%d", &val) != 1) { 179 | fprintf(stderr, "%c: Unexpected subargument '%s'\n", flag, optarg); 180 | return false; 181 | } else if(val < min) { 182 | fprintf(stderr, "%c: Expected gte %d but got '%d'\n", flag, min, val); 183 | return false; 184 | } 185 | 186 | *dest = val; 187 | return true; 188 | } 189 | 190 | int main(int argc, char **argv) { 191 | args_t args = { 192 | .len = DEFAULT_LEN, 193 | }; 194 | 195 | int each_arg; 196 | while((each_arg = getopt(argc, argv, "l:")) != -1) 197 | switch(each_arg) { 198 | case 'l': 199 | if(!parse_arg_arg(&args.len, 'l', 1)) 200 | return 127; 201 | break; 202 | default: 203 | printf("USAGE: %s [-l #] [-- ...]\n", argv[0]); 204 | printf( 205 | " -l #: LENGTH to traverse (octawords, default %d)\n", 206 | DEFAULT_LEN); 207 | return 127; 208 | } 209 | 210 | if(!dpdk_start(argc, argv)) 211 | return 127; 212 | 213 | return experiment(&args); 214 | } 215 | -------------------------------------------------------------------------------- /clients/movnt.h: -------------------------------------------------------------------------------- 1 | #ifndef MOVNT_H_ 2 | #define MOVNT_H_ 3 | 4 | #include 5 | 6 | void movntq4(uint64_t *dest, uint64_t a, uint64_t b, uint64_t c, uint64_t d); 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /clients/movnt.s: -------------------------------------------------------------------------------- 1 | .globl movntq4 2 | # %rdi : uint64_t *dest 3 | # %rsi : uint64_t a 4 | # %rdx : uint64_t b 5 | # %rcx : uint64_t c 6 | # %r8 : uint64_t d 7 | movntq4: 8 | movnti %rsi, 0(%rdi) 9 | movnti %rdx, 8(%rdi) 10 | movnti %rcx, 16(%rdi) 11 | movnti %r8, 24(%rdi) 12 | ret 13 | -------------------------------------------------------------------------------- /clients/pcm.cpp_v2.10.patch: -------------------------------------------------------------------------------- 1 | 153c153 2 | < cout << " Core (SKT) | EXEC | IPC | FREQ | AFREQ | L3MISS | L2MISS | L3HIT | L2HIT | L3MPI | L2MPI |"; 3 | --- 4 | > cout << " Core (SKT) | INST | EXEC | IPC | FREQ | AFREQ | L3MISS | L2MISS | L3HIT | L2HIT | L3MPI | L2MPI |"; 5 | 176c176,177 6 | < " " << getExecUsage(cstates1[i], cstates2[i]) << 7 | --- 8 | > " " << setw(10) << getInstructionsRetired(cstates1[i], cstates2[i]) << 9 | > " " << getExecUsage(cstates1[i], cstates2[i]) << 10 | 483a485 11 | > cout << "Socket" << i << ";;;;;;;;;;;;;"; 12 | 485,487c487,491 13 | < cout << "Socket" << i << ";;;;;;;;;;;;;;"; 14 | < else 15 | < cout << "Socket" << i << ";;;;;;;;;;;;;"; 16 | --- 17 | > cout << ";"; 18 | > if (m->CoreLocalMemoryBWMetricAvailable()) 19 | > cout << ";"; 20 | > if (m->CoreRemoteMemoryBWMetricAvailable()) 21 | > cout << ";"; 22 | 557c561 23 | < else 24 | --- 25 | > else { 26 | 558a563,569 27 | > if (m->L3CacheOccupancyMetricAvailable()) 28 | > cout << ";"; 29 | > if (m->CoreLocalMemoryBWMetricAvailable()) 30 | > cout << ";"; 31 | > if (m->CoreRemoteMemoryBWMetricAvailable()) 32 | > cout << ";"; 33 | > } 34 | 562a574,575 35 | > 36 | > cout << ";"; 37 | 576c589 38 | < cout << "LMB"; 39 | --- 40 | > cout << "LMB;"; 41 | 622c635 42 | < cout << "LMB"; 43 | --- 44 | > cout << "LMB;"; 45 | 691c704 46 | < cout << "EXEC;IPC;FREQ;AFREQ;L3MISS;L2MISS;L3HIT;L2HIT;L3MPI;L2MPI;"; 47 | --- 48 | > cout << "INST;EXEC;IPC;FREQ;AFREQ;L3MISS;L2MISS;L3HIT;L2HIT;L3MPI;L2MPI;"; 49 | 695c708 50 | < cout << "LMB"; 51 | --- 52 | > cout << "LMB;"; 53 | 698c711 54 | < cout << "READ;WRITE;TEMP;"; 55 | --- 56 | > //cout << "READ;WRITE;TEMP;"; 57 | 762c775 58 | < cout << "N/A"; 59 | --- 60 | > cout << "N/A;"; 61 | 904c917,918 62 | < cout << getExecUsage(cstates1[i], cstates2[i]) << 63 | --- 64 | > cout << getInstructionsRetired(cstates1[i], cstates2[i]) << 65 | > ';' << getExecUsage(cstates1[i], cstates2[i]) << 66 | -------------------------------------------------------------------------------- /clients/perf_poll.c: -------------------------------------------------------------------------------- 1 | #include "perf_poll.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "syscallers.h" 10 | 11 | int perf_poll_init(size_t count, const struct perf_event_attr *counters) { 12 | assert(counters); 13 | 14 | int fd = -1; 15 | 16 | for(unsigned idx = 0; idx < count; ++idx) { 17 | int tfd = perf_event_open(counters + idx, 0, -1, fd, 0); 18 | if(tfd == -1) { 19 | int terrno = errno; 20 | char desc[] = "Initializing perf counter \0\0"; 21 | sprintf(strchr(desc, '\0'), "%u", idx); 22 | errno = terrno; 23 | puts(desc); 24 | return tfd; 25 | } 26 | if(fd == -1) 27 | fd = tfd; 28 | } 29 | 30 | return fd; 31 | } 32 | 33 | bool perf_poll_start(int fd) { 34 | assert(fd > fileno(stderr)); 35 | return ioctl(fd, PERF_EVENT_IOC_ENABLE) >= 0; 36 | } 37 | 38 | bool perf_poll_stop(int fd) { 39 | assert(fd > fileno(stderr)); 40 | return ioctl(fd, PERF_EVENT_IOC_DISABLE) >= 0; 41 | } 42 | -------------------------------------------------------------------------------- /clients/perf_poll.h: -------------------------------------------------------------------------------- 1 | #ifndef PERF_POLL_H_ 2 | #define PERF_POLL_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | int perf_poll_init(size_t count, const struct perf_event_attr *counters); 9 | bool perf_poll_start(int fd); 10 | bool perf_poll_stop(int fd); 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /clients/rdtscp.h: -------------------------------------------------------------------------------- 1 | #ifndef RDTSCP_H_ 2 | #define RDTSCP_H_ 3 | 4 | #include 5 | 6 | inline uint64_t rdtscp(void) { 7 | uint32_t cycles_low, cycles_high; 8 | __asm volatile( 9 | "RDTSCP\n\t" 10 | "mov %%edx, %0\n\t" 11 | "mov %%eax, %1\n\t" 12 | : "=r" (cycles_high), "=r" (cycles_low) 13 | ); 14 | return ((uint64_t)cycles_high << 32 | cycles_low); 15 | } 16 | #endif 17 | -------------------------------------------------------------------------------- /clients/realtime.c: -------------------------------------------------------------------------------- 1 | #include "realtime.h" 2 | 3 | clock_t realtime(void) { 4 | struct timespec ns; 5 | clock_gettime(CLOCK_REALTIME, &ns); 6 | return ns.tv_sec * 1000000 + ns.tv_nsec / 1000; 7 | } 8 | 9 | int comparetimes(const void *first, const void *second) { 10 | return *(const clock_t *) first - *(const clock_t *) second; 11 | } 12 | -------------------------------------------------------------------------------- /clients/realtime.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | clock_t realtime(void); 4 | 5 | int comparetimes(const void *first, const void *second); 6 | -------------------------------------------------------------------------------- /clients/rng.c: -------------------------------------------------------------------------------- 1 | #include "rng.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | struct rng_state { 9 | unsigned last; 10 | unsigned coeff; 11 | unsigned incr; 12 | unsigned mod; 13 | }; 14 | 15 | static inline bool coprime(unsigned a, size_t bnfacts, const int *bpfacts) { 16 | unsigned iters; 17 | for(iters = 0; iters < bnfacts; ++iters) { 18 | if(a % bpfacts[iters] == 0) 19 | break; 20 | } 21 | return iters == bnfacts; 22 | } 23 | 24 | // Picks parameters compliant with Hull-Dobell Thm. to achieve full cycle 25 | rng_t *rng_lcfc_init(unsigned period, size_t nfactors, const int *pfactors) { 26 | unsigned incr; 27 | do { 28 | do 29 | incr = rand() % period; 30 | while(incr == 0 || incr % period == 1 || incr % period == period - 1); 31 | } while(!coprime(incr, nfactors, pfactors)); 32 | return rng_lcfc_init_incr(period, nfactors, pfactors, incr); 33 | } 34 | 35 | // Ensures parameters are compliant with Hull-Dobell Thm. 36 | rng_t *rng_lcfc_init_incr(unsigned period, size_t nfactors, const int *pfactors, unsigned incr) { 37 | assert(period >= 5); 38 | assert(nfactors); 39 | assert(pfactors); 40 | 41 | if(!coprime(incr, nfactors, pfactors)) 42 | return NULL; 43 | 44 | static bool seeded = false; 45 | if(!seeded) 46 | srand(time(NULL)); 47 | 48 | rng_t *res = malloc(sizeof *res); 49 | if(!res) 50 | return NULL; 51 | 52 | res->last = rand(); 53 | 54 | res->coeff = 4; 55 | for(unsigned idx = 0; idx < nfactors; ++idx) 56 | res->coeff *= pfactors[idx]; 57 | res->coeff += 1; 58 | 59 | res->incr = incr; 60 | 61 | res->mod = period; 62 | 63 | return res; 64 | } 65 | 66 | void rng_lcfc_clean(rng_t *victim) { 67 | if(victim) 68 | free(victim); 69 | } 70 | 71 | unsigned rng_lcfc(rng_t *ctxt) { 72 | return ctxt->last = (ctxt->coeff * ctxt->last + ctxt->incr) % ctxt->mod; 73 | } 74 | -------------------------------------------------------------------------------- /clients/rng.h: -------------------------------------------------------------------------------- 1 | #ifndef RNG_H_ 2 | #define RNG_H_ 3 | 4 | #include 5 | 6 | typedef struct rng_state rng_t; 7 | 8 | // pfactors must contain all prime factors of period, which must be at least 5 9 | rng_t *rng_lcfc_init(unsigned period, size_t nfactors, const int *pfactors); 10 | 11 | // incr must be coprime with period 12 | rng_t *rng_lcfc_init_incr(unsigned period, size_t nfactors, const int *pfactors, unsigned incr); 13 | 14 | void rng_lcfc_clean(rng_t *victim); 15 | 16 | unsigned rng_lcfc(rng_t *ctxt); 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /clients/rng_test.c: -------------------------------------------------------------------------------- 1 | #include "rng.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | int main(int argc, char **argv) { 8 | if(argc < 4) { 9 | printf("USAGE: %s ...\n", argv[0]); 10 | return 1; 11 | } 12 | 13 | rng_t *lcfc = NULL; 14 | bool *seen = NULL; 15 | int ret = 0; 16 | unsigned period = atoi(argv[1]); 17 | size_t nfactors = atoi(argv[2]); 18 | 19 | if(nfactors != (unsigned) argc - 3) { 20 | fprintf(stderr, " must be trailing args count (%d)\n", argc - 3); 21 | return 1; 22 | } 23 | 24 | int pfactors[nfactors]; 25 | for(unsigned idx = 0; idx < nfactors; ++idx) 26 | pfactors[idx] = atoi(argv[idx + 3]); 27 | 28 | lcfc = rng_lcfc_init(period, nfactors, pfactors); 29 | if(!lcfc) { 30 | perror("rng_lcfc_init()"); 31 | ret = 1; 32 | goto cleanup; 33 | } 34 | 35 | seen = calloc(period, sizeof *seen); 36 | if(!seen) { 37 | perror("calloc()"); 38 | ret = 1; 39 | goto cleanup; 40 | } 41 | 42 | for(unsigned iter = 0; iter < period; ++iter) { 43 | unsigned rn = rng_lcfc(lcfc); 44 | if(rn >= period) { 45 | printf("Test FAILED: result %u greater than period!\n", rn); 46 | ret = 1; 47 | goto cleanup; 48 | } 49 | if(seen[rn]) { 50 | printf("Test FAILED: %u seen twice within a single period!\n", rn); 51 | ret = 1; 52 | goto cleanup; 53 | } 54 | seen[rn] = true; 55 | } 56 | puts("Test passed."); 57 | 58 | cleanup: 59 | if(seen) 60 | free(seen); 61 | if(lcfc) 62 | rng_lcfc_clean(lcfc); 63 | return ret; 64 | } 65 | -------------------------------------------------------------------------------- /clients/square_evictions_csv: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | entry_already_exists() { 4 | "$jaguar_script" get "$outfile_json" "$1" >/dev/null 2>&1 5 | } 6 | 7 | add_legend_entry() { 8 | local switch="$1" 9 | local terse="$2" 10 | local description="$3" 11 | local unit="$4" 12 | if ! entry_already_exists "$legendpre.$switch" 13 | then 14 | "$jaguar_script" set "$outfile_json" "$legendpre.$switch.terse" string "$terse" 15 | "$jaguar_script" set "$outfile_json" "$legendpre.$switch.description" string "$description" 16 | "$jaguar_script" set "$outfile_json" "$legendpre.$switch.unit" string "$unit" 17 | fi 18 | } 19 | 20 | jaguar_script="`dirname "$0"`/../jaguar/jaguar" 21 | if [ ! -e "$jaguar_script" ] 22 | then 23 | echo "ERROR: Couldn't find jaguar script. You didn't pass me to a shell instead of executing me directly, did you?" >&2 24 | exit 1 25 | fi 26 | if [ $# -lt 2 ] 27 | then 28 | echo "USAGE: $0 [arguments]..." 29 | exit 1 30 | fi 31 | outfile_json="$1" 32 | series="$2" 33 | shift 2 34 | 35 | [ -e "$outfile_json" ] || "$jaguar_script" init "$outfile_json" 36 | 37 | legendpre="legend.args.square_evictions" 38 | datapre="data.$series" 39 | types="string,integer" 40 | header="" 41 | 42 | # TODO: custfacts should be saved as a string, but we currently only do ints 43 | seen_hugepages="false" 44 | seen_randomize="false" 45 | seen_singlerng="false" 46 | seen_norngspin="false" 47 | seen_custfacts="false" 48 | seen_memcheck="false" 49 | seen_cpucheck="false" 50 | seen_logprfchr="false" 51 | seen_profmemac="false" 52 | seen_daemonize="false" 53 | 54 | add_legend_entry -h "hugepages" "use hugepages" 55 | add_legend_entry -r "randomize" "random traversal order" 56 | add_legend_entry -s "single_rng" "use the same rng for all phases" 57 | add_legend_entry -q "dont_spin_rng" "reject out-of-range rng results" 58 | add_legend_entry -f "custom_rng_facts" "provided custom prime factors" 59 | add_legend_entry -w "memcheck" "sanity-check memory throughput" 60 | add_legend_entry -v "cpucheck" "sanity-check guess clock speed" 61 | add_legend_entry -l "perf" "record perf data" 62 | add_legend_entry -m "rdtscp" "profile memory accesses with rdtscp" 63 | add_legend_entry -i "daemonize" "perform traversals on signal" 64 | 65 | while [ $# -gt 0 ] 66 | do 67 | lastheader="$header" 68 | 69 | switch="$1" 70 | shift 71 | 72 | case "$switch" in 73 | -n*) 74 | header="$header\n-n" 75 | add_legend_entry -n "periods" "number of periods" 76 | ;; 77 | -p*) 78 | header="$header\n-p" 79 | add_legend_entry -p "passes_per_phase" "passes per phase" 80 | ;; 81 | -c*) 82 | header="$header\n-c" 83 | add_legend_entry -c "contracted_percent" "small traversal subset" "% of a cache way" 84 | ;; 85 | -e*) 86 | header="$header\n-e" 87 | add_legend_entry -e "expanded_percent" "large traversal/allocation" "% of a cache way" 88 | ;; 89 | -h*) 90 | seen_hugepages="true" 91 | ;; 92 | -r*) 93 | seen_randomize="true" 94 | 95 | case "$1" in 96 | -*) 97 | ;; 98 | *) 99 | shift 100 | ;; 101 | esac 102 | continue 103 | ;; 104 | -q*) 105 | seen_norngspin="true" 106 | ;; 107 | -f*) 108 | seen_custfacts="true" 109 | 110 | case "$1" in 111 | -*) 112 | ;; 113 | *) 114 | shift 115 | ;; 116 | esac 117 | continue 118 | ;; 119 | -s*) 120 | seen_singlerng="true" 121 | ;; 122 | -w*) 123 | seen_memcheck="true" 124 | ;; 125 | -v*) 126 | seen_cpucheck="true" 127 | ;; 128 | -l*) 129 | seen_logprfchr="true" 130 | 131 | case "$1" in 132 | -*) 133 | ;; 134 | *) 135 | shift 136 | ;; 137 | esac 138 | continue 139 | ;; 140 | -j*) 141 | header="$header\n-j" 142 | add_legend_entry -j "perf_stride" "perf logging frequency" 143 | ;; 144 | -m*) 145 | seen_profmemac="true" 146 | ;; 147 | -a*) 148 | header="$header\n-a" 149 | add_legend_entry -a "accesses_per_activation" "accesses per activation" 150 | ;; 151 | -b*) 152 | header="$header\n-b" 153 | add_legend_entry -b "rng_skip" "initial random numbers to skip" 154 | ;; 155 | -i*) 156 | seen_daemonize="true" 157 | ;; 158 | *) 159 | echo "Unexpected switch: $switch" 160 | exit 1 161 | ;; 162 | esac 163 | 164 | suffix="`printf %s "$switch" | sed 's/..\(.*\)/\1/'`" 165 | case "$suffix" in 166 | [a-z]*) 167 | set -- "-$suffix" "$@" 168 | ;; 169 | *) 170 | if [ "$header" = "$lastheader" ] 171 | then 172 | continue 173 | fi 174 | 175 | if [ -n "$suffix" ] 176 | then 177 | header="$header,$suffix" 178 | else 179 | header="$header,$1" 180 | shift 181 | fi 182 | ;; 183 | esac 184 | done 185 | 186 | "$jaguar_script" set "$outfile_json" "$datapre.type" string square_evictions 187 | echo "string,boolean\nname,value\n-h,$seen_hugepages\n-r,$seen_randomize\n-s,$seen_singlerng\n-q,$seen_norngspin\n-f,$seen_custfacts\n-w,$seen_memcheck\n-v,$seen_cpucheck\n-l,$seen_logprfchr\n-m,$seen_profmemac\n-i,$seen_daemonize" | "$jaguar_script" set "$outfile_json" "$datapre.args" array - 188 | if [ -n "$header" ] 189 | then 190 | echo "$types\nname,value$header" | sed 's/^,//' | "$jaguar_script" set "$outfile_json" "$datapre.args[]" - 191 | fi 192 | -------------------------------------------------------------------------------- /clients/square_evictions_wrapper: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ -n "$CATBENCH_JAGFILE" ] 4 | then 5 | if ! "`dirname "$0"`/square_evictions_csv" "$CATBENCH_JAGFILE" "$@" 6 | then 7 | echo "ERROR: Failed to record argument data!" >&2 8 | exit 1 9 | fi 10 | shift 11 | else 12 | echo "WARN: Log filename did not reach target wrapper!" >&2 13 | fi 14 | "`dirname "$0"`/square_evictions" "$@" 15 | -------------------------------------------------------------------------------- /clients/summarize_helpers.sh: -------------------------------------------------------------------------------- 1 | tool="" 2 | toolargs="" 3 | 4 | driver_init() { 5 | builddeps "$1" 6 | startlogging "$2" 7 | } 8 | 9 | builddeps() { 10 | if ! make "$1" 11 | then 12 | echo "Failed to build target utility!" 13 | exit 1 14 | fi 15 | if ! make -C.. external/pqos/pqos 16 | then 17 | echo "Failed to build pqos utility!" 18 | exit 1 19 | fi 20 | } 21 | 22 | startlogging() { 23 | exec >"$1" 2>&1 24 | } 25 | 26 | logstatus() { 27 | runlog git log --oneline -1 28 | runlog git status -uno 29 | runlog git diff HEAD 30 | echo === 31 | echo 32 | 33 | runlog sudo ../external/pqos/pqos -s 34 | } 35 | 36 | runtrial() { 37 | local aftymask="$1" 38 | shift 39 | 40 | if [ -n "$tool" ] 41 | then 42 | eval runlog sudo sh -c \'PATH=\"$PATH\" pcm.x $toolargs -- taskset \"$aftymask\" "$@"\' 43 | else 44 | runlog perf stat -e cache-misses,cache-references $toolargs taskset "$aftymask" "$@" 45 | fi 46 | } 47 | 48 | runlog() { 49 | echo "\$ $@" 50 | "$@" 51 | } 52 | -------------------------------------------------------------------------------- /clients/summarize_slobro: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | . ./summarize_helpers.sh 4 | 5 | if [ $# -lt 1 ] 6 | then 7 | echo "USAGE: $0 " 8 | exit 1 9 | fi 10 | 11 | logprefix="$1" 12 | logfile="$logprefix.log" 13 | logfile_a="${logprefix}_a.csv" 14 | logfile_b="${logprefix}_b.csv" 15 | tool="pcm" 16 | 17 | truncate -s0 "$logfile_a" 18 | truncate -s0 "$logfile_b" 19 | 20 | driver_init square_evictions "$logfile" 21 | sudo ../external/pqos/pqos -e "llc:0=0xffc;llc:1=0x1;llc:2=0x2" 22 | sudo ../external/pqos/pqos -a "llc:1=0,1;llc:2=2" 23 | logstatus 24 | 25 | testprogargs="-n1 -c100 -e100 -hr" 26 | runlog taskset 0x1 ./square_evictions $testprogargs & 27 | 28 | sleep 2 29 | 30 | toolargs="0.001 -csv=\"$logfile_a\" -m" 31 | runtrial 0x2 ./square_evictions $testprogargs \& 32 | 33 | toolargs="0.001 -csv=\"$logfile_b\" -m" 34 | runtrial 0x4 ./square_evictions $testprogargs \& 35 | 36 | sleep 10 37 | 38 | runlog date +"%F;%T.%3N" 39 | runlog sudo ../external/pqos/pqos -a "llc:2=0" 40 | runlog date +"%F;%T.%3N" 41 | 42 | wait 43 | -------------------------------------------------------------------------------- /clients/summarize_square_evictions: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | . ./summarize_helpers.sh 4 | 5 | if [ $# -lt 2 -o \( $# -ge 3 -a "$3" != "pcm" \) ] 6 | then 7 | echo "USAGE: $0 <0xmask> [pcm]" 8 | exit 1 9 | fi 10 | 11 | logfile="$1" 12 | mask="$2" 13 | tool="$3" 14 | 15 | driver_init square_evictions "$logfile" 16 | logstatus 17 | 18 | seq 20 20 200 | while read ce 19 | do 20 | runtrial "$mask" ./square_evictions -n1 -c"$ce" -e"$ce" -hr 21 | done 22 | -------------------------------------------------------------------------------- /clients/summarize_square_wave: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | . ./summarize_helpers.sh 4 | 5 | if [ $# -lt 2 -o \( $# -ge 3 -a -n "$3" -a "$3" != "huge" \) ] 6 | then 7 | echo "USAGE: $0 <0xmask> [huge] [contracted %] [expanded %]" 8 | exit 1 9 | fi 10 | 11 | logfile="$1" 12 | mask="$2" 13 | huge="" 14 | if [ $# -ge 3 -a -n "$3" ] 15 | then 16 | huge="-h" 17 | fi 18 | contract="50" 19 | if [ $# -ge 4 ] 20 | then 21 | contract="$4" 22 | fi 23 | expand="200" 24 | if [ $# -ge 5 ] 25 | then 26 | expand="$5" 27 | fi 28 | tool="pcm" 29 | toolargs="0.5" 30 | 31 | driver_init square_evictions "$logfile" 32 | logstatus 33 | 34 | [ -n "$tool" ] && runlog sudo sh -c 'echo 1 >/proc/sys/vm/nr_hugepages' 35 | runtrial "$mask" ./square_evictions -c"$contract" -e"$expand" -r "$huge" 36 | -------------------------------------------------------------------------------- /clients/syscallers.h: -------------------------------------------------------------------------------- 1 | ../syscallers.h -------------------------------------------------------------------------------- /clients/tocsv_pcm: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ $# -lt 3 ] 4 | then 5 | echo "USAGE: $0 " 6 | exit 1 7 | fi 8 | 9 | infile="$1" 10 | outfile="$2" 11 | core="$3" 12 | 13 | grep "^\\s\\+Core (" "$infile" | head -n1 | tr -d "|" | tr -s " " | cut -d" " -f2- | tr " " , >"$outfile" 14 | grep "^\\s\\+$core" "$infile" | sed 's/\([0-9]\) \([A-Z]\)/\1\2/g' | tr -s " " | cut -d" " -f2- | tr " " , >>"$outfile" 15 | -------------------------------------------------------------------------------- /cost-analysis-result.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import argparse; 4 | import os; 5 | import sys; 6 | import matplotlib as mpl; 7 | mpl.use('Agg'); 8 | import matplotlib.pyplot as plt; 9 | import json; 10 | from matplotlib import ticker; 11 | import numpy as np 12 | 13 | filename="cost-analysis-result.pdf"; 14 | 15 | def graph(): 16 | fig = plt.figure(figsize=(8, 4)); 17 | ax = fig.add_subplot(1,1,1); 18 | 19 | temp = list(); 20 | range_top = 2000; 21 | t_total = np.arange(0, range_top, 1); 22 | temp.append(ax.plot(t_total, t_total, 'm:', linewidth=4.0, label="NoContention")); 23 | 24 | baseline_mite = 5.15; 25 | #series_tuples = get_tuples(filename, slabels, xlabel, ylabels); 26 | # Contention 27 | contention_mite = 4.85 28 | #contention_mite = 4.33 29 | em = 0.951; 30 | ek = contention_mite / baseline_mite; 31 | n = 1000; 32 | range_bottom = n / ek * em; 33 | 34 | t_bottom = np.arange(0, range_bottom, 1); 35 | t_top = np.arange(range_bottom, range_top, 1); 36 | temp.append(ax.plot(t_bottom, t_bottom / em - (t_bottom / em) * ek, 'r--', linewidth=2.0, label="Contention-NoCAT")); 37 | temp.append(ax.plot(t_top, (n / ek - n) + (t_top - (n / ek) * em), 'r--', linewidth=2.0));#, label="Contention-NoCAT")); 38 | 39 | 40 | allocation_mite = 5.09; 41 | #allocation_mite = 4.81; 42 | em = 0.951; 43 | ek = allocation_mite / baseline_mite; 44 | range_bottom = n / ek * em; 45 | t_bottom = np.arange(0, range_bottom, 1); 46 | t_top = np.arange(range_bottom, range_top, 1); 47 | temp.append(ax.plot(t_bottom, t_bottom / em - (t_bottom / em) * ek, 'b-', linewidth=2.0, label="Contention-CAT")); 48 | temp.append(ax.plot(t_top, (n / ek - n) + (t_top - (n / ek) * em), 'b-', linewidth=2.0));#, label="Contention-CAT")); 49 | handles, labels = ax.get_legend_handles_labels() 50 | import operator 51 | handles2 = None; 52 | labels2 = None; 53 | 54 | hl = zip(handles,labels);#sorted(zip(handles, labels), key=operator.itemgetter(1)) 55 | handles2, labels2 = zip(*hl) 56 | lgd = ax.legend(handles2, labels2, loc="upper center"); 57 | 58 | ax.set_xlabel("Machine learning throughput"); 59 | ax.set_ylabel("Number of extra machines"); 60 | plt.ylim(ymin=0, ymax=200); 61 | plt.xlim(xmin=0, xmax=1200); 62 | 63 | plt.savefig(filename, bbox_extra_artists=(lgd,), bbox_inches='tight'); 64 | exit(); 65 | 66 | def main(): 67 | graph(); 68 | 69 | main(); 70 | # Col 0 are the x points 71 | # Col 1 is the series 50/100 marker 72 | # Col 2 is the series cat data 73 | # Col 3 is the series no cat data 74 | -------------------------------------------------------------------------------- /csvify: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | emptydelim="$1" 4 | headersrc="$2" 5 | recordsrc="$3" 6 | 7 | head -n1 "$headersrc" 8 | tail -n2 "$recordsrc" | rev | cut -d" " -f1 | rev | while read each 9 | do 10 | printf '%s%s\n' "$each" "$emptydelim" 11 | done 12 | -------------------------------------------------------------------------------- /csvmerge: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | # This script is also dedicated to Brandon. 4 | 5 | from itertools import zip_longest 6 | from sys import argv 7 | 8 | def firstcol(string, delim): 9 | if string == None: 10 | return float('inf') 11 | return int(string.split(delim)[0]) 12 | 13 | def restcols(string, delim): 14 | if string == None: 15 | return 0 16 | return string[string.index(delim) + 1:].strip() 17 | 18 | def main(): 19 | if len(argv) <= 2: 20 | print("USAGE: {} ...".format(argv[0])) 21 | exit(1) 22 | 23 | delim = argv[1] 24 | numfiles = len(argv) - 2 25 | fds = [open(fn) for fn in argv[2:]] 26 | 27 | numdelims = None 28 | for fd in fds: 29 | curheader = next(fd) 30 | curnumdelims = curheader.count(delim) 31 | if numdelims == None: 32 | print(curheader.strip(), end='') 33 | for time in range(numfiles - 1): 34 | print(delim, end='') 35 | print(restcols(curheader, delim), end='') 36 | print() 37 | numdelims = curnumdelims 38 | continue 39 | if curnumdelims != numdelims: 40 | print('Error: CSVs have different numbers of columns or delimiters') 41 | return 42 | placeholder = delim * numdelims 43 | 44 | nextel = [next(fd) for fd in fds] 45 | 46 | while nextel.count(None) != len(fds): 47 | maxel = firstcol(min(nextel, key = lambda x: firstcol(x, delim)), delim) 48 | res = str(maxel) 49 | for idx in range(len(nextel)): 50 | if firstcol(nextel[idx], delim) == maxel: 51 | res += delim + restcols(nextel[idx], delim) 52 | nextel[idx] = next(fds[idx], None) 53 | else: 54 | res += placeholder 55 | print(res) 56 | 57 | for fd in fds: 58 | fd.close() 59 | 60 | if __name__ == '__main__': 61 | main() 62 | -------------------------------------------------------------------------------- /csvmergecheck: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | delim="$1" 4 | checkfile="$2" 5 | shift 2 6 | 7 | if [ $(wc -l "$checkfile" | cut -d" " -f1 ) -ne $(cat "$@" | sort | cut -d"$delim" -f1 | uniq | wc -l) ] 8 | then 9 | echo "ERROR: Unexpected number of lines in output file. Do one or more input files have duplicate primary keys?!" 10 | exit 1 11 | else 12 | echo "Looks good to me, approval." 13 | fi 14 | 15 | true 16 | -------------------------------------------------------------------------------- /data_analysis/graph-cat.py: -------------------------------------------------------------------------------- 1 | ../graph-cat.py -------------------------------------------------------------------------------- /data_analysis/jaguar: -------------------------------------------------------------------------------- 1 | ../jaguar/ -------------------------------------------------------------------------------- /data_analysis/largescale_and_cdf: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | readonly SERIES="baseline basealloc contention allocation" 4 | readonly INDICES="`seq 0 2`" 5 | 6 | set -e 7 | if [ $# -ne 3 ] 8 | then 9 | echo "USAGE: $0 " 10 | false 11 | fi 12 | readonly name="$1" 13 | readonly jaguar="$2" 14 | readonly seethef="$3" 15 | 16 | [ -x "$jaguar" ] 17 | [ -x "$seethef" ] 18 | 19 | mkdir "$name" 20 | #mkdir "${name}_overhead" 21 | counter="1" 22 | for suffix in "" #"_overhead" 23 | do 24 | for index in $INDICES 25 | do 26 | for series in $SERIES 27 | do 28 | filename="$name$suffix/data_$series-$index.csv" 29 | #"./$jaguar" get "$name-raw.json" "data.$series$suffix.samples[$index].round_trip_time" | sed -e 's/\[\(.*\)\]/\1/' -e 's/, /\n/g' >"$filename" 30 | tail -n+"$counter" "$name.log" | head -n30000000 | tail -n20000000 >"$filename" 31 | 32 | gnuplot <<-tolpung 33 | set output "$name$suffix/timescale_$series-$index.png" 34 | set terminal png 35 | plot "$filename" 36 | tolpung 37 | 38 | "./$seethef" <"$filename" >"$filename-cdf" 39 | gnuplot <<-tolpung 40 | set output "$name$suffix/cdf_$series-$index.png" 41 | set terminal png 42 | set logscale x 43 | plot "$filename-cdf" with lines 44 | tolpung 45 | 46 | counter="$((counter + 30000000))" 47 | done 48 | 49 | gnuplot <<-tolpung 50 | set output "$name$suffix/cdf_$index.png" 51 | set terminal png 52 | set logscale x 53 | plot "$name$suffix/data_`echo "$SERIES" | cut -d" " -f1`-$index.csv-cdf" with lines, \ 54 | "$name$suffix/data_`echo "$SERIES" | cut -d" " -f2`-$index.csv-cdf" with lines, \ 55 | "$name$suffix/data_`echo "$SERIES" | cut -d" " -f3`-$index.csv-cdf" with lines, \ 56 | "$name$suffix/data_`echo "$SERIES" | cut -d" " -f4`-$index.csv-cdf" with lines 57 | tolpung 58 | done 59 | done 60 | rm $name/data_*.csv* $name$suffix/data_*.csv* 61 | -------------------------------------------------------------------------------- /data_analysis/make-cdf: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # Todo: Make it adaptive; don't print out 4 | # unnecessary colinear points. 5 | 6 | $step = $ARGV[0]; 7 | if (!$step) { $step = 0.1; } 8 | $max = $ARGV[1]; 9 | 10 | $totsamps = 0; 11 | while () { 12 | chomp; 13 | s/\#.*//; 14 | next if (length($_) < 1); 15 | push @samps, $_; 16 | # $totsamps += $_; 17 | } 18 | 19 | 20 | @samps = sort bynum @samps; 21 | #print "Samples: @samps\n"; 22 | 23 | $count = 0; 24 | $looking_at = $samps[0]; 25 | $totsamps = $#samps + 1; 26 | my $last_x; 27 | my $last_y; 28 | foreach $samp (@samps) { 29 | # XXX: Not well tested, does this change things drastically? 30 | if ($samp > ($looking_at)) { 31 | printf("%.5f %.5f\n", $looking_at, $count / $totsamps); 32 | printf("%.5f %.5f\n", $samp, $count / $totsamps); 33 | if ($samp - $looking_at < $step) { 34 | $looking_at += $step; 35 | } else { 36 | $looking_at = $samp; 37 | } 38 | } 39 | 40 | # while ($samp > $looking_at) { 41 | # printf("%.5f %.5f\n", $looking_at, $count / $totsamps); 42 | # $looking_at += $step; 43 | # if ($max && $looking_at > $max) { last; } 44 | # } 45 | $count += 1; #$samp; 46 | if ($max && $looking_at > $max) { last; } 47 | } 48 | $looking_at += $step; 49 | if ($totsamps > 0) { 50 | printf("%.5f %.5f\n", $looking_at, $count / $totsamps); 51 | } 52 | close(OUT); 53 | 54 | 55 | sub bynum { $a <=> $b; } 56 | -------------------------------------------------------------------------------- /data_analysis/mica2_tables: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | readonly DEP="round_trip_time" 4 | readonly INDEPS="0.00 0.90 0.99" 5 | readonly ITERATIONS="30000000" 6 | readonly SERIES="baseline basealloc contention allocation" 7 | readonly WARMUP="10000000" 8 | 9 | echo() { 10 | puts "INTERNAL ERROR: echo called" >&2 11 | return 1 12 | } 13 | 14 | max() { 15 | set -e 16 | 17 | sort "$@" | tail -n1 18 | } 19 | 20 | puts() { 21 | printf "%s\n" "$*" 22 | } 23 | 24 | printf() { 25 | "`which printf`" "$@" 26 | } 27 | 28 | repnz() { 29 | local times="$1" 30 | local str="$2" 31 | set -e 32 | 33 | printf %s "$str" 34 | 35 | local time 36 | for time in `seq "$((times - 1))"` 37 | do 38 | printf %s " $str" 39 | done 40 | } 41 | 42 | strlen() { 43 | set -e 44 | 45 | local str 46 | for str in "$@" 47 | do 48 | printf %s "$str" | wc -m 49 | done 50 | } 51 | 52 | filter_latencies() { 53 | set -e 54 | 55 | if [ -n "$latencies" ] 56 | then 57 | return 0 58 | fi 59 | 60 | if [ -e "$usfile" ] 61 | then 62 | readonly latencies="`cat "$usfile"`" 63 | else 64 | readonly latencies="`grep -F "Completed after:" "$logfile" | cut -d" " -f4`" 65 | fi 66 | } 67 | 68 | filter_percs() { 69 | set -e 70 | 71 | if [ -n "$percs" ] 72 | then 73 | return 0 74 | fi 75 | 76 | if [ -e "$percfile" ] 77 | then 78 | readonly percs="`cat "$percfile"`" 79 | readonly num_events="`puts "$percs" | cut -f1 | sort | uniq | wc -l`" 80 | else 81 | local sentinel="^NETWORK_RTT:" 82 | local postproc="cat" 83 | if jaguar/jaguar get "$jagfile" meta.server_binary >/dev/null 2>&1 84 | then 85 | # perf record 86 | local keyword="perf record: Captured" 87 | elif grep -Fm1 "Perf" "$logfile" >/dev/null 88 | then 89 | # perf stat 90 | local keyword="'system wide':" 91 | sentinel='seconds time elapsed$' 92 | postproc="tr -s ' ' | sed 's/^ \([^ ]\+\) \(.\+\) [^ ]\+/\2\t\1/'" 93 | else 94 | # vtune 95 | local keyword="Hardware Event" 96 | postproc="tr -s ' ' '\t' | cut -f1-2" 97 | fi 98 | 99 | readonly num_events="$((`grep -FA50 -m1 "$keyword" "$logfile" | sed "/$sentinel/q" | grep -vFe"[vdso]" -e"amplxe:" -e"--" | grep -vxF "" | grep -v '^ \+[0-9]\+ ' | wc -l` - 2))" 100 | readonly percs="`grep -vFe"[vdso]" -e"amplxe:" -e"--" "$logfile" | grep -vxF "" | grep -v '^ \+[0-9]\+ ' | grep -FA"$num_events" "$keyword" | grep -vFe"$keyword" -e"--" | eval "$postproc"`" 101 | fi 102 | readonly events="`puts "$percs" | head -n"$num_events" | cut -f1 | cut -d" " -f1`" 103 | readonly maxlen_event="`strlen $events | max -n`" 104 | } 105 | 106 | hdr_events() { 107 | set -e 108 | 109 | printf "%$((maxlen_indep + 2 + maxlen_series + 1))s : `repnz "$num_events" "%${maxlen_event}s"`\n" "" $events 110 | } 111 | 112 | hdr_series() { 113 | set -e 114 | 115 | printf "%${maxlen_indep}s : `repnz "$num_series" "%${maxlen_series}s"`\n" "" $SERIES 116 | } 117 | 118 | if [ $# -lt 2 ] 119 | then 120 | cat <<-tac 121 | USAGE: $0 -... 122 | 123 | where - is one of: 124 | -a : Ave. latency 125 | -e : Performance counter events 126 | -n : Normalized performance counter events 127 | -p : Save file with performance counter events 128 | -t : 99.9% tail latency 129 | -u : Save file with raw latencies in us 130 | tac 131 | exit 1 132 | fi 133 | args="`puts "$*" | rev | cut -d" " -f2- | rev`" 134 | shift "$(($# - 1))" 135 | jagfile="$1" 136 | set -e 137 | 138 | if [ ! -e "$jagfile" ] 139 | then 140 | puts "$jagfile: No such file" >&2 141 | exit 2 142 | fi 143 | 144 | readonly maxlen_indep="`strlen $INDEPS | max -n`" 145 | readonly maxlen_series="`strlen $SERIES | max -n`" 146 | readonly num_series="`puts "$SERIES" | wc -w`" 147 | 148 | logfile="`puts "$jagfile" | sed 's/\.[^.]\+$/.log/'`" 149 | percfile="`puts "$logfile" | sed 's/\.log$/-perc&/'`" 150 | unpack="`jaguar/jaguar get "$jagfile" meta.unpack 2>/dev/null || true`" 151 | usfile="`puts "$logfile" | sed 's/\.log$/-us&/'`" 152 | if [ -z "$unpack" ] 153 | then 154 | unpack="base64 -d" 155 | fi 156 | 157 | [ -e "$logfile" ] || jaguar/jaguar get "$jagfile" meta.log | eval "$unpack" >"$logfile" 158 | 159 | for arg in $args 160 | do 161 | case "$arg" in 162 | -a) 163 | puts "# Ave. latencies:" 164 | hdr_series 165 | index="0" 166 | for indep in $INDEPS 167 | do 168 | printf "%${maxlen_indep}s :" "$indep" 169 | for series in $SERIES 170 | do 171 | printf " %${maxlen_series}s" "`jaguar/jaguar get "$jagfile" "data.$series.samples[$index].$DEP"`" 172 | done 173 | puts 174 | index="$((index + 1))" 175 | done 176 | ;; 177 | -e) 178 | puts "# Performance counters:" 179 | filter_percs 180 | hdr_events 181 | counter="1" 182 | for indep in $INDEPS 183 | do 184 | for series in $SERIES 185 | do 186 | printf "%${maxlen_indep}s (%${maxlen_series}s) :" "$indep" "$series" 187 | printf " %'${maxlen_event}d" `puts "$percs" | tail -n+"$counter" | head -n"$num_events" | cut -f2 | tr -d ","` 188 | puts 189 | counter="$((counter + num_events))" 190 | done 191 | done 192 | ;; 193 | -n) 194 | puts "# Normalized performance counters:" 195 | filter_percs 196 | times="`grep -F "seconds time elapsed" "$logfile" | tr -s " " | cut -d" " -f2`" 197 | hdr_events 198 | counter="0" 199 | for indep in $INDEPS 200 | do 201 | for series in $SERIES 202 | do 203 | thistime="`puts "$times" | tail -n+"$((counter + 1))" | head -n1`" 204 | printf "%${maxlen_indep}s (%${maxlen_series}s) :" "$indep" "$series" 205 | printf " %'${maxlen_event}.2f" `puts "$percs" | tail -n+"$((counter * num_events + 1))" | head -n"$num_events" | cut -f2 | tr -d "," | sed "s:\$:/$thistime:" | bc -l` 206 | puts 207 | counter="$((counter + 1))" 208 | done 209 | done 210 | ;; 211 | -p) 212 | filter_percs 213 | puts "$percs" >"$percfile" 214 | continue 215 | ;; 216 | -t) 217 | puts "# 99.9% tail latencies:" 218 | filter_latencies 219 | hdr_series 220 | counter="1" 221 | for indep in $INDEPS 222 | do 223 | printf "%${maxlen_indep}s :" "$indep" 224 | for series in $SERIES 225 | do 226 | printf " %${maxlen_series}s" "`tail -n+"$counter" <<-liat | head -n"$ITERATIONS" | tail -n+"$((WARMUP + 1))" | sort -n | tail -n+"$(((ITERATIONS - WARMUP) * 999 / 1000))" | head -n1 227 | $latencies 228 | liat`" 229 | counter="$((counter + ITERATIONS))" 230 | done 231 | puts 232 | done 233 | ;; 234 | -u) 235 | filter_latencies 236 | cat >"$usfile" <<-tac 237 | $latencies 238 | tac 239 | continue 240 | ;; 241 | *) 242 | puts "WARNING: Skipping unrecognized switch: '$arg'" >&2 243 | ;; 244 | esac 245 | puts 246 | done 247 | -------------------------------------------------------------------------------- /data_analysis/network_rawnums: -------------------------------------------------------------------------------- 1 | ../network_rawnums -------------------------------------------------------------------------------- /data_analysis/network_slowdown: -------------------------------------------------------------------------------- 1 | ../network_slowdown -------------------------------------------------------------------------------- /data_analysis/postprocess.sh: -------------------------------------------------------------------------------- 1 | ../postprocess.sh -------------------------------------------------------------------------------- /data_analysis/timescale_and_cdf: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | readonly SERIES="baseline basealloc contention allocation" 4 | readonly INDICES="`seq 0 5`" 5 | 6 | set -e 7 | if [ $# -ne 3 ] 8 | then 9 | echo "USAGE: $0 " 10 | false 11 | fi 12 | readonly name="$1" 13 | readonly jaguar="$2" 14 | readonly seethef="$3" 15 | 16 | [ -x "$jaguar" ] 17 | [ -x "$seethef" ] 18 | 19 | maybe_overhead="" 20 | if jaguar/jaguar get "$name-raw.json" "data.`echo "$SERIES" | cut -d" " -f1`_overhead.description" >/dev/null 2>&1 21 | then 22 | maybe_overhead="_overhead" 23 | fi 24 | 25 | mkdir "$name" 26 | [ -n "$maybe_overhead" ] && mkdir "${name}_overhead" 27 | for suffix in "" $maybe_overhead 28 | do 29 | for index in $INDICES 30 | do 31 | for series in $SERIES 32 | do 33 | filename="$name$suffix/data_$series-$index.csv" 34 | "./$jaguar" get "$name-raw.json" "data.$series$suffix.samples[$index].round_trip_time" | sed -e 's/\[\(.*\)\]/\1/' -e 's/, /\n/g' >"$filename" 35 | 36 | gnuplot <<-tolpung 37 | set output "$name$suffix/timescale_$series-$index.png" 38 | set terminal png 39 | plot "$filename" 40 | tolpung 41 | 42 | "./$seethef" <"$filename" >"$filename-cdf" 43 | gnuplot <<-tolpung 44 | set output "$name$suffix/cdf_$series-$index.png" 45 | set terminal png 46 | set logscale x 47 | plot "$filename-cdf" with lines 48 | tolpung 49 | done 50 | 51 | gnuplot <<-tolpung 52 | set output "$name$suffix/cdf_$index.png" 53 | set terminal png 54 | set logscale x 55 | plot "$name$suffix/data_`echo "$SERIES" | cut -d" " -f1`-$index.csv-cdf" with lines, \ 56 | "$name$suffix/data_`echo "$SERIES" | cut -d" " -f2`-$index.csv-cdf" with lines, \ 57 | "$name$suffix/data_`echo "$SERIES" | cut -d" " -f3`-$index.csv-cdf" with lines 58 | tolpung 59 | done 60 | done 61 | rm $name/data_*.csv* $name$suffix/data_*.csv* 62 | -------------------------------------------------------------------------------- /dist_a.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include "bench_commands.h" 18 | #include "prep_system.h" 19 | #include "rdtscp.h" 20 | 21 | #define DEFAULT_NUM_PASSES 100000 22 | #define DEFAULT_PERCENT 80 23 | #define DEFAULT_START_CYCLE 0 24 | #define TRASH_CORE -1 25 | 26 | // Which CPU to run square_evictions on 27 | #define TARGET_CPU 3 28 | 29 | /* TODO: These are probably not super right. Do the right 30 | thing once everything kinda-works */ 31 | #define NUM_WAYS 12 32 | #define NUM_CORES 8 33 | 34 | static bool parse_arg_arg(char flag, int *dest) { 35 | int val; 36 | 37 | if(sscanf(optarg, "%d", &val) != 1) { 38 | fprintf(stderr, "%c: Unexpected subargument '%s'\n", flag, optarg); 39 | return false; 40 | } else if(val < 0) { 41 | fprintf(stderr, "%c: Expected nonnegative integer but got '%d'\n", flag, val); 42 | return false; 43 | } 44 | 45 | *dest = val; 46 | return true; 47 | } 48 | 49 | static void rotate_cores(int loc) { 50 | for(int i = 0; i < NUM_CORES; i++) { 51 | int ret = pqos_l3ca_assoc_set(i, (i+loc)%NUM_WAYS); 52 | assert(ret == PQOS_RETVAL_OK); 53 | } 54 | } 55 | 56 | // Store the precise number of cycles different between each offset 57 | static uint64_t config_offset_clocks[NUM_WAYS]; 58 | static uint64_t config_offset_begin[NUM_WAYS]; 59 | static uint64_t config_offset_end[NUM_WAYS]; 60 | 61 | static int dist_a(int num_passes, int start_cycle) { 62 | struct pqos_l3ca cos[NUM_WAYS]; 63 | for (int i=0; i < NUM_WAYS; i++) { 64 | cos[i].class_id = i; 65 | cos[i].cdp = false; 66 | cos[i].ways_mask = 1 << i; 67 | } 68 | pqos_l3ca_set(0, NUM_WAYS, cos); 69 | for(int offset = 0; offset < NUM_WAYS; ++offset) { 70 | int cycle = (start_cycle + offset) % NUM_WAYS; 71 | rotate_cores(cycle); 72 | test_prog_t cmdline[] = { 73 | // Use -h for hugepages 74 | {.cmdline = {"clients/square_evictions", "-n1", "-c50", "-e50", "-p1000000", "-hr"}}, 75 | {.target_cpu = TARGET_CPU}, 76 | }; 77 | /* Begin timed section */ 78 | run_benchmarks(cmdline, 1); 79 | uint64_t begin = rdtscp(); 80 | wait_benchmarks(); 81 | uint64_t end = rdtscp(); 82 | /* End timed section */ 83 | assert(end > begin); 84 | config_offset_clocks[cycle] = end - begin; 85 | config_offset_begin[cycle] = begin; 86 | config_offset_end[cycle] = end; 87 | } 88 | 89 | printf("Number of passes: %d\n", num_passes); 90 | for(int cycle = 0; cycle < NUM_WAYS; ++cycle) { 91 | printf("DISTA REPORTING CYCLE %d: %lu\n", cycle, config_offset_clocks[cycle]); 92 | } 93 | 94 | return 0; 95 | } 96 | 97 | int main(int argc, char *argv[]) { 98 | int num_passes = DEFAULT_NUM_PASSES; 99 | int percent = DEFAULT_PERCENT; 100 | int start_cycle = DEFAULT_START_CYCLE; 101 | char *invoc = argv[0]; 102 | int each_arg; 103 | 104 | opterr = 0; 105 | while((each_arg = getopt(argc, argv, "n:p:s:")) != -1) { 106 | switch(each_arg) { 107 | case 'n': 108 | if(!parse_arg_arg(each_arg, &num_passes)) 109 | return 1; 110 | break; 111 | case 'p': 112 | if(!parse_arg_arg(each_arg, &percent)) 113 | return 1; 114 | break; 115 | case 's': 116 | if(!parse_arg_arg(each_arg, &start_cycle)) 117 | return 1; 118 | break; 119 | default: 120 | printf("USAGE: %s [-n #] [-p #]\n", invoc); 121 | printf( 122 | " -n #: Number of passes (default %d)\n" 123 | " -p #: Percentage of cache in working set (default %d)\n" 124 | " -s #: Which way to start with\n", 125 | DEFAULT_NUM_PASSES, DEFAULT_PERCENT); 126 | return 1; 127 | } 128 | } 129 | prep_system(false, TRASH_CORE); 130 | rotate_cores(0); 131 | int ret = dist_a(num_passes, start_cycle); 132 | cleanup_system(true); 133 | return ret; 134 | } 135 | -------------------------------------------------------------------------------- /driver: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | trap exit TERM INT QUIT 4 | trap "kill 0" EXIT 5 | 6 | logging_commence() { 7 | mkfifo "$prefix.tmp" 8 | tee "$CATBENCH_LOGFILE" <"$prefix.tmp" & 9 | set -v 10 | exec >"$prefix.tmp" 2>&1 3>&1 4>&2 11 | } 12 | 13 | logging_cleanup() { 14 | set +v 15 | exec >&3 2>&4 16 | rm "$prefix.tmp" 17 | } 18 | 19 | shell_needs_protection() { 20 | local thing_that_might_need_protection="$1" 21 | [ "`eval printf '"%s\n"' "$thing_that_might_need_protection"`" != "$thing_that_might_need_protection" ] 22 | } 23 | 24 | shell_quoted_arguments() { 25 | for arg in "$@" 26 | do 27 | local delim="" 28 | if [ -z "$arg" ] || shell_needs_protection "$arg" 29 | then 30 | delim="'" 31 | fi 32 | printf %s " $delim$arg$delim" | sed "s/'\([^=]*=\)/\1'/g" 33 | done | cut -d" " -f2- 34 | } 35 | 36 | if [ $# -lt 1 ] 37 | then 38 | cat <<-tac 39 | USAGE: $0 ... 40 | 41 | Prepend $0 to the full command-line invokation of another script 42 | or program to log its environment, invocation, and interactions. 43 | 44 | If shell actions are provided (in escaped form so your own shell 45 | doesn't eat them, of course), they will be interpreted. To add 46 | files to the archive, place them in the \\\$dir directory. 47 | tac 48 | exit 127 49 | fi 50 | 51 | if [ -n "$CATBENCH_JAGFILE" ] 52 | then 53 | cat >&2 <<-tac 54 | $0: called recursively! No mere script should call the great $0! 55 | tac 56 | exit 127 57 | fi 58 | 59 | for word in "$@" 60 | do 61 | if printf %s "$word" | grep -v = >/dev/null 62 | then 63 | cmd="$word" 64 | break 65 | fi 66 | done 67 | 68 | if ! mount | grep "$PWD/ramdisk" >/dev/null 69 | then 70 | mkdir -p ramdisk 71 | sudo mount -ttmpfs none ramdisk 72 | fi 73 | 74 | prefix="catbench-`basename $cmd`_`date +%F_%H-%M-%S_%z`" 75 | export CATBENCH_JAGFILE="$prefix.json" 76 | export CATBENCH_LOGFILE="ramdisk/$prefix.log" 77 | if [ -e "$CATBENCH_JAGFILE" ] 78 | then 79 | echo "ERROR: Output JSON file already exists; aborting!" >&2 80 | exit 127 81 | fi 82 | 83 | logging_commence 84 | 85 | cp jaguar/template.json "$CATBENCH_JAGFILE" 86 | args="`shell_quoted_arguments "$@"`" 87 | jaguar/jaguar set "$CATBENCH_JAGFILE" meta.command "$args" 88 | jaguar/jaguar set "$CATBENCH_JAGFILE" meta.commit "`git log --oneline --abbrev-commit --no-decorate -1`" 89 | jaguar/jaguar set "$CATBENCH_JAGFILE" meta.date "`date "+%F %T %z"`" 90 | jaguar/jaguar set "$CATBENCH_JAGFILE" meta.message "`git log --no-abbrev-commit --decorate -1`" 91 | git diff --ignore-submodules HEAD | base64 | jaguar/jaguar set "$CATBENCH_JAGFILE" meta.patch - 92 | jaguar/jaguar set "$CATBENCH_JAGFILE" meta.perf "`perf -v`" 93 | jaguar/jaguar set "$CATBENCH_JAGFILE" meta.status "`git status -uno`" 94 | jaguar/jaguar set "$CATBENCH_JAGFILE" meta.submodule "`git submodule status`" 95 | jaguar/jaguar set "$CATBENCH_JAGFILE" meta.uname "`uname -a`" 96 | 97 | printf "%s\n" "$ $args" 98 | eval "$args" 99 | status="$?" 100 | echo "Command exited with status: $status" 101 | jaguar/jaguar set "$CATBENCH_JAGFILE" meta.exit "$status" 102 | 103 | sleep 10 104 | logging_cleanup 105 | pack="base64 -w0 '$CATBENCH_LOGFILE'" 106 | unpack="base64 -d" 107 | if [ "`du -b "$CATBENCH_LOGFILE" | cut -f1`" -gt "$((2 * 1024 * 1024 * 1024))" ] # 2 GiB 108 | then 109 | pack="gzip -c '$CATBENCH_LOGFILE' | base64 -w0" 110 | unpack="$unpack | zcat" 111 | fi 112 | eval "$pack" | jaguar/jaguar set "$CATBENCH_JAGFILE" meta.log - 113 | jaguar/jaguar set "$CATBENCH_JAGFILE" meta.unpack "$unpack" 114 | rm "$CATBENCH_LOGFILE" 115 | 116 | exit "$status" 117 | -------------------------------------------------------------------------------- /external/dpdk.patch: -------------------------------------------------------------------------------- 1 | diff --git i/build/lib/Makefile w/build/lib/Makefile 2 | new file mode 100644 3 | index 0000000..1e72e9b 4 | --- /dev/null 5 | +++ w/build/lib/Makefile 6 | @@ -0,0 +1,5 @@ 7 | +../.config: 8 | + $(MAKE) -C ../.. config T=x86_64-native-linuxapp-gcc 9 | + 10 | +%.a: ../.config 11 | + $(MAKE) -C ../.. 12 | diff --git a/lib/librte_eal/linuxapp/kni/compat.h b/lib/librte_eal/linuxapp/kni/compat.h 13 | index 78da08e..d96275a 100644 14 | --- a/lib/librte_eal/linuxapp/kni/compat.h 15 | +++ b/lib/librte_eal/linuxapp/kni/compat.h 16 | @@ -2,6 +2,8 @@ 17 | * Minimal wrappers to allow compiling kni on older kernels. 18 | */ 19 | 20 | +#include 21 | + 22 | #ifndef RHEL_RELEASE_VERSION 23 | #define RHEL_RELEASE_VERSION(a, b) (((a) << 8) + (b)) 24 | #endif 25 | @@ -67,3 +69,7 @@ 26 | (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 34))) 27 | #undef NET_NAME_UNKNOWN 28 | #endif 29 | + 30 | +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) 31 | +#define HAVE_SIGNAL_FUNCTIONS_OWN_HEADER 32 | +#endif 33 | diff --git a/lib/librte_eal/linuxapp/kni/kni_dev.h b/lib/librte_eal/linuxapp/kni/kni_dev.h 34 | index 002e5fa..72385ab 100644 35 | --- a/lib/librte_eal/linuxapp/kni/kni_dev.h 36 | +++ b/lib/librte_eal/linuxapp/kni/kni_dev.h 37 | @@ -30,9 +30,15 @@ 38 | #endif 39 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 40 | 41 | +#include "compat.h" 42 | + 43 | #include 44 | #include 45 | +#ifdef HAVE_SIGNAL_FUNCTIONS_OWN_HEADER 46 | +#include 47 | +#else 48 | #include 49 | +#endif 50 | #include 51 | #include 52 | #include 53 | diff --git a/lib/librte_eal/linuxapp/kni/ethtool/igb/igb_main.c b/lib/librte_eal/linuxapp/kni/ethtool/igb/igb_main.c 54 | index c0d52db..5f1f3a6 100644 55 | --- a/lib/librte_eal/linuxapp/kni/ethtool/igb/igb_main.c 56 | +++ b/lib/librte_eal/linuxapp/kni/ethtool/igb/igb_main.c 57 | @@ -1031,8 +1031,15 @@ static void igb_set_interrupt_capability(struct igb_adapter *adapter, bool msix) 58 | for (i = 0; i < numvecs; i++) 59 | adapter->msix_entries[i].entry = i; 60 | 61 | +#ifdef HAVE_PCI_ENABLE_MSIX 62 | err = pci_enable_msix(pdev, 63 | adapter->msix_entries, numvecs); 64 | +#else 65 | + err = pci_enable_msix_range(pdev, 66 | + adapter->msix_entries, 67 | + numvecs, 68 | + numvecs); 69 | +#endif 70 | if (err == 0) 71 | break; 72 | } 73 | diff --git a/lib/librte_eal/linuxapp/kni/ethtool/igb/kcompat.h b/lib/librte_eal/linuxapp/kni/ethtool/igb/kcompat.h 74 | index 4abab4a..4c52da3 100644 75 | --- a/lib/librte_eal/linuxapp/kni/ethtool/igb/kcompat.h 76 | +++ b/lib/librte_eal/linuxapp/kni/ethtool/igb/kcompat.h 77 | @@ -3937,4 +3937,8 @@ skb_set_hash(struct sk_buff *skb, __u32 hash, __always_unused int type) 78 | #define HAVE_VF_VLAN_PROTO 79 | #endif /* >= 4.9.0, >= SLES12SP3 */ 80 | 81 | +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 8, 0) 82 | +#define HAVE_PCI_ENABLE_MSIX 83 | +#endif 84 | + 85 | #endif /* _KCOMPAT_H_ */ 86 | diff --git a/lib/librte_eal/linuxapp/igb_uio/igb_uio.c b/lib/librte_eal/linuxapp/igb_uio/igb_uio.c 87 | index df41e457a..438e85f36 100644 88 | --- a/lib/librte_eal/linuxapp/igb_uio/igb_uio.c 89 | +++ b/lib/librte_eal/linuxapp/igb_uio/igb_uio.c 90 | @@ -380,7 +380,7 @@ igbuio_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) 91 | case RTE_INTR_MODE_MSIX: 92 | /* Only 1 msi-x vector needed */ 93 | msix_entry.entry = 0; 94 | - if (pci_enable_msix(dev, &msix_entry, 1) == 0) { 95 | + if (pci_enable_msix_range(dev, &msix_entry, 1, 1) == 0) { 96 | dev_dbg(&dev->dev, "using MSI-X"); 97 | udev->info.irq = msix_entry.vector; 98 | udev->mode = RTE_INTR_MODE_MSIX; 99 | -------------------------------------------------------------------------------- /external/modules.mk: -------------------------------------------------------------------------------- 1 | .PRECIOUS: $(dir $(lastword $(MAKEFILE_LIST)))% 2 | $(dir $(lastword $(MAKEFILE_LIST)))%: 3 | if ! [ -f $(@D)/Makefile ]; \ 4 | then \ 5 | git submodule update --init $(dir $(lastword $(MAKEFILE_LIST)))$(firstword $(subst /, ,$*)); \ 6 | if [ -f $(dir $(lastword $(MAKEFILE_LIST)))$(firstword $(subst /, ,$*)).patch ]; \ 7 | then \ 8 | cd $(dir $(lastword $(MAKEFILE_LIST)))$(firstword $(subst /, ,$*)) && git apply -3 ../$(firstword $(subst /, ,$*)).patch; \ 9 | fi; \ 10 | fi 11 | [ -e $@ ] || $(MAKE) -C $(@D) $(@F) 12 | -------------------------------------------------------------------------------- /external/pqos.patch: -------------------------------------------------------------------------------- 1 | diff --git i/lib/log.c w/lib/log.c 2 | index 15d5086..1e89fe6 100644 3 | --- i/lib/log.c 4 | +++ w/lib/log.c 5 | @@ -62,7 +62,6 @@ 6 | 7 | static FILE *m_file = NULL; /**< file that log writes to */ 8 | static int m_opt = 0; /**< log options */ 9 | -static int m_fd = -1; /**< log file descriptor */ 10 | /** 11 | * --------------------------------------- 12 | * Local functions 13 | @@ -77,22 +76,20 @@ static int m_fd = -1; /**< log file descriptor */ 14 | */ 15 | 16 | int 17 | -log_init(int fd, int opt) 18 | +log_init(FILE *f, int opt) 19 | { 20 | int ret = LOG_RETVAL_OK; 21 | 22 | if (m_file != NULL) 23 | return LOG_RETVAL_ERROR; 24 | 25 | - m_file = fdopen(fd, "a"); 26 | + m_file = f; 27 | if (m_file == NULL) { 28 | - fprintf(stderr, "%s: fdopen() failed: %s\n", 29 | - __func__, strerror(errno)); 30 | + fprintf(stderr, "log_init expected a non-NULL FILE *\n"); 31 | return LOG_RETVAL_ERROR; 32 | } 33 | 34 | m_opt = opt; 35 | - m_fd = fd; 36 | return ret; 37 | } 38 | 39 | @@ -103,12 +100,11 @@ int log_fini(void) 40 | if (m_file == NULL) 41 | return LOG_RETVAL_ERROR; 42 | 43 | - if ((m_fd != STDOUT_FILENO) && (m_fd != STDERR_FILENO)) 44 | - close(m_fd); 45 | + if ((m_file != stdout) && (m_file != stderr)) 46 | + fclose(m_file); 47 | 48 | m_file = NULL; 49 | m_opt = 0; 50 | - m_fd = -1; 51 | 52 | return ret; 53 | } 54 | diff --git i/lib/log.h w/lib/log.h 55 | index 97572bf..94af8f4 100644 56 | --- i/lib/log.h 57 | +++ w/lib/log.h 58 | @@ -72,7 +72,7 @@ extern "C" { 59 | * @return Operation status 60 | * @retval LOG_RETVAL_OK on success 61 | */ 62 | -int log_init(int fd, int opt); 63 | +int log_init(FILE *f, int opt); 64 | 65 | /** 66 | * @brief Shuts down PQoS log module 67 | diff --git i/lib/pqos.h w/lib/pqos.h 68 | index 7f7ee3f..ed7bd74 100644 69 | --- i/lib/pqos.h 70 | +++ w/lib/pqos.h 71 | @@ -88,7 +88,7 @@ enum pqos_cdp_config { 72 | * PQoS library configuration structure 73 | */ 74 | struct pqos_config { 75 | - int fd_log; /**< file descriptor to be used for 76 | + FILE *fd_log; /**< file descriptor to be used for 77 | library to log messages */ 78 | int verbose; /**< if true increases library 79 | verbosity level */ 80 | diff --git i/main.c w/main.c 81 | index fa6c54d..eaa7bcb 100644 82 | --- i/main.c 83 | +++ w/main.c 84 | @@ -2229,11 +2229,10 @@ int main(int argc, char **argv) 85 | * Set up file descriptor for message log 86 | */ 87 | if (sel_log_file == NULL) { 88 | - cfg.fd_log = STDOUT_FILENO; 89 | + cfg.fd_log = stdout; 90 | } else { 91 | - cfg.fd_log = open(sel_log_file, O_WRONLY|O_CREAT, 92 | - S_IRUSR|S_IWUSR); 93 | - if (cfg.fd_log == -1) { 94 | + cfg.fd_log = fopen(sel_log_file, "w"); 95 | + if (!cfg.fd_log) { 96 | printf("Error opening %s log file!\n", sel_log_file); 97 | exit_val = EXIT_FAILURE; 98 | goto error_exit_2; 99 | @@ -2398,8 +2397,8 @@ int main(int argc, char **argv) 100 | /** 101 | * Close file descriptor for message log 102 | */ 103 | - if (cfg.fd_log > 0 && cfg.fd_log != STDOUT_FILENO) 104 | - close(cfg.fd_log); 105 | + if (cfg.fd_log && cfg.fd_log != stdout && cfg.fd_log != stderr) 106 | + fclose(cfg.fd_log); 107 | 108 | /** 109 | * Free allocated memory 110 | -------------------------------------------------------------------------------- /factors.sh: -------------------------------------------------------------------------------- 1 | prime_factors_5="-f 3,7,13" 2 | prime_factors_10="-f 2,3,7,13" 3 | prime_factors_15="$prime_factors_5" 4 | prime_factors_20="$prime_factors_10" 5 | prime_factors_30="-f 5,983" 6 | prime_factors_40="-f 6553" 7 | prime_factors_60="-f 2,5,983" 8 | prime_factors_70="-f 11468" 9 | prime_factors_80="-f 3,17,257" 10 | prime_factors_90="-f 3,5,983" 11 | -------------------------------------------------------------------------------- /find_zipf_N.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys 4 | import math 5 | 6 | BYTES_PER_ITEM = 56 7 | 8 | def find_zipf_N(cache_size, zipf_alpha, percentile): 9 | cache_item_count = int(cache_size / BYTES_PER_ITEM) 10 | 11 | sys.stderr.write('cache_size = %d bytes (%d items)\n' % (cache_size, cache_item_count)) 12 | sys.stderr.write('zipf_alpha = %f\n' % zipf_alpha) 13 | sys.stderr.write('percentile = %f\n' % percentile) 14 | 15 | # Find N such that 16 | # percentile = sum_{i=1}{cache_item_count}{1/i**zipf_alpha} / 17 | # sum_{i=1}{N}{1/i**zipf_alpha} 18 | 19 | numerator = 0. 20 | for i in range(1, cache_item_count + 1): 21 | numerator += 1. / (i ** zipf_alpha) 22 | 23 | rhs = numerator / percentile 24 | #print('rhs = %f' % rhs) 25 | 26 | lhs = 0. 27 | prevN = 0. 28 | N = 1. 29 | while lhs < rhs: 30 | for i in range(int(prevN) + 1, int(N) + 1): 31 | lhs += 1. / (i ** zipf_alpha) 32 | prevN = N 33 | # Accurate but slow 34 | N += 1. 35 | # Inaccurate but fast 36 | #N *= 1.001 37 | #print('lhs = %f' % lhs) 38 | 39 | sys.stderr.write('found N = %d\n' % prevN) 40 | 41 | print('%d' % prevN) 42 | return prevN 43 | 44 | 45 | def test_find_zipf_N(): 46 | assert find_zipf_N(100000, 0.0, 1.0) == 1785 47 | 48 | #test_find_zipf_N() 49 | 50 | 51 | if __name__ == '__main__': 52 | if len(sys.argv) != 4: 53 | print('%s CACHE-SIZE ZIPF-ALPHA PERCENTILE' % sys.argv[0]) 54 | sys.exit(1) 55 | cache_size = int(sys.argv[1]) 56 | zipf_alpha = float(sys.argv[2]) 57 | percentile = float(sys.argv[3]) 58 | find_zipf_N(cache_size, zipf_alpha, percentile) 59 | -------------------------------------------------------------------------------- /flags.mk: -------------------------------------------------------------------------------- 1 | CPPFLAGS_global := \ 2 | -Wundef \ 3 | -isystem $(dir $(lastword $(MAKEFILE_LIST)))external/dpdk/build/include \ 4 | -isystem $(dir $(lastword $(MAKEFILE_LIST)))external/pqos/lib \ 5 | 6 | CFLAGS_global := \ 7 | -Og \ 8 | -g3 \ 9 | -std=c99 \ 10 | -Wall \ 11 | -Wextra \ 12 | -Wcast-qual \ 13 | -Wfloat-equal \ 14 | -Winline \ 15 | -Wmissing-prototypes \ 16 | -Wredundant-decls \ 17 | -Wstrict-prototypes \ 18 | -Wwrite-strings \ 19 | -Wno-unused-function \ 20 | -Wpedantic \ 21 | 22 | LDFLAGS_global := \ 23 | -L$(dir $(lastword $(MAKEFILE_LIST)))external/dpdk/build/lib \ 24 | -L$(dir $(lastword $(MAKEFILE_LIST)))external/pqos/lib \ 25 | 26 | CPPFLAGS += $(CPPFLAGS_global) 27 | CFLAGS += $(CFLAGS_global) 28 | LDFLAGS += $(LDFLAGS_global) 29 | -------------------------------------------------------------------------------- /generate_hadoop_input.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | mkdir -p text 3 | mkdir -p text/small 4 | mkdir -p text/medium 5 | rm -rf text/small/* 6 | rm -rf text/medium/* 7 | perl -e 'print "Hello\nWorld\n" x 34952533' > text/small/test.txt 8 | perl -e 'print "Hello\nWorld\n" x 52428800' > text/medium/file1.txt 9 | cp text/medium/file1.txt text/medium/file2.txt 10 | cp text/medium/file1.txt text/medium/file3.txt 11 | -------------------------------------------------------------------------------- /graph-bar.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import argparse; 4 | import os; 5 | import sys; 6 | import matplotlib as mpl; 7 | 8 | mpl.use('Agg'); 9 | import matplotlib.pyplot as plt; 10 | import json; 11 | from matplotlib import ticker; 12 | import numpy as np 13 | 14 | from graph_helper import get_tuples; 15 | from graph_helper import get_sample_description; 16 | from graph_helper import get_label; 17 | from graph_helper import get_arg_label; 18 | from graph_helper import get_arg_unit; 19 | from graph_helper import get_aux; 20 | from graph_helper import get_commit; 21 | from graph_helper import get_series_aux; 22 | 23 | def setup_optparse(): 24 | parser = argparse.ArgumentParser(); 25 | parser.add_argument('--input', '-i', dest='datafile', 26 | help='input json'); 27 | parser.add_argument('--series', '-s', nargs='+', dest='series', 28 | help='series label(s). Single label or space separated list'); 29 | parser.add_argument('--xdata', dest='x', 30 | help='X axis label'); 31 | parser.add_argument('--ydata', nargs='+', dest='y', 32 | help='Y axis data labels. Single label or space separated list'); 33 | parser.add_argument('--title', '-t', dest='title', 34 | help='Graph title'); 35 | parser.add_argument('--outfile', '-o', dest='outfile', default="graph.png", 36 | help='Output filename'); 37 | parser.add_argument('--no-commit', '-n', dest='no_commit_message', action='store_true', default=False, 38 | help="Do not include commit number on graph"); 39 | parser.add_argument('--legend-x', dest='legend_x', type=float, default=1.0, 40 | help="Legend box location x coordinate (default 1.0)"); 41 | parser.add_argument('--legend-y', dest='legend_y', type=float, default=0.3, 42 | help="Legend boy location y coordinate (default 0.3)"); 43 | args = parser.parse_args(); 44 | return args.datafile, args.series, args.x, args.y, args.title, args.outfile, args.no_commit_message, args.legend_x, args.legend_y; 45 | 46 | def graph_bar(infile, series, x, y, title, outfile, nocommit, legend_x, legend_y): 47 | width = 1; 48 | tuples = get_tuples(infile, series, x, y); 49 | yvar = y[0]; 50 | fig = plt.figure(); 51 | ax = fig.add_subplot(1,1,1); 52 | ax.set_xlabel(get_label(infile, x)); 53 | ax.set_ylabel(get_label(infile, y[0])); 54 | ax.ticklabel_format(useOffset=False); 55 | colors = [ 56 | 'b', 'g', 'r', 'm' ,'y', 'k' 57 | ] 58 | import itertools; 59 | marker = itertools.cycle(('o', '>', 'D', 's', 'h', '+', '<', '^')); 60 | color = itertools.cycle(('b', 'g', 'r', 'm' ,'y', 'k')); 61 | 62 | box = ax.get_position(); 63 | ax.set_position([box.x0, box.y0, box.width, box.height * 0.7]); 64 | 65 | lines = list(); 66 | for series_label, fields in tuples.items(): 67 | line = list(); 68 | for field, tuples in fields.items(): 69 | if(field == "description" or field == "order"): 70 | continue; 71 | points = map(list, zip(*tuples)); 72 | line_label = fields["description"] + " " + y[0]; 73 | line.append((ax.bar(points[0], points[1], width, align='center', color=color.next(), label=line_label))); 74 | lines.append((line[-1][0], fields["order"], line_label)); 75 | plt.xticks(points[0]); 76 | 77 | ax.set_title(title); 78 | ax.title.set_position((0.5, 1.08)); 79 | 80 | handles, labels = ax.get_legend_handles_labels() 81 | 82 | import operator 83 | handles2 = None; 84 | labels2 = None; 85 | h = sorted(zip(handles, labels), key=operator.itemgetter(1)) 86 | handles2, labels2 = zip(*h) 87 | lgd = ax.legend(handles2, labels2, loc="center right", bbox_to_anchor=(legend_x, legend_y)); 88 | 89 | from matplotlib.ticker import ScalarFormatter, FormatStrFormatter 90 | ax.xaxis.set_major_formatter(FormatStrFormatter('%.0f')) 91 | #fig.savefig(outfile, format='png', dpi=600, bbox_extra_artists=(lgd,), bbox_inches='tight'); 92 | plt.xlim(xmin=0); 93 | fig.savefig(outfile, format='png', dpi=600, bbox_inches='tight'); 94 | 95 | def main(): 96 | infile, series, x, y, title, outfile, nocommit, legend_x, legend_y = setup_optparse(); 97 | graph_bar(infile, series, x, y, title, outfile, nocommit, legend_x, legend_y); 98 | 99 | main(); 100 | -------------------------------------------------------------------------------- /gzip_wrapper: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # gzip_wrapper IN-PATH OUT-PATH [GZIP-OPTIONS] 4 | 5 | input_path=$1 6 | shift 7 | output_path=$1 8 | shift 9 | 10 | input_size=$(stat --printf="%s" "$input_path") 11 | echo "input size: $input_size" 12 | 13 | output_size=$(gzip "$@" -c "$input_path" | tee "$output_path" | wc -c) 14 | echo "output size: $output_size" 15 | 16 | -------------------------------------------------------------------------------- /hadoop_wrapper: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # hadoop_wrapper IN-DIR-PATH [[ITERS] HADOOP-OPTIONS] 4 | 5 | mkdir -p hadoop_output 6 | mkdir -p $input_dir_path 7 | input_dir_path=$1 8 | outdir="hadoop_output/`cat /proc/sys/kernel/random/uuid`" 9 | # Need to link /path/to/hadoop . 10 | ./hadoop/bin/hadoop jar ./hadoop/share/hadoop/mapreduce/hadoop-mapreduce-examples-2.7.3.jar wordcount $input_dir_path $outdir 11 | rm -rf $outdir 12 | -------------------------------------------------------------------------------- /jagoff: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | rewritebinpaths() { 4 | local modfile="$1" 5 | local binfiles="$2" 6 | set -e 7 | 8 | local binfile 9 | printf "%s\n" "$binfiles" | while read binfile 10 | do 11 | extractfile "meta.${binfile}_binary" "$binfile" 12 | local pathoffsets="`strings -td "$modfile" | sed -n "s: *\(.*/.*$binfile\)$:\1:p" | cut -d" " -f1`" 13 | local pathoffset 14 | printf "%s\n" "$pathoffsets" | while read pathoffset 15 | do 16 | printf "%s\0" "$binfile" | dd of="$modfile" seek="$pathoffset" bs=1 conv=notrunc 2>/dev/null 17 | done 18 | done 19 | } 20 | 21 | extractfile() { 22 | local whichkey="$1" 23 | local filename="$2" 24 | shift 2 25 | set -e 26 | 27 | local temporary="$filename.tmp" 28 | jaguar/jaguar get "$jagfile" "$whichkey" | base64 -d >"$temporary" 29 | 30 | if [ $# -gt 0 ] 31 | then 32 | local postproccmd="$1" 33 | shift 34 | "$postproccmd" "$temporary" "$@" 35 | fi 36 | 37 | if [ -e "$filename" ] 38 | then 39 | if diff "$filename" "$temporary" >/dev/null 40 | then 41 | local exitcode="0" 42 | else 43 | printf "%s\n" "ERROR: $filename: already exists!" >&2 44 | local exitcode="3" 45 | fi 46 | 47 | rm "$temporary" 48 | return "$exitcode" 49 | fi 50 | 51 | mv "$temporary" "$filename" 52 | } 53 | 54 | set -e 55 | if [ $# -lt 2 ] 56 | then 57 | cat <<-tac 58 | USAGE: $0 [Perf argument]..." 59 | 60 | Extracts a Perf recording and the binaries it profiles from an experiment datafile, 61 | fixes paths so that symbols can be resolved regardless of whether it's being run on 62 | the same machine that ran the experiment and without modifying the experimental 63 | infrastructure, and launches perf report, optionally with command-line arguments. 64 | 65 | probably ends in '.json'. 66 | probably ends in '.perf_data'. 67 | [Perf argument]s are for 'perf report'. 68 | tac 69 | exit 2 70 | fi 71 | jagfile="$1" 72 | perfkey="$2" 73 | shift 2 74 | 75 | perffile="perf.$perfkey.data" 76 | binaries="`cut -d'"' -f2 "$jagfile" | sed -n 's/\(.*\)_binary$/\1/p' | sort | uniq`" 77 | extractfile "$perfkey" "$perffile" rewritebinpaths "$binaries" 78 | 79 | perf report -i"$perffile" "$@" 80 | 81 | fuser "$perffile" >/dev/null 2>&1 || rm "$perffile" 82 | -------------------------------------------------------------------------------- /jaguar/arrcsv: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ $# -lt 2 -o $# -gt 3 ] 4 | then 5 | cat <<-tac 6 | USAGE: $0 [-n] 7 | 8 | -n means no header 9 | 10 | To get a CSV of a particular series, you can do: 11 | $ ./arrcsv data..samples 12 | 13 | To get a simple listing of the points within a data point whose dependent is recorded as a list, try: 14 | $ ./arrcsv data..samples[]. 15 | tac 16 | exit 1 17 | fi 18 | 19 | prnhdr="true" 20 | if [ $# -eq 3 ] 21 | then 22 | case "$1" in 23 | "-n") 24 | prnhdr="false" 25 | shift 26 | ;; 27 | *) 28 | echo "That was not an -n!" >&2 29 | exit 2 30 | ;; 31 | esac 32 | fi 33 | 34 | jagfile="$1" 35 | array="$2" 36 | 37 | linenum() { 38 | local regexp="$1" 39 | grep -ne "$regexp" | head -n1 | cut -d: -f1 40 | } 41 | 42 | res="`PYTHONHASHSEED="0" "$(dirname "$0")/jaguar" get "$jagfile" "$array" | sed -e 's/\[\(.*\)\]/\1/' -e 's/, /\n/g'`" 43 | 44 | open="`echo "$res" | linenum '{'`" 45 | close="`echo "$res" | linenum '}'`" 46 | 47 | header="`echo "$array" | rev | cut -d. -f1 | rev`" 48 | if [ -n "$open" -a -n "$close" ] 49 | then 50 | stride="`echo "$close - $open + 1" | bc`" 51 | header="`echo "$res" | head -n"$stride" | sed 's/.*'"'"'\([^'"'"']\+\)'"'"'.*/\1/' | paste -sd,`" 52 | delims="`for num in $(seq "$stride"); do echo -n ,; done | sed 's/,$/\\\n/'`" 53 | res="`echo "$res" | sed 's/}//' | rev | cut -d" " -f1 | rev | paste -sd"$delims"`" 54 | fi 55 | 56 | "$prnhdr" && echo "$header" 57 | echo "$res" 58 | -------------------------------------------------------------------------------- /jaguar/notes_json_format.txt: -------------------------------------------------------------------------------- 1 | { 2 | meta: { 3 | 4 | } 5 | legend: [ 6 | "args": [ 7 | { 8 | "name": , 9 | [ 10 | { 11 | "argument_name": , 12 | "description": , 13 | "unit": 14 | } 15 | ] 16 | } 17 | ] 18 | samples: [ 19 | { 20 | "name": , 21 | "description": , 22 | "unit": 23 | } 24 | ] 25 | ] 26 | data: [ 27 | { 28 | "name": , 29 | "description": 30 | "type": <--- this is used to look up under arguments in legend, 31 | "args": 32 | [ 33 | { 34 | "name_of_arg": 35 | "value": 36 | } 37 | ] 38 | "samples": [ 39 | { 40 | "x0_name": x0, <--- These keys should have entries in the legend 41 | "y0_name": y0, 42 | "y1_name": y1 43 | } 44 | ] 45 | } 46 | ] 47 | } 48 | -------------------------------------------------------------------------------- /jaguar/template.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": {}, 3 | "legend": { 4 | "args": {}, 5 | "samples": {} 6 | }, 7 | "meta": { 8 | "command": "", 9 | "commit": "", 10 | "date": "", 11 | "exit": -1, 12 | "log": "", 13 | "message": "", 14 | "patch": "", 15 | "perf": "", 16 | "status": "", 17 | "submodule": "", 18 | "uname": "", 19 | "unpack": "" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /jaguar/template_postprocessed.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": {}, 3 | "legend": { 4 | "args": {}, 5 | "samples": {} 6 | }, 7 | "meta": { 8 | "origfile": "" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /jaguar/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "meta": { 3 | "command": "fruit-tree" 4 | }, 5 | "legend": { 6 | "args": { 7 | "fruit-tree": { 8 | "--fruits": { 9 | "description": "Type of fruit", 10 | "unit": "fruit" 11 | } 12 | } 13 | }, 14 | "samples": { 15 | "successful": { 16 | "description": "Whether it was successful", 17 | "unit": "truths" 18 | }, 19 | "x0": { 20 | "description": "x0 value", 21 | "unit": "miles" 22 | }, 23 | "y0": { 24 | "description": "y0 value", 25 | "unit": "cookies" 26 | } 27 | } 28 | }, 29 | "data": { 30 | "series1": { 31 | "description": "apple series", 32 | "type": "fruit-tree", 33 | "args": [ 34 | { 35 | "name": "--fruits", 36 | "value": "apple" 37 | } 38 | ], 39 | "samples": [ 40 | { 41 | "x0": "1", 42 | "y0": "10", 43 | "z0": "100" 44 | }, 45 | { 46 | "x0": "2", 47 | "y0": "20" 48 | } 49 | ] 50 | }, 51 | "series2": { 52 | "description": "orange series", 53 | "type": "fruit-tree", 54 | "args": [ 55 | { 56 | "name": "--fruits", 57 | "value": "orange" 58 | } 59 | ], 60 | "samples": [ 61 | { 62 | "x0": "1", 63 | "y0": "100" 64 | }, 65 | { 66 | "x0": "2", 67 | "y0": "200" 68 | } 69 | ] 70 | } 71 | } 72 | } 73 | 74 | -------------------------------------------------------------------------------- /lepton_wrapper: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # lepton_wrapper IN-DIR-PATH [[ITERS] LEPTON-OPTIONS] 4 | 5 | input_dir_path=$1 6 | shift 7 | corpus_iters=1 8 | if [ $# -gt 0 ] 9 | then 10 | corpus_iters=$1 11 | shift 12 | fi 13 | 14 | count=0 15 | 16 | for iter in `seq "$corpus_iters"` 17 | do 18 | for filename in "$input_dir_path/"* 19 | do 20 | ./lepton "$@" - < "$filename" > /dev/null 21 | if [ "$?" -eq 0 ]; then count="$((count + 1))"; fi 22 | done 23 | done 24 | 25 | echo "count: $count" 26 | 27 | -------------------------------------------------------------------------------- /lockserver-driver: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | enable_cat=false 4 | logfile_name="lockserver_log" 5 | dataseries="lockserver" 6 | 7 | lockserver_alloc_percent=100 8 | trash_alloc_percent=100 9 | 10 | traverse_subset=0 11 | 12 | num_trash=8 13 | signal_iters=1 14 | signal_pause=0 15 | 16 | accesses_per_sample=163840000 17 | 18 | while [ $# -ge 1 ] 19 | do 20 | case "$1" in 21 | "-c") 22 | enable_cat=true 23 | ;; 24 | "-m") 25 | lockserver_mask="$2" 26 | shift 27 | ;; 28 | "-p") 29 | trash_mask="$2" 30 | shift 31 | ;; 32 | "-o") 33 | logfile_name="$2" 34 | shift 35 | ;; 36 | "-d") 37 | dataseries="$2" 38 | shift 39 | ;; 40 | "-l") 41 | lockserver_alloc_percent="$2" 42 | shift 43 | ;; 44 | "-t") 45 | trash_alloc_percent="$2" 46 | shift 47 | ;; 48 | "-s") 49 | traverse_subset="$2" 50 | accesses_per_sample="$2" 51 | shift 52 | ;; 53 | "-n") 54 | num_trash="$2" 55 | shift 56 | ;; 57 | "-i") 58 | signal_iters="$2" 59 | shift 60 | ;; 61 | "-w") 62 | # NB: Make certain this value (microseconds) is long enough to allow each -s-access 63 | # subset to complete; otherwise, some of the signals will be missed! 64 | signal_pause="$2" 65 | shift 66 | ;; 67 | "-a") 68 | extra_args="$2" 69 | shift 70 | ;; 71 | *) 72 | echo "Invalid argument" 73 | exit 1 74 | esac 75 | shift 76 | done 77 | 78 | cgroup_path="/sys/fs/cgroup/intel_rdt" 79 | 80 | if "$enable_cat" 81 | then 82 | if [ -z "$lockserver_mask" -o -z "$trash_mask" ] 83 | then 84 | echo "WOAH: You passed in -c, so I also require an explicit -m (lockserver mask) and -p (get trashed)" >&2 85 | exit 1 86 | fi 87 | else 88 | # Default value should be the OR of trash_mask and lockserver_mask if $enable_cat is true 89 | trash_mask=0xfff 90 | fi 91 | 92 | mkdir $cgroup_path/trash 93 | echo $trash_mask > $cgroup_path/trash/intel_rdt.l3_cbm 94 | #by doing this, our child processes are automatically added to the trash cgroup 95 | echo $$ > $cgroup_path/trash/tasks 96 | 97 | # This is the lockserver, which performs 327.62M memory accesses and then exits 98 | clients/square_evictions_wrapper "$dataseries" -p $((10000 * 100 / lockserver_alloc_percent)) -n 1 -c "$lockserver_alloc_percent" -e "$lockserver_alloc_percent" -hr -ia "$traverse_subset" -w $extra_args >"$logfile_name" 2>"$logfile_name.err" & 99 | rawpid="`while ! (ps -eo pid,args | sed 's/^ \+//' | cut -d" " -f1-2 | grep -w clients/square_evictions); do :; done`" 100 | pid="`echo "$rawpid" | cut -d" " -f1`" 101 | 102 | if "$enable_cat" 103 | then 104 | mkdir $cgroup_path/lockserver 105 | echo $pid > $cgroup_path/lockserver/tasks 106 | echo $lockserver_mask > $cgroup_path/lockserver/intel_rdt.l3_cbm 107 | fi 108 | 109 | 110 | for var in `seq 1 "$num_trash"`; do 111 | clients/square_evictions -c "$trash_alloc_percent" -e "$trash_alloc_percent" -hr > /dev/null & 112 | done 113 | sleep 10 114 | 115 | for var in `seq 1 "$signal_iters"` 116 | do 117 | kill -s 10 $pid 118 | usleep "$signal_pause" 119 | done 120 | 121 | # Sleep to allow our processes to actually run for a little while 122 | sleep 2 123 | 124 | # Don't kill the contending processes until the lockserver has gracefully exited. 125 | # Without this, the teardown interval will creep into our results! 126 | kill "$pid" 127 | while (ps -eo pid | grep -x "$pid" >/dev/null 2>&1); do :; done 128 | 129 | # CLEANUP 130 | killall square_evictions 131 | [ "$num_trash" -ne 0 ] && while (ps -eo args | cut -d" " -f1 | grep -x clients/square_evictions >/dev/null 2>&1); do :; done 132 | cgdelete intel_rdt:trash 133 | if "$enable_cat" 134 | then 135 | cgdelete intel_rdt:lockserver 136 | fi 137 | 138 | normalized="$(echo "`./avg_data.pl "$logfile_name"` / $accesses_per_sample" | bc -l)" 139 | santycheck="$(echo "1 / `./avg_data.pl "$logfile_name.err" accesses/s`" | bc -l)" 140 | 141 | if [ "`printf 'define abs(n) { if(n >= 0) return(n) else return(-n) }\nabs(%s - %s) / %s >= 0.5\n' "$normalized" "$santycheck" "$santycheck" | bc -l`" -ne 0 ] 142 | then 143 | echo "WARN: Normalized result (`echo "$normalized" | head -n1`) at least 5% off from sanity check (`echo "$santycheck"`)!" >&2 144 | fi 145 | echo "$normalized" 146 | -------------------------------------------------------------------------------- /locksmith.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "bench_commands.h" 7 | #include "log.h" 8 | #include "prep_system.h" 9 | 10 | // Should be at least 2, on 1 it might measure memory fetches, 2+ will use definitely use cache 11 | #define LARGE_NUMBER "2" 12 | 13 | #define COMMON_COS 1 14 | #define OTHER_COS 2 15 | 16 | #define READER_CORE 0 17 | #define SWITCHER_CORE 1 18 | 19 | // 21 takes about 8 seconds 20 | // 23 takes about 40 seconds 21 | // 24 takes about 1 minute 22 | #define NUM_SWITCHES (1 << 24) 23 | 24 | #define MASK_SWAP 25 | #undef COS_SWAP 26 | 27 | static test_prog_t progs[] = { 28 | { 29 | .cmdline = {"clients/square_evictions", "-e25", "-c25", "-n"LARGE_NUMBER, "-m", "-h"}, 30 | .target_cpu = 0, 31 | }, 32 | }; 33 | 34 | // Initial state is both cores on same CoS 35 | static const unsigned COS_MAPPINGS[] = { 36 | [READER_CORE] = COMMON_COS, 37 | [SWITCHER_CORE] = COMMON_COS 38 | }; 39 | static const size_t NUM_COS_MAPPINGS = sizeof COS_MAPPINGS / sizeof *COS_MAPPINGS; 40 | 41 | static const struct pqos_l3ca COS_MASKS[] = { 42 | { 43 | .class_id = COMMON_COS, 44 | .ways_mask = 0x1 | 0x2 | 0x4 | 0x8, 45 | }, { 46 | .class_id = OTHER_COS, 47 | .ways_mask = 0x10 | 0x20 | 0x40 | 0x80, 48 | }, 49 | }; 50 | 51 | static const struct pqos_l3ca COS_MASKS2[] = { 52 | { 53 | .class_id = OTHER_COS, 54 | .ways_mask = 0x1 | 0x2 | 0x4 | 0x8, 55 | }, 56 | }; 57 | 58 | static const struct pqos_l3ca COS_MASKS3[] = { 59 | { 60 | .class_id = OTHER_COS, 61 | .ways_mask = 0x10 | 0x20 | 0x40 | 0x80, 62 | }, 63 | }; 64 | 65 | static const size_t NUM_COS_MASKS = sizeof COS_MASKS / sizeof *COS_MASKS; 66 | 67 | int main(int argc, char** argv) { 68 | int swappy = 0; 69 | /* lol */ 70 | if(argc > 1) { 71 | if(argv[1][0] == '-' && argv[1][1] == 's') 72 | swappy = 1; 73 | } 74 | /* end lol */ 75 | if(prep_system(false, -1) < 0) { 76 | log_msg(LOG_FATAL, "Failed to complete initial setup\n"); 77 | return 1; 78 | } 79 | if(pqos_l3ca_set(0, NUM_COS_MASKS, COS_MASKS) != PQOS_RETVAL_OK) { 80 | log_msg(LOG_FATAL, "Failed to set CoS masks\n"); 81 | return 1; 82 | } 83 | /* Librarify this? */ 84 | for(unsigned core = 0; core < NUM_COS_MAPPINGS; ++core) { 85 | if(pqos_l3ca_assoc_set(core, COS_MAPPINGS[core]) != PQOS_RETVAL_OK) { 86 | log_msg(LOG_FATAL, "Failed to associate CoS with core\n"); 87 | return 1; 88 | } 89 | unsigned thenum = 0; 90 | assert(pqos_l3ca_assoc_get(core, &thenum) == PQOS_RETVAL_OK); 91 | assert(thenum == COS_MAPPINGS[core]); 92 | // FIXME: This is needed due to a race in libpqos: otherwise, only the first works! 93 | sleep(2); 94 | } 95 | run_benchmarks(progs, 1); 96 | if(swappy) { 97 | #ifdef COS_SWAP 98 | printf("Swapping CoSes\n"); 99 | for(int i = 0; i < NUM_SWITCHES; ++i) { 100 | if(pqos_l3ca_assoc_set(SWITCHER_CORE, OTHER_COS) != PQOS_RETVAL_OK) { 101 | log_msg(LOG_FATAL, "Failed to switch Cos on switcher process\n"); 102 | } 103 | } 104 | /* Keep swapping COS of our other core */ 105 | // TODO fix this 106 | printf("Done swapping!\n"); 107 | #endif 108 | #ifdef MASK_SWAP 109 | printf("Swapping masks\n"); 110 | for(int i = 0; i < NUM_SWITCHES; ++i) { 111 | pqos_l3ca_set(0, 1, COS_MASKS2); 112 | pqos_l3ca_set(0, 1, COS_MASKS3); 113 | } 114 | printf("Done swapping!\n"); 115 | 116 | #endif 117 | } 118 | wait_benchmarks(); 119 | cleanup_system(true); 120 | } 121 | -------------------------------------------------------------------------------- /log.c: -------------------------------------------------------------------------------- 1 | #include "log.h" 2 | 3 | #include 4 | 5 | static const char *const VERBOSITY_DESCRS[] = { 6 | "FATAL: ", 7 | "ERROR: ", 8 | "WARNING: ", 9 | "INFO: ", 10 | "VERBOSE: ", 11 | }; 12 | 13 | #ifndef LOG_DEFAULT_VERBOSITY 14 | #define LOG_DEFAULT_VERBOSITY LOG_ERROR 15 | #endif 16 | 17 | static log_verbosity_t max_handled = LOG_DEFAULT_VERBOSITY; 18 | static FILE *write_dest = NULL; 19 | 20 | static inline void init_write_dest(void) { 21 | if (!write_dest) 22 | write_dest = stderr; 23 | } 24 | 25 | log_verbosity_t log_get_verbosity(void) { 26 | return max_handled; 27 | } 28 | 29 | void log_set_verbosity(log_verbosity_t max) { 30 | max_handled = max; 31 | } 32 | 33 | FILE *log_get_dest(void) { 34 | init_write_dest(); 35 | return write_dest; 36 | } 37 | 38 | void log_set_dest(FILE *stream) { 39 | write_dest = stream; 40 | } 41 | 42 | int log_msg(log_verbosity_t verb, const char *format, ...) { 43 | init_write_dest(); 44 | 45 | if(verb > max_handled) 46 | return 0; 47 | 48 | va_list ap; 49 | va_start(ap, format); 50 | // TODO: Log caller's name? 51 | fputs(VERBOSITY_DESCRS[verb], write_dest); 52 | int ret = vfprintf(write_dest, format, ap); 53 | va_end(ap); 54 | 55 | return ret; 56 | } 57 | -------------------------------------------------------------------------------- /log.h: -------------------------------------------------------------------------------- 1 | #ifndef CATBENCH_LOG_H_ 2 | #define CATBENCH_LOG_H_ 3 | 4 | #include 5 | 6 | typedef enum { 7 | LOG_FATAL, 8 | LOG_ERROR, 9 | LOG_WARNING, 10 | LOG_INFO, 11 | LOG_VERBOSE, 12 | } log_verbosity_t; 13 | 14 | log_verbosity_t log_get_verbosity(void); 15 | void log_set_verbosity(log_verbosity_t max); 16 | FILE *log_get_dest(void); 17 | void log_set_dest(FILE *stream); 18 | int log_msg(log_verbosity_t verb, const char *format, ...); 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /network_rawnums: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | readonly DATA_POINT_DELIM_REGEX='RUNNING [A-Z]\+:' 4 | readonly FIELDS_LIST="table_entries round_trip_time" 5 | readonly SAMPLE_REGEX_CLIENT='.*remote: Completed after: \([0-9]\+\) us.*' 6 | readonly SAMPLE_REGEX_SERVER='.*Computed in: \([0-9]\+\) us.*' 7 | readonly SERIES_LIST_CLIENT="baseline basealloc contention allocation" 8 | readonly SERIES_SUFFIX_SERVER="_overhead" 9 | 10 | set -e 11 | . ./postprocess.sh 12 | 13 | puts() { 14 | printf '%s\n' "$@" 15 | } 16 | 17 | iter_deref() { 18 | local var="$1" 19 | eval puts '"$'"$var"'"' | head -n "$samples_per_point" 20 | } 21 | 22 | iter_advance() { 23 | local var="$1" 24 | eval "$var='`eval puts '"$'"$var"'"' | tail -n +"$((samples_per_point + 1))"`'" 25 | } 26 | 27 | iter_empty() { 28 | local logvar="$1" 29 | [ -z "`iter_deref "$logvar"`" ] 30 | } 31 | 32 | copyseries() { 33 | local serieslist="$1" 34 | local entryindex="$2" 35 | local logvar="$3" 36 | 37 | set -e 38 | for seriesname in $serieslist 39 | do 40 | echo -n . 41 | reuse "data.$seriesname.samples[$entryindex].$independent" integer 42 | [ "`iter_deref "$logvar" | wc -l`" -eq "$samples_per_point" ] || { echo "Missing expected number of samples for data point: the log must be missing some entries!" >&2 && false; } 43 | iter_deref "$logvar" | sed '1i\unstructured\ninteger' | jaguar/jaguar set "$outfile" "data.$seriesname.samples[$entryindex].$dependent" array - 44 | iter_advance "$logvar" 45 | done 46 | } 47 | 48 | calculateoh() { 49 | local clientvar="$1" 50 | local servervar="$2" 51 | 52 | local origlen="`puts "$servervar" | wc -l`" 53 | set -e 54 | [ -p allclients ] || mkfifo allclients 55 | eval puts '"$'"$clientvar"'"' >allclients & 56 | [ -p allservers ] || mkfifo allservers 57 | eval puts '"$'"$servervar"'"' >allservers & 58 | eval "$servervar='`paste -d"-\n" allclients allservers | bc`'" 59 | rm allclients allservers 60 | [ "`puts "$servervar" | wc -l`" -eq "$origlen" ] 61 | } 62 | 63 | [ "`puts "$FIELDS_LIST" | wc -w`" -eq 2 ] 64 | readonly independent="`puts "$FIELDS_LIST" | cut -d" " -f1`" 65 | readonly dependent="`puts "$FIELDS_LIST" | cut -d" " -f2`" 66 | readonly series_list_server="`puts "$SERIES_LIST_CLIENT" | sed "s/ \|$/$SERIES_SUFFIX_SERVER&/g"`" 67 | 68 | echo -n "Munging experiment log" 69 | 70 | log="`decode log`" 71 | echo -n . 72 | log_client="`puts "$log" | grep -e "$DATA_POINT_DELIM_REGEX" -e "$SAMPLE_REGEX_CLIENT"`" 73 | echo -n . 74 | readonly sample_delims="`puts "$log_client" | grep -n "$DATA_POINT_DELIM_REGEX"`" 75 | echo -n . 76 | readonly series_per_machine="`puts "$SERIES_LIST_CLIENT" | wc -w`" 77 | echo -n . 78 | readonly points_per_series="`puts "$sample_delims" | wc -l | sed '$a\'"$series_per_machine" | paste -sd/ | bc`" 79 | echo -n . 80 | readonly samples_per_point="`puts "$sample_delims" | cut -d: -f1 | tac | head -n2 | sed '$a\1' | paste -sd- | bc`" 81 | echo 82 | 83 | cat <<-tac 84 | 85 | According to the log, this experiemnt appears to have had the following parameters: 86 | Data series: $((series_per_machine * 2)) 87 | Series from each machine: $series_per_machine 88 | Data points per series: $points_per_series 89 | Samples per data point: $samples_per_point 90 | tac 91 | echo -n "Is this correct (y/N)? " 92 | read approved 93 | [ "$approved" = "y" ] || { echo "Not confirmed; aborting!" >&2 && false; } 94 | unset approved 95 | echo 96 | 97 | echo -n "Classifying log data" 98 | log_client="`puts "$log_client" | sed -n "s/$SAMPLE_REGEX_CLIENT/\1/p"`" 99 | echo -n . 100 | log_server="`puts "$log" | sed -n "s/$SAMPLE_REGEX_SERVER/\1/p"`" 101 | echo -n . 102 | unset log 103 | echo 104 | 105 | echo -n "Copying legend entries" 106 | for field in $FIELDS_LIST 107 | do 108 | reuse "legend.samples.$field.description" string 109 | echo -n . 110 | reuse "legend.samples.$field.unit" string 111 | echo -n . 112 | done 113 | echo 114 | 115 | has_overheads="true" 116 | echo -n "Copying series labels" 117 | for series in $SERIES_LIST_CLIENT $series_list_server 118 | do 119 | if grep -v "\<$series\>" "$SERIES_LIST_CLIENT" >/dev/null && ! jaguar/jaguar get "$infile" "data.$series.description" >/dev/null 2>&1 120 | then 121 | has_overheads="false" 122 | break 123 | fi 124 | 125 | reuse "data.$series.description" string 126 | echo -n . 127 | done 128 | echo 129 | 130 | if "$has_overheads" 131 | then 132 | echo "Computing network overheads..." 133 | calculateoh log_client log_server 134 | else 135 | echo "No network overhead information found; skipping extraction!" 136 | fi 137 | 138 | for index in `seq 0 "$((points_per_series - 1))"` 139 | do 140 | echo -n "Processing record index: $index..." 141 | 142 | "$has_overheads" && echo -n "(client)" 143 | copyseries "$SERIES_LIST_CLIENT" "$index" log_client 144 | 145 | if "$has_overheads" 146 | then 147 | echo -n "(server)" 148 | copyseries "$series_list_server" "$index" log_server 149 | fi 150 | 151 | echo 152 | done 153 | 154 | { iter_empty log_client && iter_empty log_server; } || { echo "Extra leftover samples in log: we must have misparsed it!" >&2 && false; } 155 | 156 | echo "All done! Result is in: $outfile" 157 | -------------------------------------------------------------------------------- /network_slowdown: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | . ./postprocess.sh 4 | 5 | reuse legend.samples.table_entries.description string 6 | reuse legend.samples.table_entries.unit string 7 | jaguar/jaguar set "$outfile" legend.samples.slowdown_factor.description string "Resulting slowdown factor" 8 | jaguar/jaguar set "$outfile" legend.samples.slowdown_factor.unit string "" 9 | jaguar/jaguar set "$outfile" data.introducing_contenders.description string "Adding contending processes without CAT" 10 | jaguar/jaguar set "$outfile" data.turning_off_cat.description string "Turning off CAT with contending processes" 11 | 12 | elem="0" 13 | while bounds baseline "$elem" 14 | do 15 | jaguar/jaguar get "$infile" data.baseline.samples[$elem].table_entries 16 | reuse data.baseline.samples[$elem].table_entries integer data.introducing_contenders.samples[$elem].table_entries 17 | reuse data.baseline.samples[$elem].table_entries integer data.turning_off_cat.samples[$elem].table_entries 18 | introducing_contenders="`echo "$(sample round_trip_time contention "$elem") / $(sample round_trip_time baseline "$elem")" | bc -l`" 19 | jaguar/jaguar set "$outfile" data.introducing_contenders.samples[$elem].slowdown_factor fraction "$introducing_contenders" 20 | turning_off_cat="`echo "$(sample round_trip_time contention "$elem") / $(sample round_trip_time allocation "$elem")" | bc -l`" 21 | jaguar/jaguar set "$outfile" data.turning_off_cat.samples[$elem].slowdown_factor fraction "$turning_off_cat" 22 | elem=$((elem + 1)) 23 | done 24 | -------------------------------------------------------------------------------- /networked/.sh: -------------------------------------------------------------------------------- 1 | # Validates system plugins to ensure they override the appropriate functions. 2 | 3 | # Each set of modules should either define each of the following {variables,functions} or include their names in inherit_default_{init,impl}. 4 | readonly REQUIRED_VAR_INITS="SERVER_DIR SERVER_BIN SERVER_MIN_REV CLIENT_DIR CLIENT_BIN CLIENT_MIN_REV CONTENDER_DIR CONTENDER_BIN CONTENDER_MIN_REV CONTENDER_TPUT_UNIT PERF_INIT_PHRASE SINGLETON_CONTENDER SPAWNCONTENDERS WARMUP_DURATION MAIN_DURATION EXPECTS_FILES" 5 | readonly REQUIRED_FUN_IMPLS="genserverargs genclientargs gencontenderargs prephugepages awaitserverinit waitbeforeclient extracttput extractavelatency extractalllatencies extracttaillatency extractcontendertput oninit onwarmup onmainprocessing checkserverrev checkclientrev checkcontenderrev" 6 | 7 | isfun() { 8 | local name="$1" 9 | [ "`type "$name" | sed -n '1{p;q}' | rev | cut -d" " -f1 | rev`" = "function" ] 10 | } 11 | 12 | isvar() ( 13 | local name="$1" 14 | ! isfun "$name" && eval echo '"${'"$name"'?}"' >/dev/null 2>&1 15 | ) 16 | 17 | # These variables and functions don't need to be explicitly accounted for by the set of modules. 18 | for implicit in EXPECTS_FILES checkserverrev checkclientrev checkcontenderrev 19 | do 20 | if ! isvar "$implicit" && ! isfun "$implicit" 21 | then 22 | if echo "$REQUIRED_VAR_INITS" | grep "\<$implicit\>" >/dev/null 23 | then 24 | inherit_default_init="$inherit_default_init $implicit" 25 | elif echo "$REQUIRED_FUN_IMPLS" | grep "\<$implicit\>" >/dev/null 26 | then 27 | inherit_default_impl="$inherit_default_impl $implicit" 28 | else 29 | echo "Internal error: Accepted module parameter '$implicit' is registered as neither a variable nor a function!" 30 | exit 1 31 | fi 32 | fi 33 | done 34 | 35 | if ! echo "$INDEPENDENT_VAR_WHITELIST" | grep "\<$independent\>" >/dev/null 36 | then 37 | echo "$plugin: Module does not support varying parameter '$independent'!" >&2 38 | exit 1 39 | fi 40 | 41 | uhoh="false" 42 | 43 | for var in $inherit_default_init 44 | do 45 | if isvar "$var" 46 | then 47 | echo "Internal error: Module requested default initialization of specified constant '$var'!" >&2 48 | uhoh="true" 49 | continue 50 | fi 51 | 52 | case "$var" in 53 | SERVER_DIR|CLIENT_DIR|CONTENDER_DIR) 54 | eval "$var"='"clients"' 55 | ;; 56 | SERVER_MIN_REV|CLIENT_MIN_REV|CONTENDER_MIN_REV) 57 | eval "$var"='""' 58 | ;; 59 | CONTENDER_BIN) 60 | eval "$var"='"true"' 61 | ;; 62 | EXPECTS_FILES) 63 | eval "$var"='""' 64 | ;; 65 | SINGLETON_CONTENDER) 66 | eval "$var"='"false"' 67 | ;; 68 | *) 69 | echo "Internal error: Module requested nonexistant default initialization for constant '$var'!" >&2 70 | uhoh="true" 71 | ;; 72 | esac 73 | done 74 | unset inherit_default_init 75 | 76 | for var in $REQUIRED_VAR_INITS 77 | do 78 | if ! isvar "$var" 79 | then 80 | echo "Internal error: Module neither defines nor defers to default initialization of constant '$var'!" >&2 81 | uhoh="true" 82 | continue 83 | fi 84 | 85 | readonly "$var" 86 | done 87 | unset var 88 | 89 | for fun in $inherit_default_impl 90 | do 91 | if isfun "$fun" 92 | then 93 | echo "Internal error: Module requested default implementation of overridden function '$fun'!" >&2 94 | uhoh="true" 95 | continue 96 | fi 97 | 98 | case "$fun" in 99 | genserverargs|genclientargs) 100 | eval "$fun()" '{ 101 | true 102 | }' 103 | ;; 104 | gencontenderargs) 105 | eval "$fun()" '{ 106 | true 107 | }' 108 | ;; 109 | prephugepages) 110 | eval "$fun()" '{ 111 | sudo sh -c "echo 16384 >/proc/sys/vm/nr_hugepages" 112 | }' 113 | ;; 114 | awaitserverinit) 115 | eval "$fun()" '{ 116 | waitforalloc 0 117 | }' 118 | ;; 119 | waitbeforeclient) 120 | eval "$fun()" '{ 121 | true 122 | }' 123 | ;; 124 | extractavelatency) 125 | eval "$fun()" '{ 126 | grep -F "Average:" rtt_client | cut -d" " -f2 127 | }' 128 | ;; 129 | extractalllatencies) 130 | eval "$fun()" '{ 131 | grep -F "Completed after:" rtt_client | cut -d" " -f3 132 | }' 133 | ;; 134 | extracttaillatency) 135 | eval "$fun()" '{ 136 | local entries="$1" 137 | local percentile="$2" 138 | 139 | sed -n "`echo "$entries * $percentile / 100" | bc`{p;q}" 140 | }' 141 | ;; 142 | extractcontendertput) 143 | eval "$fun()" '{ 144 | echo 0 145 | }' 146 | ;; 147 | checkserverrev) 148 | eval "$fun()" '( 149 | cd "$SERVER_DIR" 150 | [ "`git log --oneline --no-abbrev-commit | grep "^$SERVER_MIN_REV" | wc -l`" -eq "1" ] 151 | )' 152 | ;; 153 | checkclientrev) 154 | eval "$fun()" '{ 155 | [ "`ssh "$foreign_client" " 156 | cd \"$remote_path/$CLIENT_DIR\" 157 | git log --oneline --no-abbrev-commit" | grep "^$CLIENT_MIN_REV" | wc -l`" -eq "1" ] 158 | }' 159 | ;; 160 | checkcontenderrev) 161 | eval "$fun()" '{ 162 | echo "WARNING: Module specifies CONTENDER_MIN_REV but provides no checkcontenderrev implementation...?" >&2 163 | false 164 | }' 165 | ;; 166 | *) 167 | echo "Internal error: Module requested nonexistant default implementation for function '$fun'!" >&2 168 | uhoh="true" 169 | ;; 170 | esac 171 | done 172 | unset inherit_default_impl 173 | 174 | for fun in $REQUIRED_FUN_IMPLS 175 | do 176 | if ! isfun "$fun" 177 | then 178 | echo "Internal error: Module neither defines nor defers to default implementation of function '$fun'!" >&2 179 | uhoh="true" 180 | fi 181 | done 182 | unset fun 183 | 184 | if "$uhoh" 185 | then 186 | exit 1 187 | fi 188 | unset uhoh 189 | -------------------------------------------------------------------------------- /networked/bzip2.sh: -------------------------------------------------------------------------------- 1 | CONTENDER_DIR="." 2 | CONTENDER_BIN="bzip2_wrapper" 3 | SINGLETON_CONTENDER="false" 4 | 5 | CONTENDER_TPUT_UNIT="B/s" 6 | 7 | inherit_default_init="$inherit_default_init CONTENDER_MIN_REV" 8 | inherit_default_impl="$inherit_default_impl" 9 | 10 | BZ_FILENAME="linux-4.7.tar" 11 | EXPECTS_FILES="$EXPECTS_FILES \"$CONTENDER_DIR/$BZ_FILENAME\"" 12 | 13 | gencontenderargs() { 14 | echo "$BZ_FILENAME /dev/null -9" 15 | } 16 | 17 | extractcontendertput() { 18 | total_filesize=0 19 | total_time=0 20 | 21 | if [ "$SPAWNCONTENDERS" != "oninit" -a "$SPAWNCONTENDERS" != "onwarmup" ] 22 | then 23 | for contender in `seq "$contenders"` 24 | do 25 | in_file="rtt_contender_$((contender - 1))" 26 | 27 | filesize="$(grep 'input size: ' $in_file | sed -e 's/input size: \(.*\)/\1/')" 28 | total_filesize="$((total_filesize + filesize))" 29 | 30 | # parse the real elapsed time from "time -p" 31 | # use bc -l to handle floating-point numbers 32 | time="$(grep 'real ' $in_file | sed -e 's/real \(.*\)/\1/')" 33 | total_time="$(echo $total_time + $time | bc -l)" 34 | done 35 | fi 36 | 37 | if [ "$total_time" != "0" ] 38 | then 39 | echo "$total_filesize * $contenders / $total_time" | bc -l 40 | else 41 | echo 0 42 | fi 43 | } 44 | -------------------------------------------------------------------------------- /networked/contender_duration.sh: -------------------------------------------------------------------------------- 1 | SPAWNCONTENDERS="onmainprocessing" 2 | 3 | const WARMUP_DURATION="3s" 4 | const warn MAIN_DURATION="10s" 5 | 6 | inherit_default_init="$inherit_default_init" 7 | inherit_default_impl="$inherit_default_impl" 8 | 9 | oninit() { 10 | true 11 | } 12 | 13 | onwarmup() { 14 | sleep "$WARMUP_DURATION" 15 | } 16 | 17 | onmainprocessing() { 18 | contender_pids=$(cat rtt_contender_pids | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//') 19 | if [ -n "$contender_pids" ] 20 | then 21 | wait `cat rtt_contender_pids` 22 | else 23 | sleep "$MAIN_DURATION" 24 | fi 25 | } 26 | -------------------------------------------------------------------------------- /networked/fixed_duration.sh: -------------------------------------------------------------------------------- 1 | SPAWNCONTENDERS="onwarmup" 2 | 3 | const WARMUP_DURATION="3s" 4 | const MAIN_DURATION="10s" 5 | 6 | inherit_default_init="$inherit_default_init" 7 | inherit_default_impl="$inherit_default_impl" 8 | 9 | oninit() { 10 | true 11 | } 12 | 13 | onwarmup() { 14 | sleep "$WARMUP_DURATION" 15 | } 16 | 17 | onmainprocessing() { 18 | sleep "$MAIN_DURATION" 19 | } 20 | -------------------------------------------------------------------------------- /networked/grpc_interval.sh: -------------------------------------------------------------------------------- 1 | SERVER_DIR="../grpc-catbench/build" 2 | SERVER_BIN="greeter_async_server" 3 | CLIENT_DIR="../grpc-catbench/build" 4 | CLIENT_BIN="netbench" 5 | 6 | const PREPOPULATE_TABLE="false" 7 | 8 | INDEPENDENT_VAR_WHITELIST="num_trash cache_ways table_entries mite_tput_limit zipf_alpha" 9 | 10 | PERF_INIT_PHRASE="grpc" 11 | 12 | inherit_default_init="$inherit_default_init" 13 | inherit_default_impl="$inherit_default_impl extractavelatency" 14 | 15 | SERVER_MIN_REV="ef82e16" 16 | CLIENT_MIN_REV="50ece37" 17 | 18 | genserverargs() { 19 | local multiplier="1" 20 | #if type genclientargs_table_entries_multiplier >/dev/null 2>&1 21 | #then 22 | # multiplier="`genclientargs_table_entries_multiplier`" 23 | #fi 24 | 25 | # if "$PREPOPULATE_TABLE" 26 | # then 27 | # echo "'$((table_entries * multiplier))'" 28 | # else 29 | # true 30 | # fi 31 | } 32 | 33 | genclientargs() { 34 | local multiplier="1" 35 | if type genclientargs_table_entries_multiplier >/dev/null 2>&1 36 | then 37 | multiplier="`genclientargs_table_entries_multiplier`" 38 | fi 39 | sleep 1 40 | 41 | echo "-n '300000' -o /dev/null '$((table_entries * multiplier))' '$MICA_GET_RATIO' '$zipf_alpha' '$mite_tput_limit'" 42 | } 43 | 44 | prephugepages() { 45 | sleep 1 46 | #"$SERVER_DIR/../script/setup.sh" 16384 0 47 | } 48 | 49 | awaitserverinit() { 50 | #waitforalloc 1024 51 | sleep 1 52 | } 53 | 54 | waitbeforeclient() { 55 | while ! grep '^tput' rtt_server >/dev/null 2>&1; do sleep 1; done 56 | } 57 | 58 | extractaillatencies() { 59 | true 60 | } 61 | 62 | extracttput() { 63 | local all="`grep "tput=" rtt_client | tail -n"$MAIN_DURATION" | cut -d"=" -f2 | perl -nle 'print $1 if /(\S+) Mops/' | sort -n`" 64 | 65 | #printf "%s\n" "$all" | tail -n+"$((MAIN_DURATION / 2))" | head -n1 66 | echo 0 67 | } 68 | 69 | extractalllatencies() { 70 | true 71 | } 72 | 73 | extracttaillatency() { 74 | local ign="$1" 75 | local percentile="$2" 76 | 77 | grep "^$percentile-th" rtt_client | cut -d" " -f2 78 | } 79 | -------------------------------------------------------------------------------- /networked/gunzip.sh: -------------------------------------------------------------------------------- 1 | CONTENDER_DIR="." 2 | CONTENDER_BIN="gzip_wrapper" 3 | SINGLETON_CONTENDER="false" 4 | 5 | CONTENDER_TPUT_UNIT="B/s" 6 | 7 | inherit_default_init="$inherit_default_init CONTENDER_MIN_REV" 8 | inherit_default_impl="$inherit_default_impl" 9 | 10 | GZ_FILENAME="linux-4.7.tar.gz" 11 | EXPECTS_FILES="$EXPECTS_FILES \"$CONTENDER_DIR/$GZ_FILENAME\"" 12 | 13 | gencontenderargs() { 14 | echo "$GZ_FILENAME /dev/null -d" 15 | } 16 | 17 | extractcontendertput() { 18 | total_filesize=0 19 | total_time=0 20 | 21 | if [ "$SPAWNCONTENDERS" != "oninit" -a "$SPAWNCONTENDERS" != "onwarmup" ] 22 | then 23 | for contender in `seq "$contenders"` 24 | do 25 | in_file="rtt_contender_$((contender - 1))" 26 | 27 | filesize="$(grep 'output size: ' $in_file | sed -e 's/output size: \(.*\)/\1/')" 28 | total_filesize="$((total_filesize + filesize))" 29 | 30 | # parse the real elapsed time from "time -p" 31 | # use bc -l to handle floating-point numbers 32 | time="$(grep 'real ' $in_file | sed -e 's/real \(.*\)/\1/')" 33 | total_time="$(echo $total_time + $time | bc -l)" 34 | done 35 | fi 36 | 37 | if [ "$total_time" != "0" ] 38 | then 39 | echo "$total_filesize * $contenders / $total_time" | bc -l 40 | else 41 | echo 0 42 | fi 43 | } 44 | -------------------------------------------------------------------------------- /networked/gzip.sh: -------------------------------------------------------------------------------- 1 | CONTENDER_DIR="." 2 | CONTENDER_BIN="gzip_wrapper" 3 | SINGLETON_CONTENDER="false" 4 | 5 | CONTENDER_TPUT_UNIT="B/s" 6 | 7 | inherit_default_init="$inherit_default_init CONTENDER_MIN_REV" 8 | inherit_default_impl="$inherit_default_impl" 9 | 10 | GZ_FILENAME="linux-4.7.tar" 11 | EXPECTS_FILES="$EXPECTS_FILES \"$CONTENDER_DIR/$GZ_FILENAME\"" 12 | 13 | gencontenderargs() { 14 | echo "$GZ_FILENAME /dev/null -9" 15 | } 16 | 17 | extractcontendertput() { 18 | total_filesize=0 19 | total_time=0 20 | 21 | if [ "$SPAWNCONTENDERS" != "oninit" -a "$SPAWNCONTENDERS" != "onwarmup" ] 22 | then 23 | for contender in `seq "$contenders"` 24 | do 25 | in_file="rtt_contender_$((contender - 1))" 26 | 27 | filesize="$(grep 'input size: ' $in_file | sed -e 's/input size: \(.*\)/\1/')" 28 | total_filesize="$((total_filesize + filesize))" 29 | 30 | # parse the real elapsed time from "time -p" 31 | # use bc -l to handle floating-point numbers 32 | time="$(grep 'real ' $in_file | sed -e 's/real \(.*\)/\1/')" 33 | total_time="$(echo $total_time + $time | bc -l)" 34 | done 35 | fi 36 | 37 | if [ "$total_time" != "0" ] 38 | then 39 | echo "$total_filesize * $contenders / $total_time" | bc -l 40 | else 41 | echo 0 42 | fi 43 | } 44 | -------------------------------------------------------------------------------- /networked/hadoop.sh: -------------------------------------------------------------------------------- 1 | CONTENDER_DIR="." 2 | CONTENDER_BIN="hadoop_wrapper" 3 | SINGLETON_CONTENDER="false" 4 | 5 | CONTENDER_TPUT_UNIT="MB/s" 6 | 7 | inherit_default_init="$inherit_default_init CONTENDER_MIN_REV" 8 | inherit_default_impl="$inherit_default_impl" 9 | 10 | TEXT_DIR="text/text_medium" 11 | EXPECTS_FILES="$EXPECTS_FILES" 12 | 13 | gencontenderargs() { 14 | echo "$TEXT_DIR" 15 | } 16 | 17 | extractcontendertput() { 18 | total_count=0 19 | total_time=0 20 | 21 | if [ "$SPAWNCONTENDERS" != "oninit" -a "$SPAWNCONTENDERS" != "onwarmup" ] 22 | then 23 | for contender in `seq "$contenders"` 24 | do 25 | in_file="rtt_contender_$((contender - 1))" 26 | 27 | count="$(grep 'Bytes Read= ' $in_file | sed -e 's/[:space:]*Bytes Read=\(.*\)/\1/')" 28 | total_count="$((total_count + count))" 29 | 30 | # parse the real elapsed time from "time -p" 31 | # use bc -l to handle floating-point numbers 32 | time="$(grep 'real ' $in_file | sed -e 's/real \(.*\)/\1/')" 33 | total_time="$(echo $total_time + $time | bc -l)" 34 | done 35 | fi 36 | 37 | if [ "$total_time" != "0" ] 38 | then 39 | echo "`du -sb $TEXT_DIR | cut -f1` * $contenders / $total_time" | bc -l 40 | else 41 | echo 0 42 | fi 43 | } 44 | -------------------------------------------------------------------------------- /networked/hadoop_short.sh: -------------------------------------------------------------------------------- 1 | CONTENDER_DIR="." 2 | CONTENDER_BIN="hadoop_wrapper" 3 | SINGLETON_CONTENDER="false" 4 | 5 | CONTENDER_TPUT_UNIT="MB/s" 6 | 7 | inherit_default_init="$inherit_default_init CONTENDER_MIN_REV" 8 | inherit_default_impl="$inherit_default_impl" 9 | 10 | TEXT_DIR="text/small" 11 | EXPECTS_FILES="$EXPECTS_FILES" 12 | 13 | gencontenderargs() { 14 | echo "$TEXT_DIR" 15 | } 16 | 17 | extractcontendertput() { 18 | total_count=0 19 | total_time=0 20 | 21 | if [ "$SPAWNCONTENDERS" != "oninit" -a "$SPAWNCONTENDERS" != "onwarmup" ] 22 | then 23 | for contender in `seq "$contenders"` 24 | do 25 | in_file="rtt_contender_$((contender - 1))" 26 | 27 | count="$(grep 'Bytes Read= ' $in_file | sed -e 's/[:space:]*Bytes Read=\(.*\)/\1/')" 28 | total_count="$((total_count + count))" 29 | 30 | # parse the real elapsed time from "time -p" 31 | # use bc -l to handle floating-point numbers 32 | time="$(grep 'real ' $in_file | sed -e 's/real \(.*\)/\1/')" 33 | total_time="$(echo $total_time + $time | bc -l)" 34 | done 35 | fi 36 | 37 | if [ "$total_time" != "0" ] 38 | then 39 | echo "`du -sb $TEXTID_R | cut -f1` * $contenders / $total_time" | bc -l 40 | else 41 | echo 0 42 | fi 43 | } 44 | -------------------------------------------------------------------------------- /networked/lepton.sh: -------------------------------------------------------------------------------- 1 | CONTENDER_DIR="." 2 | CONTENDER_BIN="lepton_wrapper" 3 | SINGLETON_CONTENDER="false" 4 | 5 | const IMAGES_ITERS="3" 6 | 7 | CONTENDER_TPUT_UNIT="images/s" 8 | 9 | inherit_default_init="$inherit_default_init CONTENDER_MIN_REV" 10 | inherit_default_impl="$inherit_default_impl" 11 | 12 | IMAGES_DIR="images" 13 | EXPECTS_FILES="$EXPECTS_FILES \"$CONTENDER_DIR/$IMAGES_DIR\"" 14 | 15 | gencontenderargs() { 16 | echo "$IMAGES_DIR $IMAGES_ITERS -allowprogressive -singlethread -unjailed" 17 | } 18 | 19 | extractcontendertput() { 20 | total_count=0 21 | total_time=0 22 | 23 | if [ "$SPAWNCONTENDERS" != "oninit" -a "$SPAWNCONTENDERS" != "onwarmup" ] 24 | then 25 | for contender in `seq "$contenders"` 26 | do 27 | in_file="rtt_contender_$((contender - 1))" 28 | 29 | count="$(grep 'count: ' $in_file | sed -e 's/count: \(.*\)/\1/')" 30 | total_count="$((total_count + count))" 31 | 32 | # parse the real elapsed time from "time -p" 33 | # use bc -l to handle floating-point numbers 34 | time="$(grep 'real ' $in_file | sed -e 's/real \(.*\)/\1/')" 35 | total_time="$(echo $total_time + $time | bc -l)" 36 | done 37 | fi 38 | 39 | if [ "$total_time" != "0" ] 40 | then 41 | echo "$total_count * $contenders / $total_time" | bc -l 42 | else 43 | echo 0 44 | fi 45 | } 46 | -------------------------------------------------------------------------------- /networked/lepton_long.sh: -------------------------------------------------------------------------------- 1 | CONTENDER_DIR="." 2 | CONTENDER_BIN="lepton_wrapper" 3 | SINGLETON_CONTENDER="false" 4 | 5 | const IMAGES_ITERS="15" 6 | 7 | CONTENDER_TPUT_UNIT="images/s" 8 | 9 | inherit_default_init="$inherit_default_init CONTENDER_MIN_REV" 10 | inherit_default_impl="$inherit_default_impl" 11 | 12 | IMAGES_DIR="images" 13 | EXPECTS_FILES="$EXPECTS_FILES \"$CONTENDER_DIR/$IMAGES_DIR\"" 14 | 15 | gencontenderargs() { 16 | echo "$IMAGES_DIR $IMAGES_ITERS -allowprogressive -singlethread -unjailed" 17 | } 18 | 19 | extractcontendertput() { 20 | total_count=0 21 | total_time=0 22 | 23 | if [ "$SPAWNCONTENDERS" != "oninit" -a "$SPAWNCONTENDERS" != "onwarmup" ] 24 | then 25 | for contender in `seq "$contenders"` 26 | do 27 | in_file="rtt_contender_$((contender - 1))" 28 | 29 | count="$(grep 'count: ' $in_file | sed -e 's/count: \(.*\)/\1/')" 30 | total_count="$((total_count + count))" 31 | 32 | # parse the real elapsed time from "time -p" 33 | # use bc -l to handle floating-point numbers 34 | time="$(grep 'real ' $in_file | sed -e 's/real \(.*\)/\1/')" 35 | total_time="$(echo $total_time + $time | bc -l)" 36 | done 37 | fi 38 | 39 | if [ "$total_time" != "0" ] 40 | then 41 | echo "$total_count * $contenders / $total_time" | bc -l 42 | else 43 | echo 0 44 | fi 45 | } 46 | -------------------------------------------------------------------------------- /networked/lockserver.sh: -------------------------------------------------------------------------------- 1 | SERVER_BIN="lockserver-ng" 2 | CLIENT_BIN="lockclient" 3 | 4 | INDEPENDENT_VAR_WHITELIST="cache_ways client_sleep table_entries" 5 | 6 | PERF_INIT_PHRASE="Initialization complete!" 7 | 8 | inherit_default_init="$inherit_default_init SERVER_DIR SERVER_MIN_REV CLIENT_DIR CLIENT_MIN_REV" 9 | inherit_default_impl="$inherit_default_impl prephugepages extractavelatency extractalllatencies extracttaillatency" 10 | 11 | genserverargs() { 12 | echo "-l '$table_entries' -- -c 0x1" 13 | } 14 | 15 | genclientargs() { 16 | echo "-m '$local_macaddr' -s '$client_sleep'" 17 | } 18 | 19 | awaitserverinit() { 20 | waitforalloc 0 21 | sleep 3 22 | } 23 | 24 | waitbeforeclient() { 25 | while ! grep "Initialization complete" >/dev/null 2>&1; do sleep 1; done 26 | } 27 | 28 | extracttput() { 29 | echo "0.0" 30 | } 31 | -------------------------------------------------------------------------------- /networked/mica.sh: -------------------------------------------------------------------------------- 1 | SERVER_DIR="../mica2-catbench/build" 2 | SERVER_BIN="server" 3 | CLIENT_DIR="../mica2-catbench/build" 4 | CLIENT_BIN="netbench" 5 | 6 | INDEPENDENT_VAR_WHITELIST="num_trash cache_ways table_entries mite_tput_limit zipf_alpha" 7 | 8 | PERF_INIT_PHRASE="tput=" 9 | 10 | inherit_default_init="$inherit_default_init" 11 | inherit_default_impl="$inherit_default_impl genserverargs extractavelatency" 12 | 13 | SERVER_MIN_REV="ec10efe" 14 | CLIENT_MIN_REV="6306ebf" 15 | 16 | genclientargs() { 17 | local multiplier="1" 18 | if type genclientargs_table_entries_multiplier >/dev/null 2>&1 19 | then 20 | multiplier="`genclientargs_table_entries_multiplier`" 21 | fi 22 | 23 | echo "-n '$MICA_RECORD_ITERATIONS' -o /dev/null '$((table_entries * multiplier))' '$MICA_GET_RATIO' '$zipf_alpha' '$mite_tput_limit'" 24 | } 25 | 26 | prephugepages() { 27 | "$SERVER_DIR/../script/setup.sh" 16384 0 28 | } 29 | 30 | awaitserverinit() { 31 | waitforalloc 1024 32 | sleep 3 33 | } 34 | 35 | waitbeforeclient() { 36 | while ! grep '^tput' rtt_server >/dev/null 2>&1; do sleep 1; done 37 | } 38 | 39 | extractaillatencies() { 40 | true 41 | } 42 | 43 | extracttput() { 44 | MAIN_DURATION_COPY=${MAIN_DURATION%?} 45 | local all="`grep "tput=" rtt_client | tail -n"$MAIN_DURATION_COPY" | cut -d"=" -f2 | perl -nle 'print $1 if /(\S+) Mops/' | sort -n`" 46 | 47 | printf "%s\n" "$all" | tail -n+"$((MAIN_DURATION_COPY / 2))" | head -n1 48 | } 49 | 50 | extractalllatencies() { 51 | true 52 | } 53 | 54 | extracttaillatency() { 55 | local ign="$1" 56 | local percentile="$2" 57 | 58 | grep "$percentile-th" rtt_client | cut -d" " -f2 59 | } 60 | -------------------------------------------------------------------------------- /networked/mica_interval.sh: -------------------------------------------------------------------------------- 1 | SERVER_DIR="../mica2-catbench/build" 2 | SERVER_BIN="server" 3 | CLIENT_DIR="../mica2-catbench/build" 4 | CLIENT_BIN="netbench_interval" 5 | 6 | const PREPOPULATE_TABLE="false" 7 | 8 | INDEPENDENT_VAR_WHITELIST="num_trash cache_ways table_entries mite_tput_limit zipf_alpha" 9 | 10 | PERF_INIT_PHRASE="tput=" 11 | 12 | inherit_default_init="$inherit_default_init" 13 | inherit_default_impl="$inherit_default_impl extractavelatency" 14 | 15 | SERVER_MIN_REV="ef82e16" 16 | CLIENT_MIN_REV="50ece37" 17 | 18 | genserverargs() { 19 | local multiplier="1" 20 | if type genclientargs_table_entries_multiplier >/dev/null 2>&1 21 | then 22 | multiplier="`genclientargs_table_entries_multiplier`" 23 | fi 24 | 25 | if "$PREPOPULATE_TABLE" 26 | then 27 | echo "'$((table_entries * multiplier))'" 28 | else 29 | true 30 | fi 31 | } 32 | 33 | genclientargs() { 34 | local multiplier="1" 35 | if type genclientargs_table_entries_multiplier >/dev/null 2>&1 36 | then 37 | multiplier="`genclientargs_table_entries_multiplier`" 38 | fi 39 | 40 | echo "-n '$MICA_RECORD_ITERATIONS' -o /dev/null '$((table_entries * multiplier))' '$MICA_GET_RATIO' '$zipf_alpha' '$mite_tput_limit'" 41 | } 42 | 43 | prephugepages() { 44 | "$SERVER_DIR/../script/setup.sh" 16384 0 45 | } 46 | 47 | awaitserverinit() { 48 | waitforalloc 1024 49 | sleep 3 50 | } 51 | 52 | waitbeforeclient() { 53 | while ! grep '^tput' rtt_server >/dev/null 2>&1; do sleep 1; done 54 | } 55 | 56 | extractaillatencies() { 57 | true 58 | } 59 | 60 | extracttput() { 61 | local all="`grep "tput=" rtt_client | tail -n"$MAIN_DURATION" | cut -d"=" -f2 | perl -nle 'print $1 if /(\S+) Mops/' | sort -n`" 62 | 63 | printf "%s\n" "$all" | tail -n+"$((MAIN_DURATION / 2))" | head -n1 64 | } 65 | 66 | extractalllatencies() { 67 | true 68 | } 69 | 70 | extracttaillatency() { 71 | local ign="$1" 72 | local percentile="$2" 73 | 74 | grep "^$percentile-th" rtt_client | cut -d" " -f2 75 | } 76 | -------------------------------------------------------------------------------- /networked/mica_sqlite.sh: -------------------------------------------------------------------------------- 1 | . networked/mica.sh 2 | 3 | SERVER_BIN="server_sqlite" 4 | -------------------------------------------------------------------------------- /networked/mica_wss_percentage.sh: -------------------------------------------------------------------------------- 1 | genclientargs_table_entries_multiplier() { 2 | echo "mica_wss_percentage: Fixing table_entries PERCENTAGE instead of absolute value" >&2 3 | echo "$cache_ways" | tr [a-z] [A-Z] | sed 's/0X/ibase=16; obase=2; /' | bc | tr -d "0\n" | wc -c 4 | } 5 | -------------------------------------------------------------------------------- /networked/square_evictions.sh: -------------------------------------------------------------------------------- 1 | CONTENDER_BIN="square_evictions" 2 | SINGLETON_CONTENDER="false" 3 | 4 | CONTENDER_TPUT_UNIT="accesses/s" 5 | 6 | inherit_default_init="$inherit_default_init CONTENDER_DIR CONTENDER_MIN_REV" 7 | inherit_default_impl="$inherit_default_impl" 8 | 9 | gencontenderargs() { 10 | if [ "$SPAWNCONTENDERS" = "oninit" -o "$SPAWNCONTENDERS" = "onwarmup" ] 11 | then 12 | printf "%s %s %s" -c"$TRASH_ALLOC" -e"$TRASH_ALLOC" -uhr 13 | else 14 | printf "%s %s %s %s %s" -c"$TRASH_ALLOC" -e"$TRASH_ALLOC" -whr -p 100 15 | fi 16 | } 17 | 18 | extractcontendertput() { 19 | total_accesses=0 20 | total_time=0 21 | 22 | if [ "$SPAWNCONTENDERS" != "oninit" -a "$SPAWNCONTENDERS" != "onwarmup" ] 23 | then 24 | for contender in `seq "$contenders"` 25 | do 26 | in_file="rtt_contender_$((contender - 1))" 27 | 28 | # add up all accesses 29 | for accesses in $(grep 'Accesses performed: ' $in_file | sed -e 's/Accesses performed: \(.*\)/\1/') 30 | do 31 | total_accesses="$((total_accesses + accesses))" 32 | done 33 | 34 | # parse the real elapsed time from "time -p" 35 | # use bc -l to handle floating-point numbers 36 | time="$(grep 'real ' $in_file | sed -e 's/real \(.*\)/\1/')" 37 | total_time="$(echo $total_time + $time | bc -l)" 38 | done 39 | fi 40 | 41 | if [ "$total_time" != "0" ] 42 | then 43 | echo "$total_accesses * $contenders / $total_time" | bc -l 44 | else 45 | echo 0 46 | fi 47 | } 48 | -------------------------------------------------------------------------------- /networked/tensorflow_mnist_long.sh: -------------------------------------------------------------------------------- 1 | CONTENDER_DIR="." 2 | CONTENDER_BIN="tensorflow_mnist_long" 3 | SINGLETON_CONTENDER="true" 4 | 5 | CONTENDER_TPUT_UNIT="epochs/s" 6 | 7 | inherit_default_init="$inherit_default_init CONTENDER_MIN_REV" 8 | inherit_default_impl="$inherit_default_impl" 9 | 10 | gencontenderargs() { 11 | true 12 | } 13 | 14 | extractcontendertput() { 15 | total_count=1 16 | total_time=0 17 | 18 | if [ "$SPAWNCONTENDERS" != "oninit" -a "$SPAWNCONTENDERS" != "onwarmup" -a "$contenders" -ne 0 ] 19 | then 20 | in_file="rtt_contender_0" 21 | 22 | # parse the real elapsed time from "time -p" 23 | total_time="$(grep 'real ' $in_file | sed -e 's/real \(.*\)/\1/')" 24 | fi 25 | 26 | if [ "$total_time" != "0" ] 27 | then 28 | echo $total_count / $total_time | bc -l 29 | else 30 | echo 0 31 | fi 32 | } 33 | -------------------------------------------------------------------------------- /networked/tensorflow_mnist_short.sh: -------------------------------------------------------------------------------- 1 | CONTENDER_DIR="." 2 | CONTENDER_BIN="tensorflow_mnist_short" 3 | SINGLETON_CONTENDER="true" 4 | 5 | CONTENDER_TPUT_UNIT="epochs/s" 6 | 7 | inherit_default_init="$inherit_default_init CONTENDER_MIN_REV" 8 | inherit_default_impl="$inherit_default_impl" 9 | 10 | gencontenderargs() { 11 | true 12 | } 13 | 14 | extractcontendertput() { 15 | total_count=1 16 | total_time=0 17 | 18 | if [ "$SPAWNCONTENDERS" != "oninit" -a "$SPAWNCONTENDERS" != "onwarmup" -a "$contenders" -ne 0 ] 19 | then 20 | in_file="rtt_contender_0" 21 | 22 | # parse the real elapsed time from "time -p" 23 | total_time="$(grep 'real ' $in_file | sed -e 's/real \(.*\)/\1/')" 24 | fi 25 | 26 | if [ "$total_time" != "0" ] 27 | then 28 | echo $total_count / $total_time | bc -l 29 | else 30 | echo 0 31 | fi 32 | } 33 | -------------------------------------------------------------------------------- /onmycommand.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | static void ignore(int sig) {(void) sig;} 8 | 9 | int main(int argc, char **argv) { 10 | if(argc < 2) { 11 | printf("USAGE: %s [...]\n\n" 12 | "Awaits SIGUSR1, then runs the specified command.\n", 13 | argv[0]); 14 | return 1; 15 | } 16 | 17 | for(int arg = 0; arg < argc -1; ++arg) 18 | argv[arg] = argv[arg + 1]; 19 | argv[argc - 1] = NULL; 20 | 21 | struct sigaction setup = {.sa_handler = ignore}; 22 | if(sigaction(SIGUSR1, &setup, NULL)) { 23 | perror("Installing signal handler"); 24 | return 2; 25 | } 26 | 27 | while(true) { 28 | pause(); 29 | 30 | if(!fork()) { 31 | execvp(argv[0], argv); 32 | perror("Spawning process"); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /perfexpl.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "syscallers.h" 12 | 13 | #define MAX_TEST_PROG_CMDLINE_WORDS 5 14 | typedef struct { 15 | const char *cmdline[MAX_TEST_PROG_CMDLINE_WORDS]; 16 | const char *const null; 17 | } test_prog_t; 18 | 19 | static const test_prog_t TEST_PROGS[] = { 20 | // TODO: Use hugepages! 21 | {.cmdline = {"clients/square_evictions", "-n1", "-c0", "-e25", "-r"}}, 22 | }; 23 | static const int NUM_TEST_PROGS = sizeof TEST_PROGS / sizeof *TEST_PROGS; 24 | 25 | #define PERF_BUFFER_NUM_PAGES (1 + (1 << 5)) 26 | static const struct perf_event_attr METRIC = { 27 | // TODO: Use bandwidth counter! 28 | .type = PERF_TYPE_HARDWARE, 29 | .config = PERF_COUNT_HW_CACHE_MISSES, 30 | .sample_period = 1, 31 | .sample_type = PERF_SAMPLE_READ | PERF_SAMPLE_TIME | PERF_SAMPLE_CPU, 32 | .disabled = 0x1, 33 | .enable_on_exec = 0x1, 34 | .size = sizeof METRIC, 35 | }; 36 | 37 | typedef struct { 38 | struct perf_event_header header; 39 | uint64_t time; 40 | uint32_t cpu, res; 41 | uint64_t value; 42 | } perf_record_sample_t; 43 | 44 | #define SIG_CHILD_PROC_UP SIGUSR1 45 | #define SIG_EXEC_TEST_PROG SIGUSR1 46 | 47 | typedef struct { 48 | pid_t pid; 49 | int fd; 50 | struct perf_event_mmap_page *buf; 51 | } test_proc_t; 52 | 53 | static sigset_t block_signal(int signal) { 54 | sigset_t mask; 55 | sigemptyset(&mask); 56 | sigaddset(&mask, signal); 57 | sigprocmask(SIG_BLOCK, &mask, NULL); 58 | return mask; 59 | } 60 | 61 | static void await_signal(int signal) { 62 | int received; 63 | sigset_t await = block_signal(signal); 64 | sigwait(&await, &received); 65 | assert(received == signal); 66 | } 67 | 68 | static inline perf_record_sample_t *first_sample(struct perf_event_mmap_page *ptr) { 69 | return (perf_record_sample_t *) ((uintptr_t) ptr + ptr->data_offset); 70 | } 71 | 72 | static inline void next_sample(perf_record_sample_t **ptr) { 73 | *ptr += (*ptr)->header.size; 74 | } 75 | 76 | int main(void) { 77 | test_proc_t children[NUM_TEST_PROGS]; 78 | memset(&children, 1, sizeof children); 79 | int ret = 0; 80 | 81 | for(int prog = 0; prog < NUM_TEST_PROGS; ++prog) { 82 | block_signal(SIG_CHILD_PROC_UP); 83 | pid_t pid = fork(); 84 | switch(pid) { 85 | case -1: 86 | perror("Forking child"); 87 | ret = 1; 88 | goto cleanup; 89 | case 0: 90 | // TODO: Set processor affinity 91 | kill(getppid(), SIG_CHILD_PROC_UP); 92 | await_signal(SIG_EXEC_TEST_PROG); 93 | exec_v(TEST_PROGS[prog].cmdline[0], TEST_PROGS[prog].cmdline); 94 | 95 | perror("Executing test program"); 96 | ret = 1; 97 | goto cleanup; 98 | default: 99 | await_signal(SIG_CHILD_PROC_UP); 100 | 101 | children[prog].pid = pid; 102 | 103 | struct perf_event_attr metric; 104 | memcpy(&metric, &METRIC, sizeof metric); 105 | int fd = perf_event_open(&metric, pid, -1, -1, 0); 106 | if(fd < 0) { 107 | fputs("Starting Perf: permissions?\n", stderr); 108 | ret = 1; 109 | goto cleanup; 110 | } 111 | children[prog].fd = fd; 112 | 113 | struct perf_event_mmap_page *buf = 114 | mmap(NULL, PERF_BUFFER_NUM_PAGES * getpagesize(), 115 | PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 116 | if(!buf || buf == MAP_FAILED) { 117 | perror("Mapping perf buffer"); 118 | ret = 1; 119 | goto cleanup; 120 | } 121 | children[prog].buf = buf; 122 | 123 | printf("Data buffer at %llu, size %llu\n", buf->data_offset, buf->data_size); 124 | printf("Data head at %llu\n", buf->data_head); 125 | } 126 | } 127 | 128 | for(int prog = 0; prog < NUM_TEST_PROGS; ++prog) 129 | if(kill(children[prog].pid, SIG_EXEC_TEST_PROG)) { 130 | ret = 1; 131 | goto cleanup; 132 | } 133 | 134 | // TODO: Use mremap() to dynamically resize bufs as data_head indicates they're filling up 135 | 136 | for(int prog = 0; prog < NUM_TEST_PROGS; ++prog) { 137 | if(waitpid(children[prog].pid, NULL, 0) < 0) 138 | perror("Awaiting child"); 139 | 140 | puts("time,cache-misses,cpu"); 141 | 142 | perf_record_sample_t *first = first_sample(children[prog].buf); 143 | printf("%u %u\n", first->header.size, sizeof *first); 144 | assert(first->header.size == sizeof *first); 145 | 146 | uint64_t last_misses = 0; 147 | for(perf_record_sample_t *each = first; 148 | (uintptr_t) each < 149 | (uintptr_t) children[prog].buf + children[prog].buf->data_size; 150 | next_sample(&each)) { 151 | printf("%" PRId64 ",%" PRId64 ",%" PRId32 "\n", each->time, each->value - last_misses, each->cpu); 152 | last_misses = each->value; 153 | } 154 | 155 | printf("Test program ran for %llu ns\n", children[prog].buf->time_running); 156 | printf("Data head at %llu\n", children[prog].buf->data_head); 157 | } 158 | 159 | cleanup: 160 | for(int prog = 0; prog < NUM_TEST_PROGS; ++prog) 161 | if(children[prog].buf) 162 | munmap(children[prog].buf, PERF_BUFFER_NUM_PAGES * getpagesize()); 163 | return ret; 164 | } 165 | -------------------------------------------------------------------------------- /postprocess.sh: -------------------------------------------------------------------------------- 1 | reuse() { 2 | local key="$1" 3 | local type="$2" 4 | local dest="$key" 5 | if [ $# -ge 3 ] 6 | then 7 | dest="$3" 8 | fi 9 | jaguar/jaguar set "$outfile" "$dest" "$type" "`jaguar/jaguar get "$infile" "$key"`" 10 | } 11 | 12 | bounds() { 13 | local series="$1" 14 | local index="$2" 15 | jaguar/jaguar get "$infile" "data.$series.samples[$elem]" >/dev/null 2>&1 16 | } 17 | 18 | sample() { 19 | local field="$1" 20 | local series="$2" 21 | local index="$3" 22 | jaguar/jaguar get "$infile" "data.$series.samples[$index].$field" 23 | } 24 | 25 | decode() { 26 | local metadata="$1" 27 | local incantation="`jaguar/jaguar get "$infile" meta.unpack 2>/dev/null`" 28 | if [ -z "$incantation" ] 29 | then 30 | incantation="base64 -d" 31 | fi 32 | jaguar/jaguar get "$infile" "meta.$metadata" | eval "$incantation" 33 | } 34 | 35 | if [ $# -ne 2 ] 36 | then 37 | echo "USAGE: $0 " 38 | exit 2 39 | fi 40 | infile="$1" 41 | outfile="$2" 42 | 43 | if [ ! -e "$infile" ] 44 | then 45 | echo "$infile: No such file or directory" >&2 46 | exit 3 47 | fi 48 | if [ -e "$outfile" ] 49 | then 50 | echo "$outfile: File exists and would be clobbered" >&2 51 | exit 4 52 | fi 53 | 54 | cp jaguar/template_postprocessed.json "$outfile" 55 | if jaguar/jaguar get "$infile" meta.origfile >/dev/null 2>&1 56 | then 57 | reuse meta.origfile string 58 | else 59 | jaguar/jaguar set "$outfile" meta.origfile "`md5sum "$infile" | cut -d" " -f1`" 60 | fi 61 | -------------------------------------------------------------------------------- /prep_system.c: -------------------------------------------------------------------------------- 1 | #include "prep_system.h" 2 | 3 | #include 4 | #include 5 | 6 | #include "log.h" 7 | #include "proc_manip.h" 8 | 9 | /* TODO: Fix prep_system first argument, clean_system argument */ 10 | static int pick_core (const struct pqos_cpuinfo *traits, int procs_go_where) { 11 | int cpu = procs_go_where % traits->num_cores; 12 | while (cpu < 0) cpu += traits-> num_cores; 13 | return cpu; 14 | } 15 | 16 | static bool rearrange_processes(bool multicore, int procs_go_where, 17 | const struct pqos_cpuinfo *traits) { 18 | cpu_set_t mask; 19 | CPU_ZERO(&mask); 20 | if(multicore) { 21 | for(unsigned cpu = 0; cpu < traits->num_cores; ++cpu) 22 | CPU_SET(cpu, &mask); 23 | } else { 24 | CPU_SET(pick_core(traits, procs_go_where), &mask); 25 | } 26 | int attempts; 27 | uint8_t failed; 28 | // TODO: Only hold cap_sys_nice here 29 | for(attempts = 1; attempts <= REARRANGE_RETRIES && 30 | proc_manip_rebalance_system(&failed, &mask); ++attempts) { 31 | log_msg(LOG_VERBOSE, "Relocation attempt #%d completed with code %#x\n", 32 | attempts, failed); 33 | } 34 | 35 | if(attempts > REARRANGE_RETRIES) { 36 | log_msg(LOG_ERROR, "Gave up before relocating all processes\n"); 37 | return false; 38 | } 39 | if(failed) { 40 | log_msg(LOG_ERROR, "Final relocation attempt failed with code %#x\n", failed); 41 | return false; 42 | } 43 | log_msg(LOG_INFO, "Successfully relocated all system processes in %d attempts\n", attempts); 44 | return true; 45 | } 46 | 47 | #define GIT_LOG_CMD "git log --oneline -1" 48 | #define GIT_STATUS_CMD "git status -uno" 49 | #define GIT_DIFF_CMD "git --no-pager diff HEAD" 50 | #define DELIM "===" 51 | // Purposely ignoring the usual style for pointers! 52 | // I don't know enough about PL to argue about it though! 53 | int prep_system(bool multicore, int procs_go_where) { 54 | printf("%s\n", GIT_LOG_CMD); 55 | system(GIT_LOG_CMD); 56 | printf("%s\n", GIT_STATUS_CMD); 57 | system(GIT_STATUS_CMD); 58 | printf("%s\n", GIT_DIFF_CMD); 59 | system(GIT_DIFF_CMD); 60 | printf("%s\n", DELIM); 61 | int ret = 0; 62 | struct pqos_config cfg = { 63 | .fd_log = log_get_dest(), 64 | .verbose = log_get_verbosity(), 65 | .topology = NULL, 66 | .free_in_use_rmid = 0, 67 | .cdp_cfg = PQOS_REQUIRE_CDP_OFF, 68 | }; 69 | int pqos_res = pqos_init(&cfg); 70 | if(pqos_res != PQOS_RETVAL_OK) { 71 | log_msg(LOG_FATAL, "Library init failed with code %d (HW support?)\n", pqos_res); 72 | ret = -1; 73 | } 74 | const struct pqos_cpuinfo *traits = NULL; 75 | const struct pqos_cap *feats = NULL; 76 | pqos_cap_get(&feats, &traits); 77 | if(!rearrange_processes(multicore, procs_go_where, traits)) { 78 | log_msg(LOG_FATAL, "Unable to relocate all system processes (permissions?)\n"); 79 | ret = -1; 80 | } 81 | return ret; 82 | } 83 | 84 | #undef GIT_LOG_CMD 85 | #undef GIT_STATUS_CMD 86 | #undef GIT_DIFF_CMD 87 | #undef DELIM 88 | 89 | // TODO add pqos_fini errors to return value 90 | int cleanup_system(bool unpin_procs) { 91 | int ret = 0; 92 | const struct pqos_cpuinfo *traits = NULL; 93 | const struct pqos_cap *feats = NULL; 94 | pqos_cap_get(&feats, &traits); 95 | if(!unpin_procs) { 96 | bool err = rearrange_processes(true, 0, traits); 97 | if(err == false) { 98 | log_msg(LOG_FATAL, "Cleanup failed\n"); 99 | ret = -1; 100 | } 101 | } 102 | pqos_fini(); 103 | return ret; 104 | } 105 | -------------------------------------------------------------------------------- /prep_system.h: -------------------------------------------------------------------------------- 1 | #ifndef PREP_SYSTEM_H_ 2 | #define PREP_SYSTEM_H_ 3 | 4 | #include 5 | 6 | // Number of times to iterate over all processes when attempting to move them between CPUs 7 | #define REARRANGE_RETRIES 3 8 | 9 | /* Returns 0 on success 10 | * Returns -1 on failure */ 11 | int prep_system(bool multicore, int procs_go_where); 12 | 13 | /* Returns 0 on success 14 | * Returns -1 on failure */ 15 | int cleanup_system(bool unpin_procs); 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /proc_manip.c: -------------------------------------------------------------------------------- 1 | #include "log.h" 2 | #include "proc_manip.h" 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | static inline bool trunc_newline(char *victim) { 12 | char *newline = strchr(victim, '\n'); 13 | if(newline) 14 | *newline = '\0'; 15 | return newline; 16 | } 17 | 18 | int proc_manip_rebalance_system(uint8_t *errret, const cpu_set_t *cores) { 19 | FILE *pids = popen("/bin/ps -eo pid=", "r"); 20 | char *line = NULL; 21 | int chrcnt; 22 | int updated = 0; 23 | size_t bufsiz = 0; 24 | uint8_t err = 0x0; 25 | 26 | while(errno = 0, (chrcnt = getline(&line, &bufsiz, pids)) >= 0) { 27 | if(!chrcnt) 28 | continue; 29 | 30 | char *endparse = NULL; 31 | 32 | errno = 0; 33 | pid_t id = strtol(line, &endparse, 10); 34 | 35 | int errnot = errno; 36 | bool stationary = endparse == line; 37 | 38 | trunc_newline(line); 39 | if(stationary) { 40 | log_msg(LOG_WARNING, "No characters parsed in PID '%s'\n", line); 41 | err |= PROC_MANIP_ERR_PARSE_PID; 42 | continue; 43 | } else if(errnot) { 44 | log_msg(LOG_WARNING, "%s when parsing PID '%s'\n", strerror(errnot), line); 45 | err |= PROC_MANIP_ERR_PARSE_PID; 46 | continue; 47 | } 48 | 49 | cpu_set_t curr_cores; 50 | if(sched_getaffinity(id, sizeof curr_cores, &curr_cores)) { 51 | log_msg(LOG_WARNING, "Unable to read current affinity of process %d\n", id); 52 | err |= PROC_MANIP_ERR_READ_MASK; 53 | } 54 | 55 | if(CPU_EQUAL(cores, &curr_cores)) { 56 | log_msg(LOG_VERBOSE, "Process %d has already been migrated\n", id); 57 | continue; 58 | } 59 | 60 | errno = 0; 61 | sched_setaffinity(id, sizeof *cores, cores); 62 | switch(errno) { 63 | case EFAULT: 64 | assert(false); 65 | err |= PROC_MANIP_ERR_UNK_FAULT; 66 | goto cleanup; 67 | case EINVAL: 68 | log_msg(LOG_WARNING, "Unable to migrate pid %d between cores\n", id); 69 | continue; 70 | case EPERM: 71 | log_msg(LOG_ERROR, "Access denied on sched_setaffinity() attempt\n"); 72 | err |= PROC_MANIP_ERR_INSF_PRIV; 73 | goto cleanup; 74 | case ESRCH: 75 | log_msg(LOG_VERBOSE, "Process %d finished before affinity change\n", id); 76 | continue; 77 | } 78 | log_msg(LOG_INFO, "Successfully migrated process %d between cores\n", id); 79 | ++updated; 80 | } 81 | assert(!errno); 82 | 83 | cleanup: 84 | free(line); 85 | pclose(pids); 86 | 87 | *errret = err; 88 | return updated; 89 | } 90 | -------------------------------------------------------------------------------- /proc_manip.h: -------------------------------------------------------------------------------- 1 | #ifndef CATBENCH_PROC_MANIP_H_ 2 | #define CATBENCH_PROC_MANIP_H_ 3 | 4 | #include 5 | #include 6 | 7 | #define PROC_MANIP_ERR_PARSE_PID 0x1 8 | #define PROC_MANIP_ERR_READ_MASK 0x2 9 | #define PROC_MANIP_ERR_INSF_PRIV 0x4 10 | #define PROC_MANIP_ERR_UNK_FAULT 0x8 11 | 12 | // Returns number of threads updated 13 | int proc_manip_rebalance_system(uint8_t *err, const cpu_set_t *cores); 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /rdtscp.h: -------------------------------------------------------------------------------- 1 | #ifndef RDTSCP_H_ 2 | #define RDTSCP_H_ 3 | 4 | #include 5 | 6 | static inline uint64_t rdtscp(void) { 7 | uint32_t cycles_low, cycles_high; 8 | __asm volatile( 9 | "RDTSCP\n\t" 10 | "mov %%edx, %0\n\t" 11 | "mov %%eax, %1\n\t" 12 | : "=r" (cycles_high), "=r" (cycles_low) 13 | : 14 | : "eax", "edx", "ecx" 15 | ); 16 | return ((uint64_t)cycles_high << 32 | cycles_low); 17 | } 18 | 19 | static inline uint64_t logtwo(const uint64_t x) { 20 | uint64_t y; 21 | __asm volatile( "\tbsr %1, %0\n" 22 | : "=r"(y) 23 | : "r" (x) 24 | ); 25 | return y; 26 | } 27 | #endif 28 | -------------------------------------------------------------------------------- /run-benchmark: -------------------------------------------------------------------------------- 1 | sudo ./lockserver-driver -o no-cat.dat 2 | sudo ./lockserver-driver -c -o with-cat.dat 3 | echo "With CAT" 4 | ./avg_data.pl with-cat.dat 5 | echo "Without CAT" 6 | ./avg_data.pl no-cat.dat 7 | -------------------------------------------------------------------------------- /run-extended-benchmark: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | logfilename="$CATBENCH_JAGFILE" 4 | if [ -z "$logfilename" ] 5 | then 6 | cat >&2 <<-tac 7 | $0: should be invoked via driver 8 | tac 9 | exit 1 10 | fi 11 | 12 | traverse=0 13 | traverse_pause=0 14 | iters=1 15 | if [ $# -eq 3 ] 16 | then 17 | echo "I hear you like choppier lockservers, bro. Here comes one!" 18 | traverse="$1" 19 | # TODO: Must be big enough that signals don't cancel out! 20 | traverse_pause="$2" 21 | iters="$3" 22 | fi 23 | 24 | jaguar/jaguar set "$logfilename" legend.samples.trash_alloc.description string "Allocation size of non-lockserver processes" 25 | jaguar/jaguar set "$logfilename" legend.samples.trash_alloc.unit string "KB" 26 | jaguar/jaguar set "$logfilename" legend.samples.access_time.description string "Time per memory access" 27 | jaguar/jaguar set "$logfilename" legend.samples.access_time.unit string "s" 28 | 29 | lockserver_mask="0x003" 30 | trash_mask="0xffc" 31 | 32 | cache_num_sets="$(cat /sys/devices/system/cpu/cpu0/cache/index3/number_of_sets)" 33 | cache_line_size="$(cat /sys/devices/system/cpu/cpu0/cache/index3/coherency_line_size)" 34 | cache_way_size="$((cache_num_sets * cache_line_size / 1024))" 35 | 36 | for lockserver_percent in 50 100 37 | do 38 | lock_kb=$((cache_way_size * lockserver_percent / 100)) 39 | jaguar/jaguar set "$logfilename" "data.l${lock_kb}k_baseline.description" string "Lockserver ${lock_kb}k, baseline" 40 | jaguar/jaguar set "$logfilename" "data.l${lock_kb}k_nocat.description" string "Lockserver ${lock_kb}k, no CAT" 41 | jaguar/jaguar set "$logfilename" "data.l${lock_kb}k_withcat.description" string "Lockserver ${lock_kb}k, CAT $lockserver_mask" 42 | header="integer,fraction\ntrash_alloc,access_time" 43 | baseline="$header" 44 | ctrlline="$header" 45 | exptline="$header" 46 | traverse_accs=$((traverse * cache_num_sets * lockserver_percent / 100)) 47 | sleep 10 48 | base="`sudo CATBENCH_JAGFILE="$CATBENCH_JAGFILE" ./lockserver-driver -n 0 -o base-line.dat -l "$lockserver_percent" -d "l${lock_kb}k_baseline" -s "$traverse_accs" -i "$iters" -w "$traverse_pause"`" 49 | for trash_percent in 50 100 200 400 800 1600 3200 6400 50 | do 51 | echo "Lockserver%: $lockserver_percent, Trash%: $trash_percent, Trash: $num_trash" 52 | trash_kb=$((cache_way_size * trash_percent / 100)) 53 | sleep 10 54 | control="`sudo CATBENCH_JAGFILE="$CATBENCH_JAGFILE" ./lockserver-driver -o no-cat.dat -l "$lockserver_percent" -d "l${lock_kb}k_nocat" -t "$trash_percent" -s "$traverse_accs" -i "$iters" -w "$traverse_pause"`" 55 | sleep 10 56 | experimental="`sudo CATBENCH_JAGFILE="$CATBENCH_JAGFILE" ./lockserver-driver -c -m "$lockserver_mask" -p "$trash_mask" -o with-cat.dat -l "$lockserver_percent" -d "l${lock_kb}k_withcat" -t "$trash_percent" -s "$traverse_accs" -i "$iters" -w "$traverse_pause"`" 57 | baseline="$baseline\n`printf "%d,%s\n" "$trash_kb" "$base"`" 58 | ctrlline="$ctrlline\n`printf "%d,%s\n" "$trash_kb" "$control"`" 59 | exptline="$exptline\n`printf "%d,%s\n" "$trash_kb" "$experimental"`" 60 | done 61 | echo "$baseline" | jaguar/jaguar set "$logfilename" "data.l${lock_kb}k_baseline.samples" array - 62 | echo "$ctrlline" | jaguar/jaguar set "$logfilename" "data.l${lock_kb}k_nocat.samples" array - 63 | echo "$exptline" | jaguar/jaguar set "$logfilename" "data.l${lock_kb}k_withcat.samples" array - 64 | done 65 | -------------------------------------------------------------------------------- /setpgrp.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(int argc, char **argv) { 5 | if(argc < 2) { 6 | printf("USAGE: %s [argument]...\n", argv[0]); 7 | return 1; 8 | } 9 | 10 | setpgid(0, 0); 11 | execvp(argv[1], argv + 1); 12 | return 1; 13 | } 14 | -------------------------------------------------------------------------------- /setup/after_reboot: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -ev 4 | sudo modprobe msr 5 | sudo sh -c 'echo 0 >/proc/sys/kernel/perf_event_paranoid' 6 | sudo sh -c 'echo 0 >/proc/sys/kernel/nmi_watchdog' 7 | sudo sh -c 'echo 16384 >/proc/sys/vm/nr_hugepages' 8 | sudo sh -c 'for gov in /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor; do echo performance >"$gov"; done' 9 | echo "1" | sudo tee /sys/devices/system/cpu/cpu32/online 10 | 11 | sudo sh -c 'echo never >/sys/kernel/mm/transparent_hugepage/enabled' 12 | sudo sh -c 'echo never >/sys/kernel/mm/transparent_hugepage/defrag' 13 | 14 | [ -e /sys/fs/cgroup/intel_rdt ] || sudo mount -t resctrl none /sys/fs/resctrl 15 | 16 | #cd ~/hangups/examples 17 | #nohup ./dogbert & 18 | -------------------------------------------------------------------------------- /setup/after_reboot_module: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | readonly DPDK_IFACE="04:00.0" # enp130s0f0 4 | readonly KERN_IFACE="enp4s0f1" # 82:00.1 5 | readonly IP_ADDR="192.168.3.1/24" 6 | 7 | set -e 8 | ifacebind="dpdk/tools/dpdk_nic_bind.py" 9 | if [ ! -e "$ifacebind" ] 10 | then 11 | ifacebind="dpdk/tools/dpdk-devbind.py" 12 | fi 13 | 14 | printf '%s\n%s\n\n%s\n' 20 16384 34 | dpdk/tools/setup.sh || \ 15 | printf '%s\n' 20 16384 0 "" 33 | dpdk/tools/dpdk-setup.sh 16 | lsmod | grep uio || sudo modprobe uio 17 | lsmod | grep igb_uio || sudo insmod dpdk/build/kmod/igb_uio.ko 18 | sudo "$ifacebind" -u "$DPDK_IFACE" 19 | sudo "$ifacebind" -b igb_uio "$DPDK_IFACE" 20 | sudo ip addr flush "$KERN_IFACE" 21 | sudo ip addr add dev "$KERN_IFACE" "$IP_ADDR" 22 | sudo ip link set dev "$KERN_IFACE" up 23 | -------------------------------------------------------------------------------- /setup/after_reboot_router: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | ifacebind="dpdk/tools/dpdk_nic_bind.py" 5 | if [ ! -e "$ifacebind" ] 6 | then 7 | ifacebind="dpdk/tools/dpdk-devbind.py" 8 | fi 9 | 10 | printf '%s\n%s\n\n%s\n' 20 10000 34 | dpdk/tools/setup.sh || \ 11 | printf '%s\n' 20 10000 0 "" 33 | dpdk/tools/dpdk-setup.sh 12 | sudo modprobe uio 13 | lsmod | grep igb_uio || sudo insmod dpdk/build/kmod/igb_uio.ko 14 | sudo ip addr flush dev p1p1 || true 15 | sudo "$ifacebind" -u 02:00.0 16 | sudo "$ifacebind" -b igb_uio 02:00.0 17 | sudo ip addr flush dev p1p2 || true 18 | sudo ip addr add dev p1p2 192.168.3.2/24 19 | sudo ip link set dev p1p2 up 20 | -------------------------------------------------------------------------------- /setup/package: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ $# -ne 1 ] 4 | then 5 | echo "USAGE: $0 " 6 | exit 1 7 | fi 8 | 9 | mkdir -p \ 10 | /usr/local/etc/bash_completion.d/perf \ 11 | /usr/local/lib64/traceevent/plugins \ 12 | /usr/local/libexec/perf-core/scripts/perl/Perf-Trace-Util/lib/Perf/Trace \ 13 | /usr/local/libexec/perf-core/scripts/python/Perf-Trace-Util/lib/Perf/Trace \ 14 | /usr/local/libexec/perf-core/tests \ 15 | /usr/local/share/man \ 16 | 17 | checkinstall --pkgname="linux-perf-$1" --install=no --backup=no make install install-doc prefix=/usr/local 18 | -------------------------------------------------------------------------------- /slowbro.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "bench_commands.h" 7 | #include "log.h" 8 | #include "prep_system.h" 9 | 10 | #define ARG_IDX_TO_REPL_WITH_LOG_FLAG 7 11 | static test_prog_t progs[] = { 12 | { 13 | .cmdline = {"clients/square_evictions", "-e100", "-c0", "-n1", "-p10", "-hr"}, 14 | .target_cpu = 0, 15 | }, { 16 | .cmdline = {"clients/square_evictions", "-e100", "-c0", "-n1", "-p4", "-hr", "-j480", NULL}, 17 | .target_cpu = 1, 18 | }, { 19 | .cmdline = {"clients/square_evictions", "-e100", "-c0", "-n1", "-p4", "-hr", "-j480", NULL}, 20 | .target_cpu = 2, 21 | }, 22 | }; 23 | static const size_t NUM_PROGS = sizeof progs / sizeof *progs; 24 | 25 | #define COS_MAPPING_SWITCH_WHICH_CORE 0 26 | #define COS_MAPPING_SWITCH_TO_COS 2 27 | static const struct pqos_l3ca COS_MASK_REPLACEMENT = { 28 | .class_id = 3, 29 | .ways_mask = 0x2, 30 | }; 31 | 32 | static const unsigned COS_MAPPINGS[] = { 33 | [0] = 3, 34 | [1] = 1, 35 | [2] = 2, 36 | }; 37 | static const size_t NUM_COS_MAPPINGS = sizeof COS_MAPPINGS / sizeof *COS_MAPPINGS; 38 | 39 | static const struct pqos_l3ca COS_MASKS[] = { 40 | { 41 | .class_id = 3, 42 | .ways_mask = 0x1, 43 | }, { 44 | .class_id = 1, 45 | .ways_mask = 0x1, 46 | }, { 47 | .class_id = 2, 48 | .ways_mask = 0x2, 49 | }, { 50 | .class_id = 0, 51 | .ways_mask = 0xffc, 52 | } 53 | }; 54 | static const size_t NUM_COS_MASKS = sizeof COS_MASKS / sizeof *COS_MASKS; 55 | 56 | static inline clock_t realclock(void) { 57 | struct timespec ns; 58 | clock_gettime(CLOCK_REALTIME, &ns); 59 | return ns.tv_sec * 1000000 + ns.tv_nsec / 1000; 60 | } 61 | 62 | int main(int argc, char **argv) { 63 | bool slowpoke = true; 64 | 65 | if(argc < 3) { 66 | printf("USAGE: %s []\n", argv[0]); 67 | return 1; 68 | } 69 | if(argc >= 4) { 70 | puts("OPERATING IN SLOWPOKE MODE... VERY MASK, SUCH BITWISE, SO DIFFERENT"); 71 | slowpoke = true; 72 | } 73 | 74 | char logswitch1[2 + strlen(argv[1]) + 1]; 75 | sprintf(logswitch1, "-l%s", argv[1]); 76 | progs[1].cmdline[ARG_IDX_TO_REPL_WITH_LOG_FLAG] = logswitch1; 77 | 78 | char logswitch2[2 + strlen(argv[2]) + 1]; 79 | sprintf(logswitch2, "-l%s", argv[2]); 80 | progs[2].cmdline[ARG_IDX_TO_REPL_WITH_LOG_FLAG] = logswitch2; 81 | 82 | if(prep_system(false, -1) < 0) { 83 | log_msg(LOG_FATAL, "Performing initial setup\n"); 84 | return 1; 85 | } 86 | if(pqos_l3ca_set(0, NUM_COS_MASKS, COS_MASKS) != PQOS_RETVAL_OK) { 87 | log_msg(LOG_FATAL, "Failed to set CoS masks\n"); 88 | return 1; 89 | } 90 | for(unsigned core = 0; core < NUM_COS_MAPPINGS; ++core) { 91 | if(pqos_l3ca_assoc_set(core, COS_MAPPINGS[core]) != PQOS_RETVAL_OK) { 92 | log_msg(LOG_FATAL, "Failed to associate CoS with core\n"); 93 | return 1; 94 | } 95 | } 96 | 97 | run_benchmarks(progs, NUM_PROGS); 98 | 99 | usleep(4500); 100 | printf("About to change CoS: %ld\n", realclock()); 101 | if(!slowpoke) { 102 | if(pqos_l3ca_assoc_set(COS_MAPPING_SWITCH_WHICH_CORE, COS_MAPPING_SWITCH_TO_COS) != 103 | PQOS_RETVAL_OK) { 104 | log_msg(LOG_FATAL, "Failed to reassociate mobile test program\n"); 105 | return 1; 106 | } 107 | } else { 108 | if(pqos_l3ca_set(0, 1, &COS_MASK_REPLACEMENT) != PQOS_RETVAL_OK) { 109 | log_msg(LOG_FATAL, "Failed to change mask of mobile test program\n"); 110 | return 1; 111 | } 112 | } 113 | printf("Just changed CoS: %ld\n", realclock()); 114 | 115 | wait_benchmarks(); 116 | cleanup_system(true); 117 | 118 | return 0; 119 | } 120 | -------------------------------------------------------------------------------- /square_evictions-vary-allocation: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ -z "$CATBENCH_JAGFILE" ] 4 | then 5 | echo "$0: should be invoked via driver" >&2 6 | exit 1 7 | fi 8 | 9 | if [ $# -ne 1 ] 10 | then 11 | echo "USAGE: $0 0x" 12 | exit 1 13 | fi 14 | mask="$1" 15 | 16 | jaguar/jaguar set "$CATBENCH_JAGFILE" legend.samples.alloc.description string "Allocation size" 17 | jaguar/jaguar set "$CATBENCH_JAGFILE" legend.samples.alloc.unit string "KB" 18 | jaguar/jaguar set "$CATBENCH_JAGFILE" legend.samples.time.description string "Time per access" 19 | jaguar/jaguar set "$CATBENCH_JAGFILE" legend.samples.time.unit string "s" 20 | 21 | jaguar/jaguar set "$CATBENCH_JAGFILE" data.vary-allocation.description string "Allocation size vs. access rate" 22 | 23 | . ./factors.sh 24 | 25 | cache_way_size="$((`cat /sys/devices/system/cpu/cpu0/cache/index3/number_of_sets /sys/devices/system/cpu/cpu0/cache/index3/coherency_line_size | paste -sd* | bc` / 1024))" 26 | 27 | entries="integer,fraction\nalloc,time" 28 | for alloc in 5 10 15 20 25 30 40 50 60 70 80 90 100 200 400 800 1600 29 | do 30 | echo "alloc: $alloc" 31 | kb=$((cache_way_size * alloc / 100)) 32 | eval myfactors="\$prime_factors_$alloc" 33 | entries="$entries\n$kb,`sudo CATBENCH_JAGFILE="$CATBENCH_JAGFILE" ./lockserver-driver -o /dev/null -d vary-allocation -n 0 -l "$alloc" -c -m "$mask" -p 0xfff -a "-wq $myfactors" 2>&1 >/dev/null | grep "accesses/s" | cut -d: -f2 | cut -d" " -f2 | tr "\n" " " | sed 's:\([^ ]\+\) \([^ ]\+\):1.0 / ( ( \1 + \2 ) / 2.0 )\n:' | bc -l`" 34 | done 35 | 36 | echo "$entries" | jaguar/jaguar set "$CATBENCH_JAGFILE" data.vary-allocation.samples array - 37 | -------------------------------------------------------------------------------- /strip: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ $# -ne 1 -o ! -e "$1" ] 4 | then 5 | cat <<-tac 6 | USAGE: $0 7 | 8 | must already exist. 9 | tac 10 | exit 1 11 | fi 12 | 13 | grep -vFe'"perf_data": "' -e'"log"' -e'"patch"' -e'"server_binary"' "$1" | \ 14 | paste -sd"\r" | sed 's/,\r\([[:space:]]*[]}]\)/\n\1/g;s/\r/\n/g' 15 | -------------------------------------------------------------------------------- /syscallers.h: -------------------------------------------------------------------------------- 1 | #ifndef PERF_H_ 2 | #define PERF_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | static inline int perf_event_open(const struct perf_event_attr *attr, pid_t pid, int cpu, 9 | int group_fd, unsigned long flags) { 10 | return syscall(__NR_perf_event_open, attr, pid, cpu, group_fd, flags); 11 | } 12 | 13 | static inline int exec_v(const char *path, const char *const argv[]) { 14 | #pragma GCC diagnostic ignored "-Wcast-qual" 15 | return execv(path, (char *const *) argv); 16 | #pragma GCC diagnostic pop 17 | } 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /tensorflow_blt: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -eu 4 | 5 | trap exit TERM INT QUIT 6 | trap "killall tensorflow_mnist_short 2>/dev/null || true" EXIT 7 | 8 | show_usage="0" 9 | if [ ! -x setpgrp ] 10 | then 11 | echo "ERROR: setpgrp binary not found; did you build it?" >&2 12 | exit 3 13 | fi 14 | if [ -z "${CATBENCH_JAGFILE-}" ] 15 | then 16 | cat >&2 <<-tac 17 | $0: should be invoked via driver 18 | 19 | tac 20 | show_usage="2" 21 | fi 22 | if [ "$show_usage" -ne "0" -o $# -gt 2 ] 23 | then 24 | cat <<-tac 25 | USAGE: $0 [min core count] [max core count] 26 | 27 | [min core count] defaults to one. 28 | [max core count] defaults to one fewer than the number of physical cores on the first CPU socket. 29 | If only one of these is specified, it is assumed to be the max. 30 | tac 31 | exit "$show_usage" 32 | fi 33 | 34 | logfilename="$CATBENCH_JAGFILE" 35 | num_trash="`lscpu | grep Core | tr -s " " | rev | cut -d" " -f1 | rev`" 36 | step_trash="`grep -m2 "physical id" /proc/cpuinfo | uniq | wc -l`" 37 | start_trash="1" 38 | if [ -n "${2-}" ] 39 | then 40 | start_trash="$1" 41 | shift 42 | fi 43 | if [ -n "${1-}" ] 44 | then 45 | num_trash="$1" 46 | fi 47 | constrain="$(((1 << (step_trash * num_trash)) - 1))" 48 | printf "%s\n" "Trying core counts between $start_trash and $num_trash..." 49 | 50 | jaguar/jaguar set "$logfilename" legend.samples.num_trash.description string "Cores running contender" 51 | jaguar/jaguar set "$logfilename" legend.samples.num_trash.unit string "" 52 | 53 | jaguar/jaguar set "$logfilename" legend.samples.contender_tput.description string "Contender throughput" 54 | jaguar/jaguar set "$logfilename" legend.samples.contender_tput.unit string "epochs/s" 55 | 56 | jaguar/jaguar set "$logfilename" data.basecontender.description string "ContenderOnly" 57 | 58 | data="integer,fraction\nnum_trash,contender_tput" 59 | mask="0x0" 60 | for num in `seq "$num_trash"` 61 | do 62 | mask="`printf %#x "$(((mask + ((1 << (step_trash * num)) | num == num_trash)) & constrain))"`" 63 | if [ "$num" -lt "$start_trash" ] 64 | then 65 | continue 66 | fi 67 | 68 | printf "\n%s\n" "$num cores (mask $mask):" 69 | time="`time -p taskset "$mask" ./setpgrp ./tensorflow_mnist_short 2>&1 | tee /dev/tty | sed -n 's/.*real \(.*\).*/\1/p'`" 70 | tput="`printf "%s\n" "1 / $time" | bc -l`" 71 | printf "%s\n" "time $time s (tput $tput epochs/s)" 72 | data="$data\n$num,$tput" 73 | done 74 | 75 | printf "$data" | jaguar/jaguar set "$logfilename" data.basecontender.samples array - 76 | -------------------------------------------------------------------------------- /tensorflow_mnist_long: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | rm -rf /tmp/mnist_model/* 3 | # About 10 minutes 4 | python mnist.py --steps 8300 5 | -------------------------------------------------------------------------------- /tensorflow_mnist_short: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | rm -rf /tmp/mnist_model/* 3 | # Approx 2:00 4 | python mnist.py --steps 1600 5 | -------------------------------------------------------------------------------- /test-pmd/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | /testpmd 3 | /testpmd.map 4 | 5 | _* 6 | *.cmd 7 | *.d 8 | -------------------------------------------------------------------------------- /test-pmd/Makefile: -------------------------------------------------------------------------------- 1 | # BSD LICENSE 2 | # 3 | # Copyright(c) 2010-2015 Intel Corporation. All rights reserved. 4 | # All rights reserved. 5 | # 6 | # Redistribution and use in source and binary forms, with or without 7 | # modification, are permitted provided that the following conditions 8 | # are met: 9 | # 10 | # * Redistributions of source code must retain the above copyright 11 | # notice, this list of conditions and the following disclaimer. 12 | # * Redistributions in binary form must reproduce the above copyright 13 | # notice, this list of conditions and the following disclaimer in 14 | # the documentation and/or other materials provided with the 15 | # distribution. 16 | # * Neither the name of Intel Corporation nor the names of its 17 | # contributors may be used to endorse or promote products derived 18 | # from this software without specific prior written permission. 19 | # 20 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 | # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | 32 | RTE_SDK := ../external/dpdk 33 | RTE_TARGET := build 34 | 35 | include $(RTE_SDK)/mk/rte.vars.mk 36 | 37 | ifeq ($(CONFIG_RTE_TEST_PMD),y) 38 | 39 | # 40 | # library name 41 | # 42 | APP = testpmd 43 | 44 | CFLAGS += -O3 45 | CFLAGS += $(WERROR_FLAGS) 46 | 47 | # 48 | # all source are stored in SRCS-y 49 | # 50 | SRCS-y := testpmd.c 51 | SRCS-y += parameters.c 52 | SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline.c 53 | SRCS-y += config.c 54 | SRCS-y += iofwd.c 55 | SRCS-y += macfwd.c 56 | SRCS-y += macfwd-retry.c 57 | SRCS-y += macswap.c 58 | SRCS-y += flowgen.c 59 | SRCS-y += rxonly.c 60 | SRCS-y += txonly.c 61 | SRCS-y += csumonly.c 62 | SRCS-y += icmpecho.c 63 | SRCS-$(CONFIG_RTE_LIBRTE_IEEE1588) += ieee1588fwd.c 64 | SRCS-y += mempool_anon.c 65 | 66 | ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y) 67 | CFLAGS_mempool_anon.o := -D_GNU_SOURCE 68 | endif 69 | CFLAGS_cmdline.o := -D_GNU_SOURCE 70 | 71 | # this application needs libraries first 72 | DEPDIRS-y += lib drivers 73 | 74 | include $(RTE_SDK)/mk/rte.app.mk 75 | 76 | endif 77 | -------------------------------------------------------------------------------- /test-pmd/iofwd.c: -------------------------------------------------------------------------------- 1 | /*- 2 | * BSD LICENSE 3 | * 4 | * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 11 | * * Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * * Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in 15 | * the documentation and/or other materials provided with the 16 | * distribution. 17 | * * Neither the name of Intel Corporation nor the names of its 18 | * contributors may be used to endorse or promote products derived 19 | * from this software without specific prior written permission. 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | 42 | #include 43 | #include 44 | 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | #include 53 | #include 54 | #include 55 | #include 56 | #include 57 | #include 58 | #include 59 | #include 60 | #include 61 | #include 62 | #include 63 | #include 64 | #include 65 | #include 66 | #include 67 | #include 68 | 69 | #include "testpmd.h" 70 | 71 | /* 72 | * Forwarding of packets in I/O mode. 73 | * Forward packets "as-is". 74 | * This is the fastest possible forwarding operation, as it does not access 75 | * to packets data. 76 | */ 77 | static void 78 | pkt_burst_io_forward(struct fwd_stream *fs) 79 | { 80 | struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; 81 | uint16_t nb_rx; 82 | uint16_t nb_tx; 83 | #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES 84 | uint64_t start_tsc; 85 | uint64_t end_tsc; 86 | uint64_t core_cycles; 87 | #endif 88 | 89 | #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES 90 | start_tsc = rte_rdtsc(); 91 | #endif 92 | 93 | /* 94 | * Receive a burst of packets and forward them. 95 | */ 96 | nb_rx = rte_eth_rx_burst(fs->rx_port, fs->rx_queue, pkts_burst, 97 | nb_pkt_per_burst); 98 | if (unlikely(nb_rx == 0)) 99 | return; 100 | 101 | #ifdef RTE_TEST_PMD_RECORD_BURST_STATS 102 | fs->rx_burst_stats.pkt_burst_spread[nb_rx]++; 103 | #endif 104 | fs->rx_packets += nb_rx; 105 | nb_tx = rte_eth_tx_burst(fs->tx_port, fs->tx_queue, pkts_burst, nb_rx); 106 | fs->tx_packets += nb_tx; 107 | #ifdef RTE_TEST_PMD_RECORD_BURST_STATS 108 | fs->tx_burst_stats.pkt_burst_spread[nb_tx]++; 109 | #endif 110 | if (unlikely(nb_tx < nb_rx)) { 111 | fs->fwd_dropped += (nb_rx - nb_tx); 112 | do { 113 | rte_pktmbuf_free(pkts_burst[nb_tx]); 114 | } while (++nb_tx < nb_rx); 115 | } 116 | #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES 117 | end_tsc = rte_rdtsc(); 118 | core_cycles = (end_tsc - start_tsc); 119 | fs->core_cycles = (uint64_t) (fs->core_cycles + core_cycles); 120 | #endif 121 | } 122 | 123 | struct fwd_engine io_fwd_engine = { 124 | .fwd_mode_name = "io", 125 | .port_fwd_begin = NULL, 126 | .port_fwd_end = NULL, 127 | .packet_fwd = pkt_burst_io_forward, 128 | }; 129 | -------------------------------------------------------------------------------- /test-pmd/macfwd-retry.c: -------------------------------------------------------------------------------- 1 | /*- 2 | * BSD LICENSE 3 | * 4 | * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 11 | * * Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * * Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in 15 | * the documentation and/or other materials provided with the 16 | * distribution. 17 | * * Neither the name of Intel Corporation nor the names of its 18 | * contributors may be used to endorse or promote products derived 19 | * from this software without specific prior written permission. 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | 42 | #include 43 | #include 44 | 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | #include 53 | #include 54 | #include 55 | #include 56 | #include 57 | #include 58 | #include 59 | #include 60 | #include 61 | #include 62 | #include 63 | #include 64 | #include 65 | #include 66 | #include 67 | #include 68 | #include 69 | 70 | #include "testpmd.h" 71 | 72 | #define BURST_TX_WAIT_US 10 73 | #define BURST_TX_RETRIES 5 74 | 75 | /* 76 | * Global variables that control number of retires and 77 | * timeout (in us) between retires. 78 | */ 79 | uint32_t burst_tx_delay_time = BURST_TX_WAIT_US; 80 | uint32_t burst_tx_retry_num = BURST_TX_RETRIES; 81 | 82 | /* 83 | * Forwarding of packets in MAC mode with a wait and retry on TX to reduce packet loss. 84 | * Change the source and the destination Ethernet addressed of packets 85 | * before forwarding them. 86 | */ 87 | static void 88 | pkt_burst_mac_retry_forward(struct fwd_stream *fs) 89 | { 90 | struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; 91 | struct rte_mbuf *mb; 92 | struct ether_hdr *eth_hdr; 93 | uint32_t retry; 94 | uint16_t nb_rx; 95 | uint16_t nb_tx; 96 | uint16_t i; 97 | #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES 98 | uint64_t start_tsc; 99 | uint64_t end_tsc; 100 | uint64_t core_cycles; 101 | #endif 102 | 103 | #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES 104 | start_tsc = rte_rdtsc(); 105 | #endif 106 | 107 | /* 108 | * Receive a burst of packets and forward them. 109 | */ 110 | nb_rx = rte_eth_rx_burst(fs->rx_port, fs->rx_queue, pkts_burst, 111 | nb_pkt_per_burst); 112 | if (unlikely(nb_rx == 0)) 113 | return; 114 | 115 | #ifdef RTE_TEST_PMD_RECORD_BURST_STATS 116 | fs->rx_burst_stats.pkt_burst_spread[nb_rx]++; 117 | #endif 118 | fs->rx_packets += nb_rx; 119 | for (i = 0; i < nb_rx; i++) { 120 | mb = pkts_burst[i]; 121 | eth_hdr = rte_pktmbuf_mtod(mb, struct ether_hdr *); 122 | ether_addr_copy(&peer_eth_addrs[fs->peer_addr], 123 | ð_hdr->d_addr); 124 | ether_addr_copy(&ports[fs->tx_port].eth_addr, 125 | ð_hdr->s_addr); 126 | } 127 | nb_tx = rte_eth_tx_burst(fs->tx_port, fs->tx_queue, pkts_burst, nb_rx); 128 | 129 | /* 130 | * If not all packets have been TX'd then wait and retry. 131 | */ 132 | if (unlikely(nb_tx < nb_rx)) { 133 | for (retry = 0; retry < burst_tx_retry_num; retry++) { 134 | rte_delay_us(burst_tx_delay_time); 135 | nb_tx += rte_eth_tx_burst(fs->tx_port, fs->tx_queue, 136 | &pkts_burst[nb_tx], nb_rx - nb_tx); 137 | if (nb_tx == nb_rx) 138 | break; 139 | } 140 | } 141 | 142 | fs->tx_packets += nb_tx; 143 | #ifdef RTE_TEST_PMD_RECORD_BURST_STATS 144 | fs->tx_burst_stats.pkt_burst_spread[nb_tx]++; 145 | #endif 146 | if (unlikely(nb_tx < nb_rx)) { 147 | fs->fwd_dropped += (nb_rx - nb_tx); 148 | do { 149 | rte_pktmbuf_free(pkts_burst[nb_tx]); 150 | } while (++nb_tx < nb_rx); 151 | } 152 | #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES 153 | end_tsc = rte_rdtsc(); 154 | core_cycles = (end_tsc - start_tsc); 155 | fs->core_cycles = (uint64_t) (fs->core_cycles + core_cycles); 156 | #endif 157 | } 158 | 159 | struct fwd_engine mac_retry_fwd_engine = { 160 | .fwd_mode_name = "mac_retry", 161 | .port_fwd_begin = NULL, 162 | .port_fwd_end = NULL, 163 | .packet_fwd = pkt_burst_mac_retry_forward, 164 | }; 165 | -------------------------------------------------------------------------------- /test-pmd/macfwd.c: -------------------------------------------------------------------------------- 1 | /*- 2 | * BSD LICENSE 3 | * 4 | * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 11 | * * Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * * Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in 15 | * the documentation and/or other materials provided with the 16 | * distribution. 17 | * * Neither the name of Intel Corporation nor the names of its 18 | * contributors may be used to endorse or promote products derived 19 | * from this software without specific prior written permission. 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | 42 | #include 43 | #include 44 | 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | #include 53 | #include 54 | #include 55 | #include 56 | #include 57 | #include 58 | #include 59 | #include 60 | #include 61 | #include 62 | #include 63 | #include 64 | #include 65 | #include 66 | #include 67 | #include 68 | #include 69 | 70 | #include "testpmd.h" 71 | 72 | /* 73 | * Forwarding of packets in MAC mode. 74 | * Change the source and the destination Ethernet addressed of packets 75 | * before forwarding them. 76 | */ 77 | static void 78 | pkt_burst_mac_forward(struct fwd_stream *fs) 79 | { 80 | struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; 81 | struct rte_port *txp; 82 | struct rte_mbuf *mb; 83 | struct ether_hdr *eth_hdr; 84 | uint16_t nb_rx; 85 | uint16_t nb_tx; 86 | uint16_t i; 87 | uint64_t ol_flags = 0; 88 | #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES 89 | uint64_t start_tsc; 90 | uint64_t end_tsc; 91 | uint64_t core_cycles; 92 | #endif 93 | 94 | #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES 95 | start_tsc = rte_rdtsc(); 96 | #endif 97 | 98 | /* 99 | * Receive a burst of packets and forward them. 100 | */ 101 | nb_rx = rte_eth_rx_burst(fs->rx_port, fs->rx_queue, pkts_burst, 102 | nb_pkt_per_burst); 103 | if (unlikely(nb_rx == 0)) 104 | return; 105 | 106 | #ifdef RTE_TEST_PMD_RECORD_BURST_STATS 107 | fs->rx_burst_stats.pkt_burst_spread[nb_rx]++; 108 | #endif 109 | fs->rx_packets += nb_rx; 110 | txp = &ports[fs->tx_port]; 111 | if (txp->tx_ol_flags & TESTPMD_TX_OFFLOAD_INSERT_VLAN) 112 | ol_flags = PKT_TX_VLAN_PKT; 113 | if (txp->tx_ol_flags & TESTPMD_TX_OFFLOAD_INSERT_QINQ) 114 | ol_flags |= PKT_TX_QINQ_PKT; 115 | for (i = 0; i < nb_rx; i++) { 116 | mb = pkts_burst[i]; 117 | eth_hdr = rte_pktmbuf_mtod(mb, struct ether_hdr *); 118 | ether_addr_copy(&peer_eth_addrs[fs->peer_addr], 119 | ð_hdr->d_addr); 120 | ether_addr_copy(&ports[fs->tx_port].eth_addr, 121 | ð_hdr->s_addr); 122 | mb->ol_flags = ol_flags; 123 | mb->l2_len = sizeof(struct ether_hdr); 124 | mb->l3_len = sizeof(struct ipv4_hdr); 125 | mb->vlan_tci = txp->tx_vlan_id; 126 | mb->vlan_tci_outer = txp->tx_vlan_id_outer; 127 | } 128 | nb_tx = rte_eth_tx_burst(fs->tx_port, fs->tx_queue, pkts_burst, nb_rx); 129 | fs->tx_packets += nb_tx; 130 | #ifdef RTE_TEST_PMD_RECORD_BURST_STATS 131 | fs->tx_burst_stats.pkt_burst_spread[nb_tx]++; 132 | #endif 133 | if (unlikely(nb_tx < nb_rx)) { 134 | fs->fwd_dropped += (nb_rx - nb_tx); 135 | do { 136 | rte_pktmbuf_free(pkts_burst[nb_tx]); 137 | } while (++nb_tx < nb_rx); 138 | } 139 | #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES 140 | end_tsc = rte_rdtsc(); 141 | core_cycles = (end_tsc - start_tsc); 142 | fs->core_cycles = (uint64_t) (fs->core_cycles + core_cycles); 143 | #endif 144 | } 145 | 146 | struct fwd_engine mac_fwd_engine = { 147 | .fwd_mode_name = "mac", 148 | .port_fwd_begin = NULL, 149 | .port_fwd_end = NULL, 150 | .packet_fwd = pkt_burst_mac_forward, 151 | }; 152 | -------------------------------------------------------------------------------- /test-pmd/macswap.c: -------------------------------------------------------------------------------- 1 | /*- 2 | * BSD LICENSE 3 | * 4 | * Copyright(c) 2014 Tilera Corporation. All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in 14 | * the documentation and/or other materials provided with the 15 | * distribution. 16 | * * Neither the name of Tilera Corporation nor the names of its 17 | * contributors may be used to endorse or promote products derived 18 | * from this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | * 32 | */ 33 | 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | 42 | #include 43 | #include 44 | 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | #include 53 | #include 54 | #include 55 | #include 56 | #include 57 | #include 58 | #include 59 | #include 60 | #include 61 | #include 62 | #include 63 | #include 64 | #include 65 | #include 66 | #include 67 | #include 68 | #include 69 | 70 | #include "testpmd.h" 71 | 72 | /* 73 | * MAC swap forwarding mode: Swap the source and the destination Ethernet 74 | * addresses of packets before forwarding them. 75 | */ 76 | static void 77 | pkt_burst_mac_swap(struct fwd_stream *fs) 78 | { 79 | struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; 80 | struct rte_port *txp; 81 | struct rte_mbuf *mb; 82 | struct ether_hdr *eth_hdr; 83 | struct ether_addr addr; 84 | uint16_t nb_rx; 85 | uint16_t nb_tx; 86 | uint16_t i; 87 | uint64_t ol_flags = 0; 88 | #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES 89 | uint64_t start_tsc; 90 | uint64_t end_tsc; 91 | uint64_t core_cycles; 92 | #endif 93 | 94 | #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES 95 | start_tsc = rte_rdtsc(); 96 | #endif 97 | 98 | /* 99 | * Receive a burst of packets and forward them. 100 | */ 101 | nb_rx = rte_eth_rx_burst(fs->rx_port, fs->rx_queue, pkts_burst, 102 | nb_pkt_per_burst); 103 | if (unlikely(nb_rx == 0)) 104 | return; 105 | 106 | #ifdef RTE_TEST_PMD_RECORD_BURST_STATS 107 | fs->rx_burst_stats.pkt_burst_spread[nb_rx]++; 108 | #endif 109 | fs->rx_packets += nb_rx; 110 | txp = &ports[fs->tx_port]; 111 | if (txp->tx_ol_flags & TESTPMD_TX_OFFLOAD_INSERT_VLAN) 112 | ol_flags = PKT_TX_VLAN_PKT; 113 | if (txp->tx_ol_flags & TESTPMD_TX_OFFLOAD_INSERT_QINQ) 114 | ol_flags |= PKT_TX_QINQ_PKT; 115 | for (i = 0; i < nb_rx; i++) { 116 | mb = pkts_burst[i]; 117 | eth_hdr = rte_pktmbuf_mtod(mb, struct ether_hdr *); 118 | 119 | /* Swap dest and src mac addresses. */ 120 | ether_addr_copy(ð_hdr->d_addr, &addr); 121 | ether_addr_copy(ð_hdr->s_addr, ð_hdr->d_addr); 122 | ether_addr_copy(&addr, ð_hdr->s_addr); 123 | 124 | mb->ol_flags = ol_flags; 125 | mb->l2_len = sizeof(struct ether_hdr); 126 | mb->l3_len = sizeof(struct ipv4_hdr); 127 | mb->vlan_tci = txp->tx_vlan_id; 128 | mb->vlan_tci_outer = txp->tx_vlan_id_outer; 129 | } 130 | nb_tx = rte_eth_tx_burst(fs->tx_port, fs->tx_queue, pkts_burst, nb_rx); 131 | fs->tx_packets += nb_tx; 132 | #ifdef RTE_TEST_PMD_RECORD_BURST_STATS 133 | fs->tx_burst_stats.pkt_burst_spread[nb_tx]++; 134 | #endif 135 | if (unlikely(nb_tx < nb_rx)) { 136 | fs->fwd_dropped += (nb_rx - nb_tx); 137 | do { 138 | rte_pktmbuf_free(pkts_burst[nb_tx]); 139 | } while (++nb_tx < nb_rx); 140 | } 141 | #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES 142 | end_tsc = rte_rdtsc(); 143 | core_cycles = (end_tsc - start_tsc); 144 | fs->core_cycles = (uint64_t) (fs->core_cycles + core_cycles); 145 | #endif 146 | } 147 | 148 | struct fwd_engine mac_swap_engine = { 149 | .fwd_mode_name = "macswap", 150 | .port_fwd_begin = NULL, 151 | .port_fwd_end = NULL, 152 | .packet_fwd = pkt_burst_mac_swap, 153 | }; 154 | -------------------------------------------------------------------------------- /test-pmd/mempool_anon.c: -------------------------------------------------------------------------------- 1 | /*- 2 | * BSD LICENSE 3 | * 4 | * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 11 | * * Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * * Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in 15 | * the documentation and/or other materials provided with the 16 | * distribution. 17 | * * Neither the name of Intel Corporation nor the names of its 18 | * contributors may be used to endorse or promote products derived 19 | * from this software without specific prior written permission. 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #include 35 | #include 36 | #include "mempool_osdep.h" 37 | #include 38 | 39 | #ifdef RTE_EXEC_ENV_LINUXAPP 40 | 41 | #include 42 | #include 43 | #include 44 | 45 | 46 | #define PAGEMAP_FNAME "/proc/self/pagemap" 47 | 48 | /* 49 | * the pfn (page frame number) are bits 0-54 (see pagemap.txt in linux 50 | * Documentation). 51 | */ 52 | #define PAGEMAP_PFN_BITS 54 53 | #define PAGEMAP_PFN_MASK RTE_LEN2MASK(PAGEMAP_PFN_BITS, phys_addr_t) 54 | 55 | 56 | static int 57 | get_phys_map(void *va, phys_addr_t pa[], uint32_t pg_num, uint32_t pg_sz) 58 | { 59 | int32_t fd, rc; 60 | uint32_t i, nb; 61 | off_t ofs; 62 | 63 | ofs = (uintptr_t)va / pg_sz * sizeof(*pa); 64 | nb = pg_num * sizeof(*pa); 65 | 66 | if ((fd = open(PAGEMAP_FNAME, O_RDONLY)) < 0) 67 | return (ENOENT); 68 | 69 | if ((rc = pread(fd, pa, nb, ofs)) < 0 || (rc -= nb) != 0) { 70 | 71 | RTE_LOG(ERR, USER1, "failed read of %u bytes from \'%s\' " 72 | "at offset %zu, error code: %d\n", 73 | nb, PAGEMAP_FNAME, (size_t)ofs, errno); 74 | rc = ENOENT; 75 | } 76 | 77 | close(fd); 78 | 79 | for (i = 0; i != pg_num; i++) 80 | pa[i] = (pa[i] & PAGEMAP_PFN_MASK) * pg_sz; 81 | 82 | return (rc); 83 | } 84 | 85 | struct rte_mempool * 86 | mempool_anon_create(const char *name, unsigned elt_num, unsigned elt_size, 87 | unsigned cache_size, unsigned private_data_size, 88 | rte_mempool_ctor_t *mp_init, void *mp_init_arg, 89 | rte_mempool_obj_ctor_t *obj_init, void *obj_init_arg, 90 | int socket_id, unsigned flags) 91 | { 92 | struct rte_mempool *mp; 93 | phys_addr_t *pa; 94 | char *va, *uv; 95 | uint32_t n, pg_num, pg_shift, pg_sz, total_size; 96 | size_t sz; 97 | ssize_t usz; 98 | int32_t rc; 99 | 100 | rc = ENOMEM; 101 | mp = NULL; 102 | 103 | pg_sz = getpagesize(); 104 | if (rte_is_power_of_2(pg_sz) == 0) { 105 | rte_errno = EINVAL; 106 | return (mp); 107 | } 108 | 109 | pg_shift = rte_bsf32(pg_sz); 110 | 111 | total_size = rte_mempool_calc_obj_size(elt_size, flags, NULL); 112 | 113 | /* calc max memory size and max number of pages needed. */ 114 | sz = rte_mempool_xmem_size(elt_num, total_size, pg_shift); 115 | pg_num = sz >> pg_shift; 116 | 117 | /* get chunk of virtually continuos memory.*/ 118 | if ((va = mmap(NULL, sz, PROT_READ | PROT_WRITE, 119 | MAP_SHARED | MAP_ANONYMOUS | MAP_LOCKED, 120 | -1, 0)) == MAP_FAILED) { 121 | RTE_LOG(ERR, USER1, "%s(%s) failed mmap of %zu bytes, " 122 | "error code: %d\n", 123 | __func__, name, sz, errno); 124 | rte_errno = rc; 125 | return (mp); 126 | } 127 | 128 | /* extract physical mappings of the allocated memory. */ 129 | if ((pa = calloc(pg_num, sizeof (*pa))) != NULL && 130 | (rc = get_phys_map(va, pa, pg_num, pg_sz)) == 0) { 131 | 132 | /* 133 | * Check that allocated size is big enough to hold elt_num 134 | * objects and a calcualte how many bytes are actually required. 135 | */ 136 | 137 | if ((usz = rte_mempool_xmem_usage(va, elt_num, total_size, pa, 138 | pg_num, pg_shift)) < 0) { 139 | 140 | n = -usz; 141 | rc = ENOENT; 142 | RTE_LOG(ERR, USER1, "%s(%s) only %u objects from %u " 143 | "requested can be created over " 144 | "mmaped region %p of %zu bytes\n", 145 | __func__, name, n, elt_num, va, sz); 146 | } else { 147 | 148 | /* unmap unused pages if any */ 149 | if ((size_t)usz < sz) { 150 | 151 | uv = va + usz; 152 | usz = sz - usz; 153 | 154 | RTE_LOG(INFO, USER1, 155 | "%s(%s): unmap unused %zu of %zu " 156 | "mmaped bytes @%p\n", 157 | __func__, name, (size_t)usz, sz, uv); 158 | munmap(uv, usz); 159 | sz -= usz; 160 | pg_num = sz >> pg_shift; 161 | } 162 | 163 | if ((mp = rte_mempool_xmem_create(name, elt_num, 164 | elt_size, cache_size, private_data_size, 165 | mp_init, mp_init_arg, 166 | obj_init, obj_init_arg, 167 | socket_id, flags, va, pa, pg_num, 168 | pg_shift)) != NULL) 169 | 170 | RTE_VERIFY(elt_num == mp->size); 171 | } 172 | } 173 | 174 | if (mp == NULL) { 175 | munmap(va, sz); 176 | rte_errno = rc; 177 | } 178 | 179 | free(pa); 180 | return (mp); 181 | } 182 | 183 | #else /* RTE_EXEC_ENV_LINUXAPP */ 184 | 185 | 186 | struct rte_mempool * 187 | mempool_anon_create(__rte_unused const char *name, 188 | __rte_unused unsigned elt_num, __rte_unused unsigned elt_size, 189 | __rte_unused unsigned cache_size, 190 | __rte_unused unsigned private_data_size, 191 | __rte_unused rte_mempool_ctor_t *mp_init, 192 | __rte_unused void *mp_init_arg, 193 | __rte_unused rte_mempool_obj_ctor_t *obj_init, 194 | __rte_unused void *obj_init_arg, 195 | __rte_unused int socket_id, __rte_unused unsigned flags) 196 | { 197 | rte_errno = ENOTSUP; 198 | return (NULL); 199 | } 200 | 201 | #endif /* RTE_EXEC_ENV_LINUXAPP */ 202 | -------------------------------------------------------------------------------- /test-pmd/mempool_osdep.h: -------------------------------------------------------------------------------- 1 | /*- 2 | * BSD LICENSE 3 | * 4 | * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 11 | * * Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * * Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in 15 | * the documentation and/or other materials provided with the 16 | * distribution. 17 | * * Neither the name of Intel Corporation nor the names of its 18 | * contributors may be used to endorse or promote products derived 19 | * from this software without specific prior written permission. 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #ifndef _MEMPOOL_OSDEP_H_ 35 | #define _MEMPOOL_OSDEP_H_ 36 | 37 | #include 38 | 39 | /** 40 | * @file 41 | * mempool OS specific header. 42 | */ 43 | 44 | /* 45 | * Create mempool over objects from mmap(..., MAP_ANONYMOUS, ...). 46 | */ 47 | struct rte_mempool * 48 | mempool_anon_create(const char *name, unsigned n, unsigned elt_size, 49 | unsigned cache_size, unsigned private_data_size, 50 | rte_mempool_ctor_t *mp_init, void *mp_init_arg, 51 | rte_mempool_obj_ctor_t *obj_init, void *obj_init_arg, 52 | int socket_id, unsigned flags); 53 | 54 | #endif /*_RTE_MEMPOOL_OSDEP_H_ */ 55 | --------------------------------------------------------------------------------