Browse Source

Added experiments.

Kyle Fredrickson 1 year ago
parent
commit
f1a24ae0a2

+ 3 - 0
.gitignore

@@ -1 +1,4 @@
 target/
+data/
+*.svg
+/*.perf*

+ 224 - 4
baseline/Cargo.lock

@@ -2,11 +2,60 @@
 # It is not intended for manual editing.
 version = 3
 
+[[package]]
+name = "anstream"
+version = "0.6.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b"
+dependencies = [
+ "anstyle",
+ "anstyle-parse",
+ "anstyle-query",
+ "anstyle-wincon",
+ "colorchoice",
+ "is_terminal_polyfill",
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle"
+version = "1.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b"
+
+[[package]]
+name = "anstyle-parse"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4"
+dependencies = [
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle-query"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5"
+dependencies = [
+ "windows-sys",
+]
+
+[[package]]
+name = "anstyle-wincon"
+version = "3.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19"
+dependencies = [
+ "anstyle",
+ "windows-sys",
+]
+
 [[package]]
 name = "baseline"
 version = "0.1.0"
 dependencies = [
- "omq",
+ "clap",
  "otils",
 ]
 
@@ -17,15 +66,186 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "41c270e7540d725e65ac7f1b212ac8ce349719624d7bcff99f8e2e488e8cf03f"
 
 [[package]]
-name = "omq"
-version = "0.1.0"
+name = "clap"
+version = "4.5.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0"
 dependencies = [
- "otils",
+ "clap_builder",
+ "clap_derive",
 ]
 
+[[package]]
+name = "clap_builder"
+version = "4.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4"
+dependencies = [
+ "anstream",
+ "anstyle",
+ "clap_lex",
+ "strsim",
+]
+
+[[package]]
+name = "clap_derive"
+version = "4.5.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64"
+dependencies = [
+ "heck",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "clap_lex"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce"
+
+[[package]]
+name = "colorchoice"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422"
+
+[[package]]
+name = "heck"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
+
+[[package]]
+name = "is_terminal_polyfill"
+version = "1.70.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800"
+
 [[package]]
 name = "otils"
 version = "0.1.0"
 dependencies = [
  "cc",
 ]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.84"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec96c6a92621310b51366f1e28d05ef11489516e93be030060e5fc12024a49d6"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.36"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "strsim"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
+
+[[package]]
+name = "syn"
+version = "2.0.66"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
+
+[[package]]
+name = "utf8parse"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
+
+[[package]]
+name = "windows-sys"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
+dependencies = [
+ "windows-targets",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
+dependencies = [
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_gnullvm",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670"
+
+[[package]]
+name = "windows_i686_gnullvm"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"

+ 4 - 1
baseline/Cargo.toml

@@ -3,9 +3,12 @@ name = "baseline"
 version = "0.1.0"
 edition = "2021"
 
+[profile.release]
+debug = true
+
 [dependencies]
-omq = { path = "../omq" }
 otils = { path = "../otils" }
+clap = { version = "4.5.4", features = ["derive"] }
 
 [package.metadata.fortanix-sgx]
 stack-size=0x400000

+ 14 - 10
baseline/makefile

@@ -1,24 +1,28 @@
+NAME = baseline
+BUILD_DIR = target/x86_64-fortanix-unknown-sgx/release
+KEY = private.pem
+
+BINARY = $(BUILD_DIR)/$(NAME)
+TARGET = $(BUILD_DIR)/$(NAME).sgxs
+SIGNATURE = $(BUILD_DIR)/$(NAME).sig
+
 HEAP_SIZE = 0x100000000
 STACK_SIZE = 0x400000
 MAX_THREADS = 9
 
-BUILD_DIR = target/x86_64-fortanix-unknown-sgx/release
-
-BINARY = $(BUILD_DIR)/baseline
-TARGET = $(BUILD_DIR)/baseline.sgxs
-SIGNATURE = $(BUILD_DIR)/baseline.sig
-
-.PHONY: clean run
+.PHONY: build run clean
 
 $(TARGET): $(BINARY)
 	ftxsgx-elf2sgxs -o $(TARGET) $(BINARY) --heap-size $(HEAP_SIZE) --stack-size $(STACK_SIZE) --threads $(MAX_THREADS)
-	sgxs-sign --key private.pem $(TARGET) $(SIGNATURE)
+	sgxs-sign --key $(KEY) $(TARGET) $(SIGNATURE)
+
+$(BINARY): build
 
-$(BINARY):
+build:
 	cargo build --release
 
 run: $(TARGET)
-	ftxsgx-runner $(TARGET) 3 7 8
+	ftxsgx-runner $(TARGET) 2097152 30000 8
 
 clean:
 	rm -rf $(BUILD_DIR)

+ 0 - 3
baseline/run_experiment.sh

@@ -1,3 +0,0 @@
-#! /bin/bash
-
-ftxsgx-runner target/x86_64-fortanix-unknown-sgx/release/sparta.sgxs $@

+ 37 - 11
baseline/src/main.rs

@@ -1,26 +1,50 @@
+#![feature(test)]
+mod omq;
+mod request;
+
+use clap::Parser;
+use omq::ObliviousMultiQueue;
+use request::Request;
 use std::time::UNIX_EPOCH;
 
-use omq::{Omq, Request};
+/// Baseline oblivious sort based multiqueue.
+#[derive(Parser, Debug)]
+#[command(version, about, long_about = None)]
+struct Args {
+    /// Number of send requests to store in the database.
+    sends: usize,
+
+    /// Number of messages to fetch from the database.
+    fetches: usize,
+
+    /// Total number of threads available.
+    threads: usize,
+
+    /// Total number of runs.
+    #[arg(short, long, default_value = "1")]
+    runs: usize,
+
+    /// Number of runs before measurements are recorded.
+    #[arg(short, long, default_value = "0")]
+    warmup_runs: usize,
+}
 
 fn main() {
-    let args: Vec<String> = std::env::args().collect();
-    let num_sends = args[1].parse::<usize>().unwrap();
-    let num_fetches = args[2].parse::<usize>().unwrap();
-    let num_threads = args[3].parse::<usize>().unwrap();
+    let args = Args::parse();
 
-    let mut o = Omq::new(num_threads);
+    let mut o = ObliviousMultiQueue::new(args.threads);
 
-    let sends: Vec<Request> = (0..num_sends)
+    let sends: Vec<Request> = (0..args.sends)
         .map(|x| Request::new_send(0, x.try_into().unwrap()))
         .collect();
     o.batch_send(sends);
-    let results: Vec<u128> = (0..15)
+    let results: Vec<u128> = (0..(args.runs + args.warmup_runs))
         .map(|_| {
             let start = std::time::SystemTime::now()
                 .duration_since(UNIX_EPOCH)
                 .unwrap()
                 .as_nanos();
-            let _ = o.batch_fetch(vec![Request::new_fetch(0, num_fetches)]);
+            let _ = o.batch_fetch(vec![Request::new_fetch(0, args.fetches)]);
             let end = std::time::SystemTime::now()
                 .duration_since(UNIX_EPOCH)
                 .unwrap()
@@ -28,8 +52,10 @@ fn main() {
             end - start
         })
         .collect();
-    for idx in 5..results.len() {
-        print!("{}\t", results[idx]);
+
+    print!("{}\t", args.sends);
+    for result in results[args.warmup_runs..].iter() {
+        print!("{}\t", *result as f64 / 1000000000.0);
     }
     println!();
 }

+ 13 - 12
omq/src/lib.rs → baseline/src/omq.rs

@@ -1,18 +1,15 @@
-#![feature(test)]
-
-mod request;
+use crate::request::Request;
 use otils::ObliviousOps;
-pub use request::Request;
 
 #[derive(Debug)]
-pub struct Omq {
+pub struct ObliviousMultiQueue {
     num_threads: usize,
     message_store: Vec<Request>,
 }
 
-impl Omq {
+impl ObliviousMultiQueue {
     pub fn new(num_threads: usize) -> Self {
-        Omq {
+        ObliviousMultiQueue {
             num_threads,
             message_store: Vec::new(),
         }
@@ -24,9 +21,7 @@ impl Omq {
     }
 
     fn update_store(&mut self, fetches: Vec<Request>, fetch_sum: usize) {
-        let size = self.message_store.len() + fetches.len() + fetch_sum;
-
-        self.message_store.reserve(size - self.message_store.len());
+        self.message_store.reserve(fetches.len() + fetch_sum);
 
         for fetch in fetches.iter() {
             self.message_store
@@ -65,7 +60,10 @@ impl Omq {
             |r| r.should_deliver(),
             self.num_threads,
         );
-        let deliver = self.message_store[0..fetch_sum].to_vec();
+        let deliver: Vec<Request> = self.message_store.drain(0..fetch_sum).collect();
+        // for r in deliver.iter() {
+        //     println!("{:?}", r);
+        // }
 
         otils::compact(
             &mut self.message_store[..],
@@ -73,6 +71,9 @@ impl Omq {
             self.num_threads,
         );
         self.message_store.truncate(final_size);
+        // for r in self.message_store.iter() {
+        //     println!("{:?}", r);
+        // }
 
         deliver
     }
@@ -87,7 +88,7 @@ mod tests {
 
     #[bench]
     fn bench_fetch(b: &mut Bencher) {
-        let mut o = Omq::new(8);
+        let mut o = ObliviousMultiQueue::new(8);
 
         let sends: Vec<Request> = (0..1048576)
             .map(|x| Request::new_send(0, x.try_into().unwrap()))

+ 6 - 6
omq/src/request.rs → baseline/src/request.rs

@@ -6,13 +6,13 @@ pub const FETCH: u16 = 0;
 pub const SEND: u16 = 1;
 pub const DUMMY: u16 = 2;
 
-#[derive(Debug, Clone, Copy)]
+#[derive(Debug)]
 pub struct Request {
     pub uid: i32,
     pub req_type: u16,
     pub mark: u16,
     pub volume: usize,
-    pub message: u64,
+    pub _message: u64,
     pub _dum: [u64; 13],
 }
 
@@ -29,7 +29,7 @@ impl Request {
                 .duration_since(UNIX_EPOCH)
                 .unwrap()
                 .as_nanos() as usize,
-            message,
+            _message: message,
             _dum: [0; 13],
         }
     }
@@ -43,7 +43,7 @@ impl Request {
             req_type: FETCH,
             mark: 0,
             volume,
-            message: 0,
+            _message: 0,
             _dum: [0; 13],
         }
     }
@@ -55,7 +55,7 @@ impl Request {
                 req_type: DUMMY,
                 mark: 0,
                 volume: 0,
-                message: 0,
+                _message: 0,
                 _dum: [0; 13],
             })
             .collect()
@@ -81,7 +81,7 @@ impl Max for Request {
             req_type: DUMMY,
             mark: 0,
             volume: 0,
-            message: 0,
+            _message: 0,
             _dum: [0; 13],
         }
     }

+ 52 - 0
experiments/message_scaling.py

@@ -0,0 +1,52 @@
+import os
+import subprocess
+
+SENDS = [2**i for i in range(20, 30)]
+FETCHES = 50000
+USERS = int(FETCHES / 2)
+
+
+THREADS = 8
+MAPS = 4
+
+RUNS = 1
+WARMUP = 0
+
+DATA_DIR = os.path.join(os.getcwd(), "data", "message-scaling")
+os.makedirs(DATA_DIR, exist_ok=True)
+
+SPARTA_DIR = os.path.join(os.getcwd(), "sparta")
+BASELINE_DIR = os.path.join(os.getcwd(), "baseline")
+
+BASELINE_FILE = os.path.join(DATA_DIR, f"baseline-{FETCHES}-{THREADS}.csv")
+SPARTA_FILE = os.path.join(DATA_DIR, f"sparta-{FETCHES}-{THREADS}-{MAPS}.csv")
+
+
+def sparta_cmd(sends):
+    cmd = ["cargo", "run", "--release", "--",
+           str(sends), str(FETCHES), str(THREADS), str(USERS), str(MAPS)]
+    result = subprocess.run(cmd, capture_output=True,
+                            text=True, cwd=SPARTA_DIR)
+    return result.stdout
+
+
+def baseline_cmd(sends):
+    cmd = ["cargo", "run", "--release", "--",
+           str(sends), str(FETCHES), str(THREADS)]
+    result = subprocess.run(cmd, capture_output=True,
+                            text=True, cwd=BASELINE_DIR)
+    return result.stdout
+
+
+for send in SENDS:
+    print(send)
+
+    with open(SPARTA_FILE, "a") as sparta_file:
+        output = sparta_cmd(send)
+        print("\tsparta:", output)
+        sparta_file.write(output)
+
+    with open(BASELINE_FILE, "a") as baseline_file:
+        output = baseline_cmd(send)
+        print("\tbaseline:", output)
+        baseline_file.write(output)

+ 0 - 0
experiments/thread_scaling.py


+ 0 - 0
experiments/user_scaling.py


+ 0 - 23
omq/Cargo.lock

@@ -1,23 +0,0 @@
-# This file is automatically @generated by Cargo.
-# It is not intended for manual editing.
-version = 3
-
-[[package]]
-name = "cc"
-version = "1.0.98"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "41c270e7540d725e65ac7f1b212ac8ce349719624d7bcff99f8e2e488e8cf03f"
-
-[[package]]
-name = "omq"
-version = "0.1.0"
-dependencies = [
- "otils",
-]
-
-[[package]]
-name = "otils"
-version = "0.1.0"
-dependencies = [
- "cc",
-]

+ 0 - 7
omq/Cargo.toml

@@ -1,7 +0,0 @@
-[package]
-name = "omq"
-version = "0.1.0"
-edition = "2021"
-
-[dependencies]
-otils = { path = "../otils" }

+ 1 - 1
otils

@@ -1 +1 @@
-Subproject commit 70bf6686dc29da3966727847499480d2986fa33e
+Subproject commit 2b0a0bc57376e658253f01274e98e270cc8452e1

+ 226 - 6
sparta/Cargo.lock

@@ -2,6 +2,55 @@
 # It is not intended for manual editing.
 version = 3
 
+[[package]]
+name = "anstream"
+version = "0.6.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b"
+dependencies = [
+ "anstyle",
+ "anstyle-parse",
+ "anstyle-query",
+ "anstyle-wincon",
+ "colorchoice",
+ "is_terminal_polyfill",
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle"
+version = "1.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b"
+
+[[package]]
+name = "anstyle-parse"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4"
+dependencies = [
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle-query"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5"
+dependencies = [
+ "windows-sys",
+]
+
+[[package]]
+name = "anstyle-wincon"
+version = "3.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19"
+dependencies = [
+ "anstyle",
+ "windows-sys",
+]
+
 [[package]]
 name = "arrayref"
 version = "0.3.7"
@@ -39,6 +88,52 @@ version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 
+[[package]]
+name = "clap"
+version = "4.5.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0"
+dependencies = [
+ "clap_builder",
+ "clap_derive",
+]
+
+[[package]]
+name = "clap_builder"
+version = "4.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4"
+dependencies = [
+ "anstream",
+ "anstyle",
+ "clap_lex",
+ "strsim",
+]
+
+[[package]]
+name = "clap_derive"
+version = "4.5.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64"
+dependencies = [
+ "heck",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "clap_lex"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce"
+
+[[package]]
+name = "colorchoice"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422"
+
 [[package]]
 name = "constant_time_eq"
 version = "0.3.0"
@@ -52,11 +147,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9dfa3c0fd35278e839805680f4c2f673ca71eb91068115b4a611e71429bc0c46"
 
 [[package]]
-name = "omq"
-version = "0.1.0"
-dependencies = [
- "otils",
-]
+name = "heck"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
+
+[[package]]
+name = "is_terminal_polyfill"
+version = "1.70.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800"
 
 [[package]]
 name = "otils"
@@ -65,12 +165,132 @@ dependencies = [
  "cc",
 ]
 
+[[package]]
+name = "proc-macro2"
+version = "1.0.84"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec96c6a92621310b51366f1e28d05ef11489516e93be030060e5fc12024a49d6"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.36"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
+dependencies = [
+ "proc-macro2",
+]
+
 [[package]]
 name = "sparta"
 version = "0.1.0"
 dependencies = [
  "blake3",
+ "clap",
  "fastapprox",
- "omq",
  "otils",
 ]
+
+[[package]]
+name = "strsim"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
+
+[[package]]
+name = "syn"
+version = "2.0.66"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
+
+[[package]]
+name = "utf8parse"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
+
+[[package]]
+name = "windows-sys"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
+dependencies = [
+ "windows-targets",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
+dependencies = [
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_gnullvm",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670"
+
+[[package]]
+name = "windows_i686_gnullvm"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"

+ 4 - 1
sparta/Cargo.toml

@@ -4,12 +4,15 @@ version = "0.1.0"
 edition = "2021"
 
 [dependencies]
-omq = { path = "../omq" }
 otils = { path = "../otils" }
 blake3 = "1.5.1"
 fastapprox = "0.3.1"
+clap = { version = "4.5.4", features = ["derive"] }
 
 [package.metadata.fortanix-sgx]
 stack-size=0x400000
 heap-size=0x100000000
 threads=9
+
+[profile.release]
+# debug = true

+ 14 - 10
sparta/makefile

@@ -1,24 +1,28 @@
+NAME = sparta
+BUILD_DIR = target/x86_64-fortanix-unknown-sgx/release
+KEY = private.pem
+
+BINARY = $(BUILD_DIR)/$(NAME)
+TARGET = $(BUILD_DIR)/$(NAME).sgxs
+SIGNATURE = $(BUILD_DIR)/$(NAME).sig
+
 HEAP_SIZE = 0x100000000
 STACK_SIZE = 0x400000
 MAX_THREADS = 9
 
-BUILD_DIR = target/x86_64-fortanix-unknown-sgx/release
-
-BINARY = $(BUILD_DIR)/sparta
-TARGET = $(BUILD_DIR)/sparta.sgxs
-SIGNATURE = $(BUILD_DIR)/sparta.sig
-
-.PHONY: clean run
+.PHONY: build run clean
 
 $(TARGET): $(BINARY)
 	ftxsgx-elf2sgxs -o $(TARGET) $(BINARY) --heap-size $(HEAP_SIZE) --stack-size $(STACK_SIZE) --threads $(MAX_THREADS)
-	sgxs-sign --key private.pem $(TARGET) $(SIGNATURE)
+	sgxs-sign --key $(KEY) $(TARGET) $(SIGNATURE)
+
+$(BINARY): build
 
-$(BINARY):
+build:
 	cargo build --release
 
 run: $(TARGET)
-	ftxsgx-runner $(TARGET) 5 3 3 8 4
+	ftxsgx-runner $(TARGET) --help
 
 clean:
 	rm -rf $(BUILD_DIR)

+ 0 - 3
sparta/run_experiment.sh

@@ -1,3 +0,0 @@
-#! /bin/bash
-
-ftxsgx-runner target/x86_64-fortanix-unknown-sgx/release/sparta.sgxs $@

+ 61 - 45
sparta/src/load_balancer.rs

@@ -2,22 +2,10 @@ use crate::omap::ObliviousMap;
 pub use crate::record::{IndexRecord, Record, RecordType, SubmapRecord};
 use fastapprox::fast;
 use otils::{self, ObliviousOps};
-use std::{cmp, f64::consts::E, thread};
+use std::{cmp, f64::consts::E, thread, time::UNIX_EPOCH};
 
 const LAMBDA: usize = 128;
 
-// pub struct BalanceRecord(Record);
-
-// impl BalanceRecord {}
-
-// impl PartialEq for BalanceRecord {
-//     fn eq(&self, other: &Self) -> bool {}
-// }
-
-// impl PartialOrd for BalanceRecord {
-//     fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {}
-// }
-
 pub struct LoadBalancer {
     num_users: i64,
     num_threads: usize,
@@ -33,15 +21,14 @@ impl LoadBalancer {
         user_store.reserve(num_users as usize);
         user_store.extend((0..num_users).map(|i| IndexRecord::new(i, RecordType::User)));
 
-        let mut submaps = Vec::new();
-        submaps.reserve(num_submaps as usize);
+        let mut submaps = Vec::with_capacity(num_submaps as usize);
         submaps.extend(
             (0..num_submaps).map(|_| ObliviousMap::new(num_threads / num_submaps as usize)),
         );
 
         LoadBalancer {
             num_users,
-            num_threads: num_threads / num_submaps,
+            num_threads,
             num_submaps,
             user_store,
             submaps,
@@ -82,7 +69,8 @@ impl LoadBalancer {
         submap_size: usize,
         is_send: bool,
     ) -> Vec<SubmapRecord> {
-        let requests = requests.into_iter().map(|r| SubmapRecord(r.0)).collect();
+        let requests: Vec<SubmapRecord> = requests.into_iter().map(|r| SubmapRecord(r.0)).collect();
+
         let mut requests = self.pad_for_submap(requests, submap_size, is_send);
 
         requests = otils::sort(requests, self.num_threads); // sort by omap, then by dummy
@@ -102,6 +90,7 @@ impl LoadBalancer {
         }
 
         otils::compact(&mut requests[..], |r| r.0.mark == 1, self.num_threads);
+        requests.truncate(self.num_submaps * submap_size);
         requests
     }
 
@@ -145,7 +134,7 @@ impl LoadBalancer {
             |r| r.is_request(),
             self.num_threads,
         );
-        let requests = self.user_store[0..num_requests].to_vec();
+        let requests = self.user_store.drain(0..num_requests).collect();
 
         otils::compact(
             &mut self.user_store[..],
@@ -172,24 +161,21 @@ impl LoadBalancer {
             .collect();
 
         let mut remaining_submaps = &mut self.submaps[..];
-        let mut remaining_requests = &mut requests[..self.num_submaps * submap_size];
 
         thread::scope(|s| {
             for _ in 0..self.num_submaps - 1 {
                 let (submap, rest_submaps) = remaining_submaps.split_at_mut(1);
                 remaining_submaps = rest_submaps;
 
-                let (requests, rest_requests) = remaining_requests.split_at_mut(submap_size);
-                remaining_requests = rest_requests;
-                s.spawn(|| submap[0].batch_send(requests.to_vec()));
+                let batch = requests.drain(0..submap_size).collect();
+                s.spawn(|| submap[0].batch_send(batch));
             }
 
             let (submap, rest_submaps) = remaining_submaps.split_at_mut(1);
             remaining_submaps = rest_submaps;
 
-            let (requests, rest_requests) = remaining_requests.split_at_mut(submap_size);
-            remaining_requests = rest_requests;
-            submap[0].batch_send(requests.to_vec());
+            let batch = requests.drain(0..submap_size).collect();
+            submap[0].batch_send(batch);
         });
 
         // parallelize
@@ -241,7 +227,7 @@ impl LoadBalancer {
             |r| r.is_request(),
             self.num_threads,
         );
-        let deliver = self.user_store[0..num_requests].to_vec();
+        let deliver = self.user_store.drain(0..num_requests).collect();
 
         otils::compact(
             &mut self.user_store[..],
@@ -262,52 +248,82 @@ impl LoadBalancer {
             .iter()
             .fold(0, |acc, fetch| acc + fetch.data as usize);
         let fetches = fetches.into_iter().map(|r| IndexRecord(r)).collect();
+
+        // let start = std::time::SystemTime::now()
+        //     .duration_since(UNIX_EPOCH)
+        //     .unwrap()
+        //     .as_nanos();
         let requests = self.get_fetch_indices(fetches, num_requests);
+        // let end = std::time::SystemTime::now()
+        //     .duration_since(UNIX_EPOCH)
+        //     .unwrap()
+        //     .as_nanos();
+        // println!("fetch idx {}: {}", requests.len(), end - start);
 
         let submap_size = self.pad_size(requests.len() as f64);
+
+        // let start = std::time::SystemTime::now()
+        //     .duration_since(UNIX_EPOCH)
+        //     .unwrap()
+        //     .as_nanos();
         let mut requests: Vec<Record> = self
             .get_submap_requests(requests, submap_size, false)
             .into_iter()
             .map(|r| r.0)
             .collect();
-
-        let mut responses: Vec<IndexRecord> = Vec::with_capacity(submap_size * self.num_submaps);
-        (0..submap_size * self.num_submaps)
-            .for_each(|_| responses.push(IndexRecord::new(0, RecordType::Dummy)));
+        // let end = std::time::SystemTime::now()
+        //     .duration_since(UNIX_EPOCH)
+        //     .unwrap()
+        //     .as_nanos();
+        // println!("submap requests {}: {}", requests.len(), end - start);
 
         let mut remaining_submaps = &mut self.submaps[..];
-        let mut remaining_requests = &mut requests[..self.num_submaps * submap_size];
-        let mut remaining_responses = &mut responses[..];
+        let mut responses: Vec<IndexRecord> = Vec::with_capacity(submap_size * self.num_submaps);
 
+        // let start = std::time::SystemTime::now()
+        //     .duration_since(UNIX_EPOCH)
+        //     .unwrap()
+        //     .as_nanos();
         thread::scope(|s| {
+            let mut handles = Vec::new();
             for _ in 0..self.num_submaps - 1 {
                 let (submap, rest_submaps) = remaining_submaps.split_at_mut(1);
                 remaining_submaps = rest_submaps;
-                // println!("submaps: {}", remaining_submaps.len());
+                let batch = requests.drain(0..submap_size).collect();
 
-                let (batch, rest_requests) = remaining_requests.split_at_mut(submap_size);
-                remaining_requests = rest_requests;
-                // println!("");
-
-                let (responses, rest_responses) = remaining_responses.split_at_mut(submap_size);
-                remaining_responses = rest_responses;
-                s.spawn(|| submap[0].batch_fetch(batch.to_vec(), responses));
+                handles.push(s.spawn(|| submap[0].batch_fetch(batch)));
             }
 
             let (submap, rest_submaps) = remaining_submaps.split_at_mut(1);
             remaining_submaps = rest_submaps;
+            let batch = requests.drain(0..submap_size).collect();
 
-            let (batch, rest_requests) = remaining_requests.split_at_mut(submap_size);
-            remaining_requests = rest_requests;
+            let response = submap[0].batch_fetch(batch);
 
-            let (responses, rest_responses) = remaining_responses.split_at_mut(submap_size);
-            remaining_responses = rest_responses;
-            submap[0].batch_fetch(batch.to_vec(), responses);
+            responses.extend(response);
+            for handle in handles.into_iter() {
+                responses.extend(handle.join().unwrap());
+            }
         });
+        // let end = std::time::SystemTime::now()
+        //     .duration_since(UNIX_EPOCH)
+        //     .unwrap()
+        //     .as_nanos();
+        // println!("submap response {}: {}", responses.len(), end - start);
 
         // this only really needs to be a shuffle
+        // let start = std::time::SystemTime::now()
+        //     .duration_since(UNIX_EPOCH)
+        //     .unwrap()
+        //     .as_nanos();
         responses = otils::sort(responses, self.num_threads);
         otils::compact(&mut responses, |r| r.0.is_send(), self.num_threads);
+        // let end = std::time::SystemTime::now()
+        //     .duration_since(UNIX_EPOCH)
+        //     .unwrap()
+        //     .as_nanos();
+        // println!("final: {}", end - start);
+
         responses.drain(0..num_requests).map(|r| r.0).collect()
     }
 }

+ 40 - 16
sparta/src/main.rs

@@ -2,33 +2,56 @@ mod load_balancer;
 mod omap;
 mod record;
 
-use std::time::UNIX_EPOCH;
-
+use clap::Parser;
 use load_balancer::LoadBalancer;
 use record::Record;
+use std::time::UNIX_EPOCH;
+
+/// Baseline oblivious sort based multiqueue.
+#[derive(Parser, Debug)]
+#[command(version, about, long_about = None)]
+struct Args {
+    /// Number of send requests to store in the database.
+    sends: usize,
+
+    /// Number of messages to fetch from the database.
+    fetches: u64,
+
+    /// Total number of threads available.
+    threads: usize,
+
+    /// Number of users in the user store.
+    users: usize,
+
+    /// Number of submaps.
+    maps: usize,
+
+    /// Total number of runs.
+    #[arg(short, long, default_value = "1")]
+    runs: usize,
+
+    /// Number of runs before measurements are recorded.
+    #[arg(short, long, default_value = "0")]
+    warmup_runs: usize,
+}
 
 fn main() {
-    let args: Vec<String> = std::env::args().collect();
-    let num_users = args[1].parse::<usize>().unwrap();
-    let num_sends = args[2].parse::<usize>().unwrap();
-    let num_fetches = args[3].parse::<usize>().unwrap();
-    let num_threads = args[4].parse::<usize>().unwrap();
-    let num_maps = args[5].parse::<usize>().unwrap();
-
-    let mut l = LoadBalancer::new(num_users as i64, num_threads, num_maps);
-    let sends: Vec<Record> = (0..num_sends)
-        .map(|x| Record::send(x as i64, x.try_into().unwrap()))
+    let args = Args::parse();
+
+    let mut l = LoadBalancer::new(args.users as i64, args.threads, args.maps);
+    let sends: Vec<Record> = (0..args.sends)
+        .map(|x| Record::send(0 as i64, x.try_into().unwrap()))
         .collect();
 
     l.batch_send(sends);
 
-    let results: Vec<u128> = (0..15)
+    let results: Vec<u128> = (0..(args.runs + args.warmup_runs))
         .map(|_| {
             let start = std::time::SystemTime::now()
                 .duration_since(UNIX_EPOCH)
                 .unwrap()
                 .as_nanos();
-            let _ = l.batch_fetch(vec![Record::fetch(0, num_fetches as u64)]);
+            let _ = l.batch_fetch(vec![Record::fetch(0, args.fetches)]);
             let end = std::time::SystemTime::now()
                 .duration_since(UNIX_EPOCH)
                 .unwrap()
@@ -37,8 +60,9 @@ fn main() {
         })
         .collect();
 
-    for idx in 5..results.len() {
-        print!("{}\t", results[idx]);
+    print!("{}\t", args.sends);
+    for result in results[..].iter() {
+        print!("{}\t", *result as f64 / 1000000000.0);
     }
     println!();
 }

+ 7 - 7
sparta/src/omap.rs

@@ -77,7 +77,7 @@ impl ObliviousMap {
             .extend(requests.into_iter().map(|r| MapRecord(r)));
     }
 
-    pub fn batch_fetch(&mut self, requests: Vec<Record>, response: &mut [IndexRecord]) {
+    pub fn batch_fetch(&mut self, requests: Vec<Record>) -> Vec<IndexRecord> {
         let final_size = self.message_store.len();
         let num_requests = requests.len();
 
@@ -100,12 +100,11 @@ impl ObliviousMap {
             |r| r.should_deliver(),
             self.num_threads,
         );
-
-        for idx in 0..num_requests {
-            response[idx] = IndexRecord(self.message_store[idx].0.clone());
-        }
-
-        self.message_store.drain(0..num_requests);
+        let response = self
+            .message_store
+            .drain(0..num_requests)
+            .map(|r| IndexRecord(r.0))
+            .collect();
 
         otils::compact(
             &mut self.message_store[..],
@@ -113,5 +112,6 @@ impl ObliviousMap {
             self.num_threads,
         );
         self.message_store.truncate(final_size);
+        response
     }
 }

+ 1 - 3
sparta/src/record.rs

@@ -10,7 +10,7 @@ pub enum RecordType {
     Dummy,
 }
 
-#[derive(Debug, Clone)]
+#[derive(Debug)]
 pub struct Record {
     pub uid: i64,
     pub idx: u32,
@@ -23,7 +23,6 @@ pub struct Record {
     pub last_send: u32,
 
     pub data: u64,
-
     pub _dum: [u64; 12],
 }
 
@@ -63,7 +62,6 @@ impl Record {
     }
 }
 
-#[derive(Clone)]
 pub struct IndexRecord(pub Record);
 
 impl IndexRecord {