aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitattributes1
-rw-r--r--.gitignore1
-rw-r--r--README.md18
-rw-r--r--analysis/analyze.R177
-rw-r--r--analysis/figures/delay_inmem0_stddev.txt4
-rw-r--r--analysis/figures/delay_inmem1_stddev.txt4
-rw-r--r--analysis/figures/fp_inmem0.txt13
-rw-r--r--analysis/figures/fp_inmem1.txt13
-rw-r--r--analysis/figures/power_median.txt4
-rw-r--r--analysis/figures/pure_read_inmemFALSE.pdfbin0 -> 145648 bytes
-rw-r--r--analysis/figures/pure_read_inmemFALSE_delay.pdfbin0 -> 153683 bytes
-rw-r--r--analysis/figures/pure_read_inmemFALSE_power.pdfbin0 -> 25540207 bytes
-rw-r--r--analysis/figures/pure_read_inmemTRUE.pdfbin0 -> 136388 bytes
-rw-r--r--analysis/figures/pure_read_inmemTRUE_delay.pdfbin0 -> 138217 bytes
-rw-r--r--analysis/figures/pure_read_inmemTRUE_power.pdfbin0 -> 26254959 bytes
-rw-r--r--analysis/figures/zmq.pdfbin0 -> 185290 bytes
-rw-r--r--sandbox/.gitignore2
-rw-r--r--sandbox/config19
-rw-r--r--sandbox/config_beaglebone19
-rw-r--r--sandbox/config_rpi19
-rw-r--r--sandbox/pure-read/Makefile10
-rw-r--r--sandbox/pure-read/read.c88
-rwxr-xr-xsandbox/run_beaglebone.sh138
-rwxr-xr-xsandbox/run_host.sh74
-rw-r--r--scripts/network_beaglebone.sh13
-rw-r--r--scripts/network_host.sh11
26 files changed, 628 insertions, 0 deletions
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..b637a67
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1 @@
+*.csv binary \ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..5904657
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+netstats.txt \ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..1a3ed07
--- /dev/null
+++ b/README.md
@@ -0,0 +1,18 @@
+# ina260-beaglebone-performance
+
+## Notes
+- Host machine = the one that launches the experiments
+
+## Package requirements
+### Host machine *AND* BeagleBone Black
+Packages:
+- time
+- iperf
+- zeromq
+### BeagleBone Black
+Driver:
+- INA260 for BeagleBone Black (available [here](https://gitlab.com/manzerbredes/ina260-sysfs-driver))
+
+## Results used in the paper
+- The results presented in the paper can be downloaded [here](https://data.lguegan.com/Repeatability/Datasets/INA260_BeagleBone_Black.tar.gz).
+- You can analyze them by extracting the content of the archive into the `analysis/results/` folder, and run the `analysis/analyze.R` script.
diff --git a/analysis/analyze.R b/analysis/analyze.R
new file mode 100644
index 0000000..745b9d3
--- /dev/null
+++ b/analysis/analyze.R
@@ -0,0 +1,177 @@
+library("tidyverse")
+library("latex2exp")
+
+## |--------------------------------+---------------------+-------------+------------------------------+--------------------------------------------+------------------------------------------------------------------|
+## | Monitored Hardware | Alim | I2C Address | Notes | OS | sha256sum (.img file) |
+## |--------------------------------+---------------------+-------------+------------------------------+--------------------------------------------+------------------------------------------------------------------|
+## | 1Kohm resistor | some random 5V alim | 0x40 | | | |
+## | Raspberry Pi 3 model B (2016) | 5.1V rpi alim | 0x41 | Powered through GPIO 2 and 6 | 2023-05-03-raspios-bullseye-arm64-lite.img | 9cd68ff450bc0fe0ac5b60e32723bc403ebca89d1214714e8e74361370d25204 |
+## | Raspberry Pi 3 model B+ (2017) | 5.1V rpi alim | 0x42 | Powered through GPIO 2 and 6 | 2023-05-03-raspios-bullseye-arm64-lite.img | 9cd68ff450bc0fe0ac5b60e32723bc403ebca89d1214714e8e74361370d25204 |
+## | Raspberry Pi 4 model B (2018) | 5.1V rpi alim | 0x43 | Powered through GPIO 2 and 6 | 2023-05-03-raspios-bullseye-arm64-lite.img | 9cd68ff450bc0fe0ac5b60e32723bc403ebca89d1214714e8e74361370d25204 |
+## |--------------------------------+---------------------+-------------+------------------------------+--------------------------------------------+------------------------------------------------------------------|
+
+
+pure_read=read_csv("results/pure_read.csv")
+zmq=read_csv("results/zmq.csv")
+
+GG_DELAY_READ=function(exp,for_inmem=0){
+ delays=exp%>%filter(inmem==for_inmem)%>%group_by(usen,deviceid)%>%mutate(tsnsec=(nsecs*10e-10)+timestamp)
+ delays=delays%>%mutate(delay=tsnsec-lag(tsnsec,1,default=NA))%>%filter(!is.na(delay))%>%mutate(time=timestamp-startat)
+ delays=delays%>%group_by(usen)%>%mutate(duration=max(time))
+ delays=delays%>%group_by(usen,deviceid,time)%>%summarize(delay_sd=sd(delay),delay_mean=mean(delay),duration=mean(duration),delay_max=max(delay),delay_min=min(delay))
+##### Store in file
+ f=paste0("figures/delay_inmem",for_inmem,"_stddev.txt")
+ window=0
+ ina1<<-delays%>%filter(usen==1,time>window,time<duration-window)
+ ina2<<-delays%>%filter(usen==2,time>window,time<duration-window)
+ ina3<<-delays%>%filter(usen==3,time>window,time<duration-window)
+ ina4<<-delays%>%filter(usen==4,time>window,time<duration-window)
+ write(paste0("With 1 INA260 sd=",mean(ina1$delay_sd)," min=",mean(ina1$delay_min)," max=",mean(ina1$delay_max)),f)
+ write(paste0("With 2 INA260 sd=",mean(ina2$delay_sd)," min=",mean(ina2$delay_min)," max=",mean(ina2$delay_max)),f,append=TRUE)
+ write(paste0("With 3 INA260 sd=",mean(ina3$delay_sd)," min=",mean(ina3$delay_min)," max=",mean(ina3$delay_max)),f,append=TRUE)
+ write(paste0("With 4 INA260 sd=",mean(ina4$delay_sd)," min=",mean(ina4$delay_min)," max=",mean(ina4$delay_max)),f,append=TRUE)
+ ##### Compute additional metrics
+ durations=delays%>%group_by(usen,deviceid)%>%summarise(duration=max(time))
+ med=delays%>%group_by(usen)%>%summarize(median=round(median(delay_mean),digits=9),duration=mean(duration))
+#### End
+ label_at <- function(n) function(x) ifelse(x %% n == 0, x, ifelse (x==0,x,""))
+ ggplot(delays,aes(time,delay_mean,color=deviceid))+geom_point()+
+ facet_wrap(~usen,labeller = labeller(usen = c("1" = "With 1 ina260 in use",
+ "2" = "With 2 ina260 in use",
+ "3" = "With 3 ina260 in use",
+ "4" = "With 4 ina260 in use")))+
+ ylab(TeX(r'(Average delay per seconds $\bar{d}$)'))+
+ xlab("Time (s)")+
+ labs(color="Device id")+
+ scale_y_continuous(breaks = seq(0, 0.1,by=0.0001),labels=seq(0, 0.1,by=0.0001))+
+ geom_text(data=med,aes(x=max(med$duration)/2,y=median,label=median),inherit.aes=FALSE,nudge_y=0.00004)+
+ geom_hline(data=med,aes(yintercept=median),size=0.9,show.legend = FALSE,size=0.3)+
+ theme(legend.position="top",legend.margin=margin(b = -0.2, unit='cm'))
+ ggsave(paste0("figures/pure_read_inmem",for_inmem!=0,"_delay.pdf"),width=6,height=5.5)
+}
+
+
+
+GG_READ_PERF=function(exp,for_inmem=0){
+##### Analyze
+ exp=exp%>%filter(inmem==for_inmem)%>%mutate(time=timestamp-startat)
+ data=exp%>%group_by(usen,deviceid)%>%group_by(usen,deviceid,timestamp,startat,endat)%>%summarize(nperdev=n())%>%mutate(time=timestamp-startat,duration=endat-startat)
+##### Now complete missing measurements (say no value on at time 5 then a row with a zero at that time must be added)
+ data=data%>%group_by(usen,deviceid)%>%complete(timestamp=seq(min(startat),min(endat),by=1),fill=list(nperdev=0))%>%mutate(startat=min(startat,na.rm=TRUE),endat=max(startat,na.rm=TRUE),time=timestamp-startat,duration=max(duration,na.rm=TRUE))
+##### Compute additional metrics
+ durations=exp%>%group_by(usen,deviceid)%>%summarise(duration=max(endat)-max(startat))
+ med=data%>%group_by(usen)%>%summarize(median=round(median(nperdev)),duration=mean(duration))
+#### End
+
+ # Plot
+ msg=paste0("(inmem=",for_inmem,")")
+ nread=max(exp$nread)
+ label_at <- function(n) function(x) ifelse(x %% n == 0, x, ifelse (x==0,x,""))
+ ggplot(data,aes(x=time,y=nperdev,color=deviceid)) + geom_point(size=0.3) +geom_line() + xlab("Time (s)") + ylab(TeX(r'(Sample read frequency $f_r$)')) +
+ facet_wrap(~usen,labeller = labeller(usen = c("1" = "With 1 ina260 in use",
+ "2" = "With 2 ina260 in use",
+ "3" = "With 3 ina260 in use",
+ "4" = "With 4 ina260 in use")))+
+ scale_x_continuous(breaks = seq(0,3600,by=60),labels=label_at(60))+
+ scale_y_continuous(breaks = seq(0, max(data$nperdev), by = 1000),expand = expansion(mult = 0.1))+
+ #ggtitle(paste("Stop until",nread,"measurements are done", msg))+
+ labs(color="Device id")+
+ geom_vline(data=durations,aes(xintercept=duration,color=deviceid),linetype="dashed",show.legend = FALSE)+
+ geom_hline(data=med,aes(yintercept=median),show.legend = FALSE,size=0.3)+
+ geom_text(data=med,aes(x=duration/2,y=median,label=median),inherit.aes=FALSE,vjust=-0.55)+
+ theme(legend.position="top",legend.margin=margin(b = -0.2, unit='cm'))
+ ggsave(paste0("figures/pure_read_inmem",for_inmem!=0,".pdf"),width=6,height=5.5)
+}
+
+TABLE_DELAY=function(exp,for_inmem=0){
+ delays=exp%>%filter(inmem==for_inmem)%>%group_by(usen,deviceid)%>%mutate(tsnsec=(nsecs*10e-10)+timestamp)
+ delays=delays%>%group_by(usen,deviceid)%>%mutate(delay=tsnsec-lag(tsnsec,1,default=NA))%>%filter(!is.na(delay))%>%mutate(time=timestamp-startat)
+ f=paste0("figures/fp_inmem",for_inmem,".txt")
+ write("", f)
+ delays%>%group_by(usen)%>%group_walk(function(data,grp){
+ cur_usen=grp$usen
+ cdf=ecdf(data$delay) # Get CDF
+#### For fd
+ fdefault=454.54
+ percent=1-cdf(1/fdefault)
+ write(paste0("inmem=",for_inmem," usen=",cur_usen,": f=",fdefault,"Hz percent=",round(percent*100,digits=2),"%", " missings=",percent*length(data$delay)),f, append=TRUE)
+#### For fmax
+ fmax=3571.429
+ percent=1-cdf(1/fmax)
+ write(paste0("inmem=",for_inmem," usen=",cur_usen,": f=",fmax,"Hz percent=",round(percent*100,digits=2),"%", " missings=",percent*length(data$delay),"\n----"),f, append=TRUE)
+ # plot(cdf,xlim=c(0,0.001))
+ })
+}
+
+GG_READ_POWER=function(exp,for_inmem=0){
+ # Analyze
+ exp=exp%>%filter(inmem==for_inmem)%>%mutate(time=timestamp-startat+nsecs*1e-9)
+ nread=max(exp$nread)
+ msg=paste0("(inmem=",for_inmem,")")
+ data=exp%>%group_by(usen,deviceid)%>%mutate(duration=endat-startat)
+ # Plot
+ label_at <- function(n) function(x) ifelse(x %% n == 0, x, ifelse (x==0,x,""))
+ ggplot(data,aes(x=time,y=power,color=deviceid)) + geom_point(size=0.3) +geom_line() + xlab("Time (s)") + ylab("Power consumption (W)") +
+ facet_wrap(~usen,labeller = labeller(usen = c("1" = "With 1 ina260 in use",
+ "2" = "With 2 ina260 in use",
+ "3" = "With 3 ina260 in use",
+ "4" = "With 4 ina260 in use")))+
+ scale_x_continuous(breaks = seq(0,3600,by=60),labels=label_at(60)) + ggtitle(paste("Stop until",nread,"measurements are done", msg))
+ ggsave(paste0("figures/pure_read_inmem",for_inmem!=0,"_power.pdf"),width=10)
+}
+
+TABLE_READ_POWER=function(exp){
+ power_0x40<<-median((exp%>%filter(addr=="0x40"))$power)
+ power_0x41<<-median((exp%>%filter(addr=="0x41"))$power)
+ power_0x42<<-median((exp%>%filter(addr=="0x42"))$power)
+ power_0x43<<-median((exp%>%filter(addr=="0x43"))$power)
+ power_0x40_std<<-round(sd((exp%>%filter(addr=="0x40"))$power),digits=2)
+ power_0x41_std<<-round(sd((exp%>%filter(addr=="0x41"))$power),digits=2)
+ power_0x42_std<<-round(sd((exp%>%filter(addr=="0x42"))$power),digits=2)
+ power_0x43_std<<-round(sd((exp%>%filter(addr=="0x43"))$power),digits=2)
+ f="figures/power_median.txt"
+ write(paste0("1Kohm resistor 0x40: ",power_0x40,"W(",power_0x40_std,")"), f)
+ write(paste0("Raspberri Pi 3 model B (2016) 0x41: ",power_0x41,"W(",power_0x41_std,")"), f, append=TRUE)
+ write(paste0("Raspberri Pi 3 model B+ (2017) 0x42: ",power_0x42,"W(",power_0x42_std,")"), f, append=TRUE)
+ write(paste0("Raspberry Pi 4 model B (2018) 0x43: ",power_0x43,"W(",power_0x43_std,")"), f, append=TRUE)
+}
+
+GG_ZMQ_PERF=function(exp){
+##### Analyze
+ data=exp%>%group_by(usen,deviceid,timestamp)%>%summarize(nperdev=n(),duration=max(duration))%>%mutate(time=timestamp-min(timestamp))
+ data=data%>%group_by(usen,deviceid)%>%mutate(startat=min(timestamp),endat=max(timestamp))
+ jean <<- data
+##### Now complete missing measurements (say no value on at time 5 then a row with a zero at that time must be added)
+ data=data%>%group_by(usen,deviceid)%>%complete(timestamp=seq(min(startat),min(startat)+max(duration),by=1),fill=list(nperdev=0))%>%mutate(startat=min(startat,na.rm=TRUE),endat=max(startat,na.rm=TRUE),time=timestamp-startat)
+#### Now compute additional metrics
+ med=data%>%group_by(usen)%>%summarize(median=round(median(nperdev)),duration_real=max(timestamp)-min(timestamp))
+#### Plot
+ label_at <- function(n) function(x) ifelse(x %% n == 0, x, ifelse (x==0,x,""))
+ ggplot(data,aes(x=time,y=nperdev,color=deviceid))+geom_point()+geom_line()+
+ facet_wrap(~usen,labeller = labeller(usen = c("1" = "With 1 ina260 in use",
+ "2" = "With 2 ina260 in use",
+ "3" = "With 3 ina260 in use",
+ "4" = "With 4 ina260 in use")))+
+ scale_x_continuous(breaks = seq(0,3600,by=60),labels=label_at(60))+
+ scale_y_continuous(breaks = seq(0, max(data$nperdev), by = 1000),expand = expansion(mult = 0.1))+
+ geom_hline(data=med,aes(yintercept=median),show.legend = FALSE,size=0.3)+
+ geom_text(data=med,aes(x=duration_real/2,y=median,label=median),inherit.aes=FALSE,vjust=-0.55)+
+ #ggtitle(paste("Running zmq experiment for",unique(exp$duration),"s"))+
+ labs(color="Device id")+
+ xlab("Time (s)") + ylab(TeX(r'(Sample read frequency $f_r$)'))+
+ theme(legend.position="top",legend.margin=margin(b = -0.2, unit='cm'))
+ ggsave("figures/zmq.pdf")
+
+}
+
+
+TABLE_DELAY(pure_read,0)
+TABLE_DELAY(pure_read,1)
+GG_DELAY_READ(pure_read,0)
+GG_DELAY_READ(pure_read,1)
+GG_READ_POWER(pure_read,0)
+GG_READ_POWER(pure_read,1)
+GG_READ_PERF(pure_read,0)
+GG_READ_PERF(pure_read,1)
+GG_ZMQ_PERF(zmq)
+TABLE_READ_POWER(pure_read)
diff --git a/analysis/figures/delay_inmem0_stddev.txt b/analysis/figures/delay_inmem0_stddev.txt
new file mode 100644
index 0000000..06a2402
--- /dev/null
+++ b/analysis/figures/delay_inmem0_stddev.txt
@@ -0,0 +1,4 @@
+With 1 INA260 sd=6.00937815261358e-05 min=0.000136256217956543 max=0.00356734121167982
+With 2 INA260 sd=0.000115172896629317 min=0.000216300670917218 max=0.00428919131939228
+With 3 INA260 sd=9.35477242715891e-05 min=0.000364981953750181 max=0.00227669163433182
+With 4 INA260 sd=0.000116468101100906 min=0.000549188091275403 max=0.00281525927986728
diff --git a/analysis/figures/delay_inmem1_stddev.txt b/analysis/figures/delay_inmem1_stddev.txt
new file mode 100644
index 0000000..23d4013
--- /dev/null
+++ b/analysis/figures/delay_inmem1_stddev.txt
@@ -0,0 +1,4 @@
+With 1 INA260 sd=1.73904637611061e-05 min=0.000125433459426417 max=0.000961011106317694
+With 2 INA260 sd=2.3209413244053e-05 min=0.000202646191488176 max=0.000837534866076988
+With 3 INA260 sd=3.46769061118768e-05 min=0.000362649877020653 max=0.00108031448743022
+With 4 INA260 sd=3.55985545001392e-05 min=0.000521048997183266 max=0.00118109433905883
diff --git a/analysis/figures/fp_inmem0.txt b/analysis/figures/fp_inmem0.txt
new file mode 100644
index 0000000..a13652d
--- /dev/null
+++ b/analysis/figures/fp_inmem0.txt
@@ -0,0 +1,13 @@
+
+inmem=0 usen=1: f=454.54Hz percent=0.01% missings=28.99999999999
+inmem=0 usen=1: f=3571.429Hz percent=1.31% missings=6553.00000000003
+----
+inmem=0 usen=2: f=454.54Hz percent=0.01% missings=144.99999999995
+inmem=0 usen=2: f=3571.429Hz percent=95.62% missings=956231
+----
+inmem=0 usen=3: f=454.54Hz percent=0.04% missings=604.999999999978
+inmem=0 usen=3: f=3571.429Hz percent=99.06% missings=1485850
+----
+inmem=0 usen=4: f=454.54Hz percent=0.07% missings=1470
+inmem=0 usen=4: f=3571.429Hz percent=99.39% missings=1987883
+----
diff --git a/analysis/figures/fp_inmem1.txt b/analysis/figures/fp_inmem1.txt
new file mode 100644
index 0000000..d86a5b6
--- /dev/null
+++ b/analysis/figures/fp_inmem1.txt
@@ -0,0 +1,13 @@
+
+inmem=1 usen=1: f=454.54Hz percent=0% missings=17.0000000000018
+inmem=1 usen=1: f=3571.429Hz percent=0.07% missings=364.999999999992
+----
+inmem=1 usen=2: f=454.54Hz percent=0% missings=33.000000000023
+inmem=1 usen=2: f=3571.429Hz percent=99.04% missings=990429
+----
+inmem=1 usen=3: f=454.54Hz percent=0.02% missings=225.999999999981
+inmem=1 usen=3: f=3571.429Hz percent=99.6% missings=1494044
+----
+inmem=1 usen=4: f=454.54Hz percent=0.03% missings=571.000000000086
+inmem=1 usen=4: f=3571.429Hz percent=99.85% missings=1996963
+----
diff --git a/analysis/figures/power_median.txt b/analysis/figures/power_median.txt
new file mode 100644
index 0000000..3fc1ab7
--- /dev/null
+++ b/analysis/figures/power_median.txt
@@ -0,0 +1,4 @@
+1Kohm resistor 0x40: 0.3W(0.05)
+Raspberri Pi 3 model B (2016) 0x41: 1.34W(0.02)
+Raspberri Pi 3 model B+ (2017) 0x42: 2.27W(0.02)
+Raspberry Pi 4 model B (2018) 0x43: 1.91W(0.15)
diff --git a/analysis/figures/pure_read_inmemFALSE.pdf b/analysis/figures/pure_read_inmemFALSE.pdf
new file mode 100644
index 0000000..ae182ad
--- /dev/null
+++ b/analysis/figures/pure_read_inmemFALSE.pdf
Binary files differ
diff --git a/analysis/figures/pure_read_inmemFALSE_delay.pdf b/analysis/figures/pure_read_inmemFALSE_delay.pdf
new file mode 100644
index 0000000..fd1f70f
--- /dev/null
+++ b/analysis/figures/pure_read_inmemFALSE_delay.pdf
Binary files differ
diff --git a/analysis/figures/pure_read_inmemFALSE_power.pdf b/analysis/figures/pure_read_inmemFALSE_power.pdf
new file mode 100644
index 0000000..41d5009
--- /dev/null
+++ b/analysis/figures/pure_read_inmemFALSE_power.pdf
Binary files differ
diff --git a/analysis/figures/pure_read_inmemTRUE.pdf b/analysis/figures/pure_read_inmemTRUE.pdf
new file mode 100644
index 0000000..6468f20
--- /dev/null
+++ b/analysis/figures/pure_read_inmemTRUE.pdf
Binary files differ
diff --git a/analysis/figures/pure_read_inmemTRUE_delay.pdf b/analysis/figures/pure_read_inmemTRUE_delay.pdf
new file mode 100644
index 0000000..00dcf8a
--- /dev/null
+++ b/analysis/figures/pure_read_inmemTRUE_delay.pdf
Binary files differ
diff --git a/analysis/figures/pure_read_inmemTRUE_power.pdf b/analysis/figures/pure_read_inmemTRUE_power.pdf
new file mode 100644
index 0000000..353cba8
--- /dev/null
+++ b/analysis/figures/pure_read_inmemTRUE_power.pdf
Binary files differ
diff --git a/analysis/figures/zmq.pdf b/analysis/figures/zmq.pdf
new file mode 100644
index 0000000..2825548
--- /dev/null
+++ b/analysis/figures/zmq.pdf
Binary files differ
diff --git a/sandbox/.gitignore b/sandbox/.gitignore
new file mode 100644
index 0000000..841d798
--- /dev/null
+++ b/sandbox/.gitignore
@@ -0,0 +1,2 @@
+ina260-zmq-publisher
+pure-read/read \ No newline at end of file
diff --git a/sandbox/config b/sandbox/config
new file mode 100644
index 0000000..317165f
--- /dev/null
+++ b/sandbox/config
@@ -0,0 +1,19 @@
+# Global Configuration:
+inadev="2:0x40 2:0x41 2:0x42 2:0x43"
+bbhost=debian@192.168.6.2
+delaypurezmq=10
+delayiperfpure=10
+
+# Pure Read Experiments:
+nread=500000
+readrest=60
+
+# ZMQ Experiments:
+zmqrest=60
+zmqduration=300
+hostip=192.168.7.1
+zmqport=5556
+zmqlogdelay=0
+zmqloginterval=60
+zmqmsgsize=20242880
+zmqmaxqueue=1
diff --git a/sandbox/config_beaglebone b/sandbox/config_beaglebone
new file mode 100644
index 0000000..317165f
--- /dev/null
+++ b/sandbox/config_beaglebone
@@ -0,0 +1,19 @@
+# Global Configuration:
+inadev="2:0x40 2:0x41 2:0x42 2:0x43"
+bbhost=debian@192.168.6.2
+delaypurezmq=10
+delayiperfpure=10
+
+# Pure Read Experiments:
+nread=500000
+readrest=60
+
+# ZMQ Experiments:
+zmqrest=60
+zmqduration=300
+hostip=192.168.7.1
+zmqport=5556
+zmqlogdelay=0
+zmqloginterval=60
+zmqmsgsize=20242880
+zmqmaxqueue=1
diff --git a/sandbox/config_rpi b/sandbox/config_rpi
new file mode 100644
index 0000000..376065a
--- /dev/null
+++ b/sandbox/config_rpi
@@ -0,0 +1,19 @@
+# Global Configuration:
+inadev="1:0x41"
+bbhost=pi@10.128.0.93
+delaypurezmq=0
+delayiperfpure=5
+
+# Pure Read Experiments:
+nread=500000
+readrest=5
+
+# ZMQ Experiments:
+zmqrest=5
+zmqduration=60
+hostip=10.128.0.133
+zmqport=5556
+zmqlogdelay=0
+zmqloginterval=10
+zmqmsgsize=20242880
+zmqmaxqueue=1 \ No newline at end of file
diff --git a/sandbox/pure-read/Makefile b/sandbox/pure-read/Makefile
new file mode 100644
index 0000000..353835b
--- /dev/null
+++ b/sandbox/pure-read/Makefile
@@ -0,0 +1,10 @@
+
+all: read
+
+read: read.c
+ gcc $^ -o $@
+
+clean:
+ - rm read
+
+.PHONY: clean \ No newline at end of file
diff --git a/sandbox/pure-read/read.c b/sandbox/pure-read/read.c
new file mode 100644
index 0000000..539933d
--- /dev/null
+++ b/sandbox/pure-read/read.c
@@ -0,0 +1,88 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <time.h>
+
+#define BUFFER_SIZE 255
+#define IN_MEM (inmem!=0)
+
+typedef struct power_data {
+ float power; // Power value
+ long ts; // Associated timestamp
+ long nsecs; // Associated nanosecs
+} power_data;
+
+int main(int argc, char *argv[])
+{
+ if(argc != 4){
+ printf("Usage: %s <device-id> <nread> <inmem>\n\
+ \rFor <device-id>, see folder name in /sys/kernel/ina260/",argv[0]);
+ exit(1);
+ }
+
+ char *deviceid=argv[1];
+ int nread=atoi(argv[2]);
+ int inmem=atoi(argv[3]);
+
+ if(nread<=0){
+ printf("<nread> must be greater than 0\n");
+ exit(3);
+ }
+
+ // File to read
+ char path[255];
+ sprintf(path, "/sys/kernel/ina260/%s/power", deviceid);
+
+ // Open file
+ int fd;
+ char buff[BUFFER_SIZE];
+ fd = open(path, O_RDONLY);
+ if(fd<0){
+ perror(path);
+ exit(2);
+ }
+
+ // Check if its in memory reading
+ power_data *data;
+ if(IN_MEM){
+ data=malloc(sizeof(power_data)*nread);
+ if(data == NULL){
+ perror("Cannot allocate enough memory for in memory reads");
+ exit(4);
+ }
+ }
+
+ // Perform reads
+ float power=-1;
+ struct timespec power_ts;
+ clock_gettime(CLOCK_REALTIME, &power_ts);
+
+ printf("startat:%ld\n", power_ts.tv_sec);
+ for(int i=0;i<nread;i++){
+ read(fd, buff, BUFFER_SIZE);
+ // Get power measurement timestamp:
+ clock_gettime(CLOCK_REALTIME, &power_ts);
+ power=atof(buff);
+ if(IN_MEM){
+ data[i].power=power;
+ data[i].ts=power_ts.tv_sec;
+ data[i].nsecs=power_ts.tv_nsec;
+ }
+ else{
+ printf("%s %11ld %10ld> Power is %fW\n",deviceid, power_ts.tv_sec,power_ts.tv_nsec,power);
+ }
+ lseek(fd,0,SEEK_SET);
+ }
+ close(fd);
+
+ if(IN_MEM){
+ // We only print now (most I/O will happend at the end and this must be visible on the results)
+ for(int i=0;i<nread;i++){
+ printf("%s %11ld %10ld> Power is %fW\n",deviceid, data[i].ts, data[i].nsecs, data[i].power);
+ }
+ free(data);
+ }
+ printf("endat:%ld\n", time(NULL));
+ return 0;
+}
diff --git a/sandbox/run_beaglebone.sh b/sandbox/run_beaglebone.sh
new file mode 100755
index 0000000..c610c6e
--- /dev/null
+++ b/sandbox/run_beaglebone.sh
@@ -0,0 +1,138 @@
+#!/usr/bin/env bash
+
+set -e
+
+wai=$(dirname $(readlink -f "$0")) # Current script directory
+source ${wai}/config
+
+info () {
+ echo -e "\033[0;32m$@\033[0m"
+}
+
+abort () {
+ echo -e "\033[0;31m$@\033[0m"
+ exit 1
+}
+
+iperf-run () {
+ info "---------- Running iperf test ----------"
+ iperf -c ${hostip}
+}
+
+pure-read () {
+ local clean="${1:-1}"
+ local inmem="${2:-0}"
+ info "---------- Running pure read experiments (inmem=${inmem},clean=${clean}) ----------"
+ info "Ensuring that ina260 devices are connected..."
+ for dev in $inadev
+ do
+ bus=$(echo $dev|cut -d: -f1)
+ addr=$(echo $dev|cut -d: -f2)
+ [ -z $(ls /sys/kernel/ina260/ |grep "${bus}-.*${addr#0x}") ] && echo ina260 $addr | sudo tee "/sys/bus/i2c/devices/i2c-${bus}/new_device"
+ [ -z $(ls /sys/kernel/ina260/ |grep "${bus}-.*${addr#0x}") ] && abort "Cannot connect $dev"
+ done
+ info "Compiling..."
+ make -C ${wai}/pure-read -B
+ [ $clean -eq 1 ] && rm -f ${wai}/pure_read_bus*.out
+ local ndev=$(echo $inadev|wc -w)
+ for usen in $(seq 1 $ndev)
+ do
+ info "Run $nread read over $usen devices"
+ local n=0
+ unset pids # Erase previous pids
+ for dev in $inadev
+ do
+ local bus=$(echo $dev|cut -d: -f1)
+ local addr=$(echo $dev|cut -d: -f2)
+ local devicepath=$(realpath /sys/kernel/ina260/${bus}-*${addr#0x})
+ local deviceid=$(basename ${devicepath})
+ local logfile=${wai}/pure_read_bus${bus}_addr${addr}_usen${usen}_nread${nread}_inmem${inmem}.out
+ echo "${bus}:${addr}:${usen}:${nread}:${deviceid}" > ${logfile}
+ /usr/bin/time -f "statsline:%P:%M" ${wai}/pure-read/read $deviceid $nread $inmem &>> ${logfile} &
+ pids[${i}]=$!
+ n=$(( n + 1 ))
+ [ $n -eq $usen ] && break
+ done
+ # Wait for all pids
+ for pid in ${pids[*]}; do
+ wait $pid
+ done
+ sync # Ensure that I/O are applied on sdcard
+ info "Beaglebone is resting for ${readrest}s"
+ sleep ${readrest}
+ done
+ # Generate the results
+ info "Collecting logs..."
+ local csv="${wai}/pure_read.csv"
+ [ $clean -eq 1 ] && echo "bus,addr,usen,nread,deviceid,startat,endat,inmem,cpu_usage,resident,timestamp,nsecs,power" > "$csv"
+ for logfile in ${wai}/pure_read_bus*inmem${inmem}.out
+ do
+ local bus=$(head -n1 "$logfile"|cut -d: -f1)
+ local addr=$(head -n1 "$logfile"|cut -d: -f2)
+ local usen=$(head -n1 "$logfile"|cut -d: -f3)
+ local nread=$(head -n1 "$logfile"|cut -d: -f4)
+ local deviceid="${bus}-${addr}"
+ local startat=$(cat "$logfile"|grep startat|cut -d: -f2)
+ local endat=$(cat "$logfile"|grep endat|cut -d: -f2)
+ local cpu_usage=$(cat "$logfile"|grep statsline|cut -d: -f2|awk '{print(($0+0)/100)}')
+ local resident=$(cat "$logfile"|grep statsline|cut -d: -f3|awk '{print(($0+0)*1000)}')
+ local infos="${bus},${addr},${usen},${nread},${deviceid},${startat},${endat},${inmem},${cpu_usage},${resident}"
+ awk '/Power is/ { print("'${infos}',"$2+0","$3+0","$6+0)}' "$logfile" >> "$csv"
+ done
+}
+
+zmq () {
+ echo "---------- Running zmq experiments ----------"
+ info "Disconnecting all ina260..."
+ for dev in $(ls /sys/kernel/ina260/)
+ do
+ dev=$(basename $dev)
+ bus=$(echo $dev|cut -d\- -f1)
+ addr=$(echo $dev|cut -d\- -f2)
+ echo 0x${addr} | sudo tee /sys/bus/i2c/devices/i2c-${bus}/delete_device
+ done
+ # Setup publisher
+ cd ${wai}/ina260-zmq-publisher
+ rm -f publisher_*.log
+ info "Compiling..."
+ make -B
+ # Run experiments (add one new ina260 at each loop)
+ local n=1
+ for dev in $inadev
+ do
+ info "Run zmq over $n devices for ${zmqduration}s"
+ bus=$(echo $dev|cut -d: -f1)
+ addr=$(echo $dev|cut -d: -f2)
+ [ -z $(ls /sys/kernel/ina260/ |grep "${bus}-.*${addr#0x}") ] && echo ina260 $addr | sudo tee "/sys/bus/i2c/devices/i2c-${bus}/new_device"
+ [ -z $(ls /sys/kernel/ina260/ |grep "${bus}-.*${addr#0x}") ] && abort "Cannot connect $dev"
+ # Run experiment
+ sed "s/^KEY=.*/KEY=usen$n/g" -i config.mk
+ make publish &
+ sleep ${zmqduration}
+ kill -s SIGINT $(cat pid)
+ # Wait for all publisher processes to end:
+ for pid in $(cat pid)
+ do
+ while ps -p $pid > /dev/null; do continue; done
+ done
+ # Done
+ n=$(( n + 1 ))
+ info "Beaglebone is resting for ${zmqrest}s"
+ sleep $zmqrest
+ done
+ cd ${wai} # Go back to last directory
+}
+
+##### Run experiments
+# Network benchmark
+iperf-run
+info "Sleep ${delayiperfpure}s before starting pure-read experiments..."
+sleep ${delayiperfpure}
+# Pure read
+pure-read 1 1 # Do in memory first!
+pure-read 0 0 # This way, we are sure in file has no impact
+# Sleep
+info "Sleep ${delaypurezmq}s before starting zmq experiments..."
+sleep ${delaypurezmq}
+# ZMQ
+zmq \ No newline at end of file
diff --git a/sandbox/run_host.sh b/sandbox/run_host.sh
new file mode 100755
index 0000000..c107d4b
--- /dev/null
+++ b/sandbox/run_host.sh
@@ -0,0 +1,74 @@
+#!/usr/bin/env bash
+set -e
+wai=$(dirname $(readlink -f "$0")) # Current script directory
+zmq=${wai}/ina260-zmq-publisher
+source ${wai}/config # Load experiment configuration
+bbexec="ssh -q ${bbhost}"
+nosync="no" # change this to yes ONLY FOR TESTS
+
+# Ensure zmq publisher is available
+[ ! -d "${zmq}" ] && git clone https://gitlab.com/manzerbredes/ina260-zmq-publisher.git "${zmq}"
+# Configuring zmq project
+echo "Configuring ina260-zmq-publisher"
+sed "s/^SUBSCRIBER_ADDR=.*/SUBSCRIBER_ADDR=${hostip}/g" -i ${zmq}/config.mk
+sed "s/^ZMQ_PORT=.*/ZMQ_PORT=${zmqport}/g" -i ${zmq}/config.mk
+sed "s/^LOG_DELAY=.*/LOG_DELAY=${zmqlogdelay}/g" -i ${zmq}/config.mk
+sed "s/^LOG_INTERVAL=.*/LOG_INTERVAL=${zmqloginterval}/g" -i ${zmq}/config.mk
+sed "s/^ZMQ_MSG_SIZE=.*/ZMQ_MSG_SIZE=${zmqmsgsize}/g" -i ${zmq}/config.mk
+sed "s/^MAX_QUEUE=.*/MAX_QUEUE=${zmqmaxqueue}/g" -i ${zmq}/config.mk
+
+# Setting up beaglebone
+[ ${nosync} != "yes" ] && rsync -avh --exclude=".git*" --exclude="ina260-zmq-publisher/data" ina260-zmq-publisher pure-read run_beaglebone.sh config ${bbhost}:sandbox/
+
+# Cleaning previous results
+[ -x "${zmq}/data" ] && rm -rf "${zmq}/data"
+
+##### Run experiments
+# Start zmq subscriber on the host
+echo "Starting subscriber"
+cd $zmq
+make -B
+make subscribe &
+zmqpid=$!
+cd - > /dev/null
+# Start iperf
+iperf -s -fm -o netstats.txt &
+iperfpid=$!
+# Start experiments
+$bbexec "cd sandbox && ./run_beaglebone.sh"
+
+# Collect pure-read results
+echo "Fetching pure-read results"
+rsync -avh ${bbhost}:sandbox/pure_read.csv ${wai}/../analysis/results/
+
+# Collect zmq results
+echo "Formatting zmq results"
+. ${wai}/config
+zmqcsv="${wai}/../analysis/results/zmq.csv"
+echo "bus,addr,deviceid,usen,duration,loginterval,logdelay,rest,msgsize,timestamp,nsecs,power" > "$zmqcsv"
+for exp in ${zmq}/data/*
+do
+ usen=$(basename $exp|sed "s/usen//g")
+ for dev in $exp/*
+ do
+ deviceid=$(basename $dev)
+ bus=$(echo $deviceid|cut -d\- -f1)
+ addr=0x$(echo $deviceid|cut -d\- -f2|awk '{print $0+0}')
+ infos="${bus},${addr},${bus}-${addr},${usen},${zmqduration},${zmqloginterval},${zmqlogdelay},${zmqrest},${zmqmsgsize}"
+ cat $dev/* | awk '!/timestamp/{print("'$infos',"$0)}' >> "$zmqcsv"
+ done
+done
+
+# Collecting iperf results
+echo "Formatting iperf results"
+bw=$(cat netstats.txt |awk -F '[ -]+' '/sec/{print $8}') # Mbps
+iperfcsv="${wai}/../analysis/results/iperf.csv"
+echo "bw" > "$iperfcsv"
+echo "${bw}" >> "$iperfcsv"
+
+# Stopping zmq subscriber and iperf
+echo "Stopping subscriber..."
+kill $zmqpid
+echo "Stopping iperf..."
+kill $iperfpid
+echo "Finished congratulations!"
diff --git a/scripts/network_beaglebone.sh b/scripts/network_beaglebone.sh
new file mode 100644
index 0000000..11fdce4
--- /dev/null
+++ b/scripts/network_beaglebone.sh
@@ -0,0 +1,13 @@
+#!/usr/bin/env bash
+
+# Config
+NAMESERVER="162.19.75.102"
+
+# Setup
+ifconfig eth0 down
+ifconfig usb1 down
+ifconfig usb0 10.0.0.2/24
+iptables -F
+ip route del default
+ip route add default via 10.0.0.1 dev usb0
+echo "nameserver ${NAMESERVER}" > /etc/resolv.conf
diff --git a/scripts/network_host.sh b/scripts/network_host.sh
new file mode 100644
index 0000000..d48b90b
--- /dev/null
+++ b/scripts/network_host.sh
@@ -0,0 +1,11 @@
+#!/usr/bin/env bash
+
+# Config
+INTERNET_INTERFACE="wlp0s20f3"
+BEAGLEBONE_INTERFACE="enp0s20f0u4u4u2"
+
+# Setup
+iptables -F
+iptables -t nat -A POSTROUTING -o ${INTERNET_INTERFACE} -j MASQUERADE
+iptables -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
+iptables -A FORWARD -i ${BEAGLEBONE_INTERFACE} -o ${INTERNET_INTERFACE} -j ACCEPT