From 3be71b43e43b0b9e2d5bdfde6292584d354a52ff Mon Sep 17 00:00:00 2001 From: Andrew Date: Wed, 19 Mar 2025 09:42:07 +0000 Subject: [PATCH] [CT420]: Assignment 2 move benchmarks --- .../assignment2/code/benchmarks/bm1.c | 104 ++++++++++++ .../assignment2/code/benchmarks/bm2.c | 106 ++++++++++++ .../assignment2/code/benchmarks/merged | Bin 0 -> 17168 bytes .../assignment2/code/benchmarks/merged.c | 159 ++++++++++++++++++ 4 files changed, 369 insertions(+) create mode 100644 year4/semester2/CT420/assignments/assignment2/code/benchmarks/bm1.c create mode 100644 year4/semester2/CT420/assignments/assignment2/code/benchmarks/bm2.c create mode 100755 year4/semester2/CT420/assignments/assignment2/code/benchmarks/merged create mode 100644 year4/semester2/CT420/assignments/assignment2/code/benchmarks/merged.c diff --git a/year4/semester2/CT420/assignments/assignment2/code/benchmarks/bm1.c b/year4/semester2/CT420/assignments/assignment2/code/benchmarks/bm1.c new file mode 100644 index 00000000..768981c2 --- /dev/null +++ b/year4/semester2/CT420/assignments/assignment2/code/benchmarks/bm1.c @@ -0,0 +1,104 @@ +// Compile code with gcc -o bm1 bm1.c -lrt -Wall -O2 +// Execute code with sudo ./bm1 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ITERATIONS 1000 +#define NS_PER_SEC 1000000000L + +volatile sig_atomic_t signal_received = 0; +struct timespec start, end, sleep_time; + +void signal_handler(int signum) { + signal_received = 1; + clock_gettime(CLOCK_MONOTONIC, &end); +} + +void configure_realtime_scheduling() { + struct sched_param param; + param.sched_priority = sched_get_priority_max(SCHED_FIFO); + if (sched_setscheduler(0, SCHED_FIFO, ¶m) == -1) { + perror("sched_setscheduler"); + exit(EXIT_FAILURE); + } +} + +void lock_memory() { + if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1) { + perror("mlockall"); + exit(EXIT_FAILURE); + } +} + +void benchmark_nanosleep() { + // struct timespec start, end, sleep_time; + long long total_jitter = 0; + long long max_jitter = 0; + long long min_jitter = LLONG_MAX; + + sleep_time.tv_sec = 0; + sleep_time.tv_nsec = 1000000; // 1 ms + + for (int i = 0; i < ITERATIONS; i++) { + clock_gettime(CLOCK_MONOTONIC, &start); + nanosleep(&sleep_time, NULL); + clock_gettime(CLOCK_MONOTONIC, &end); + + long long elapsed = (end.tv_sec - start.tv_sec) * NS_PER_SEC + (end.tv_nsec - start.tv_nsec); + long long jitter = elapsed - sleep_time.tv_nsec; + + total_jitter += llabs(jitter); + if (jitter > max_jitter) max_jitter = jitter; + if (jitter < min_jitter) min_jitter = jitter; + } + + printf("Nanosleep Benchmark:\n"); + printf("Average jitter: %lld ns\n", total_jitter / ITERATIONS); + printf("Max jitter: %lld ns\n", max_jitter); + printf("Min jitter: %lld ns\n", min_jitter); +} + +void benchmark_signal_latency() { + long long total_latency = 0; + long long max_latency = 0; + long long min_latency = LLONG_MAX; + + signal(SIGUSR1, signal_handler); + + for (int i = 0; i < ITERATIONS; i++) { + clock_gettime(CLOCK_MONOTONIC, &start); + kill(getpid(), SIGUSR1); + while (!signal_received); + + long long latency = (end.tv_sec - start.tv_sec) * NS_PER_SEC + (end.tv_nsec - start.tv_nsec); + total_latency += latency; + if (latency > max_latency) max_latency = latency; + if (latency < min_latency) min_latency = latency; + + signal_received = 0; + } + + printf("\nSignal Latency Benchmark:\n"); + printf("Average latency: %lld ns\n", total_latency / ITERATIONS); + printf("Max latency: %lld ns\n", max_latency); + printf("Min latency: %lld ns\n", min_latency); +} + +int main() { + configure_realtime_scheduling(); + lock_memory(); + + benchmark_nanosleep(); + benchmark_signal_latency(); + + return 0; +} \ No newline at end of file diff --git a/year4/semester2/CT420/assignments/assignment2/code/benchmarks/bm2.c b/year4/semester2/CT420/assignments/assignment2/code/benchmarks/bm2.c new file mode 100644 index 00000000..7e06f2d7 --- /dev/null +++ b/year4/semester2/CT420/assignments/assignment2/code/benchmarks/bm2.c @@ -0,0 +1,106 @@ +// Compile code with gcc -o bm2 bm2.c -lrt -Wall -O2 +// Execute code with sudo ./bm2 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ITERATIONS 1000 +#define NS_PER_SEC 1000000000L + +timer_t timer_id; +volatile sig_atomic_t timer_expired = 0; +struct timespec start, end; + +void timer_handler(int signum) { + timer_expired = 1; + clock_gettime(CLOCK_MONOTONIC, &end); +} + +void configure_realtime_scheduling() { + struct sched_param param; + param.sched_priority = sched_get_priority_max(SCHED_FIFO); + if (sched_setscheduler(0, SCHED_FIFO, ¶m) == -1) { + perror("sched_setscheduler"); + exit(EXIT_FAILURE); + } +} + +void lock_memory() { + if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1) { + perror("mlockall"); + exit(EXIT_FAILURE); + } +} + +void benchmark_timer() { + long long total_jitter = 0; + long long max_jitter = 0; + long long min_jitter = LLONG_MAX; + + struct sigevent sev; + sev.sigev_notify = SIGEV_SIGNAL; + sev.sigev_signo = SIGRTMIN; + sev.sigev_value.sival_ptr = &timer_id; + + if (timer_create(CLOCK_MONOTONIC, &sev, &timer_id) == -1) { + perror("timer_create"); + exit(EXIT_FAILURE); + } + + struct itimerspec its; + its.it_value.tv_sec = 0; + its.it_value.tv_nsec = 1000000; // 1 ms + its.it_interval = its.it_value; + + signal(SIGRTMIN, timer_handler); + + if (timer_settime(timer_id, 0, &its, NULL) == -1) { + perror("timer_settime"); + exit(EXIT_FAILURE); + } + clock_gettime(CLOCK_MONOTONIC, &start); + for (int i = 0; i < ITERATIONS; i++) { + // while (!timer_expired); + + while (!timer_expired) { + struct timespec ts = {0, 100}; + nanosleep(&ts, NULL); + } + + clock_gettime(CLOCK_MONOTONIC, &end); + + long long elapsed = (end.tv_sec - start.tv_sec) * NS_PER_SEC + (end.tv_nsec - start.tv_nsec); + long long jitter = elapsed - its.it_interval.tv_nsec; + + total_jitter += llabs(jitter); + if (jitter > max_jitter) max_jitter = jitter; + if (jitter < min_jitter) min_jitter = jitter; + + timer_expired = 0; + start = end; + } + + printf("\nTimer Benchmark:\n"); + printf("Average jitter: %lld ns\n", total_jitter / ITERATIONS); + printf("Max jitter: %lld ns\n", max_jitter); + printf("Min jitter: %lld ns\n", min_jitter); + + timer_delete(timer_id); +} + +int main() { + configure_realtime_scheduling(); + lock_memory(); + + benchmark_timer(); + + return 0; +} diff --git a/year4/semester2/CT420/assignments/assignment2/code/benchmarks/merged b/year4/semester2/CT420/assignments/assignment2/code/benchmarks/merged new file mode 100755 index 0000000000000000000000000000000000000000..b3355225f2115c2b7e1287e5b57399bc8c2a9f6a GIT binary patch literal 17168 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 Ku5l +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ITERATIONS 10000 +#define NS_PER_SEC 1000000000L + +timer_t timer_id; +volatile sig_atomic_t timer_expired = 0; +volatile sig_atomic_t signal_received = 0; +struct timespec start, end, sleep_time; + +void save_results(const char *filename, long long *data) { + FILE *file = fopen(filename, "w"); + if (!file) { + perror("fopen"); + exit(EXIT_FAILURE); + } + fprintf(file, "Iteration,Latency/Jitter (ns)\n"); + for (int i = 0; i < ITERATIONS; i++) { + fprintf(file, "%d,%lld\n", i, data[i]); + } + fclose(file); +} + +void signal_handler(int signum) { + signal_received = 1; + clock_gettime(CLOCK_MONOTONIC, &end); +} + +void timer_handler(int signum) { + timer_expired = 1; + clock_gettime(CLOCK_MONOTONIC, &end); +} + +void configure_realtime_scheduling() { + struct sched_param param; + param.sched_priority = sched_get_priority_max(SCHED_FIFO); + if (sched_setscheduler(0, SCHED_FIFO, ¶m) == -1) { + perror("sched_setscheduler"); + exit(EXIT_FAILURE); + } +} + +void lock_memory() { + if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1) { + perror("mlockall"); + exit(EXIT_FAILURE); + } +} + +void benchmark_nanosleep() { + long long jitter_data[ITERATIONS]; + sleep_time.tv_sec = 0; + sleep_time.tv_nsec = 1000000; // 1 ms + + for (int i = 0; i < ITERATIONS; i++) { + clock_gettime(CLOCK_MONOTONIC, &start); + nanosleep(&sleep_time, NULL); + clock_gettime(CLOCK_MONOTONIC, &end); + + jitter_data[i] = ((end.tv_sec - start.tv_sec) * NS_PER_SEC + (end.tv_nsec - start.tv_nsec)) - sleep_time.tv_nsec; + } + save_results("nanosleep.csv", jitter_data); +} + +void benchmark_signal_latency() { + long long latency_data[ITERATIONS]; + signal(SIGUSR1, signal_handler); + + for (int i = 0; i < ITERATIONS; i++) { + clock_gettime(CLOCK_MONOTONIC, &start); + kill(getpid(), SIGUSR1); + while (!signal_received); + + latency_data[i] = (end.tv_sec - start.tv_sec) * NS_PER_SEC + (end.tv_nsec - start.tv_nsec); + signal_received = 0; + } + save_results("signal_latency.csv", latency_data); +} + +void benchmark_timer() { + long long jitter_data[ITERATIONS]; + struct sigevent sev; + sev.sigev_notify = SIGEV_SIGNAL; + sev.sigev_signo = SIGRTMIN; + sev.sigev_value.sival_ptr = &timer_id; + + if (timer_create(CLOCK_MONOTONIC, &sev, &timer_id) == -1) { + perror("timer_create"); + exit(EXIT_FAILURE); + } + + struct itimerspec its; + its.it_value.tv_sec = 0; + its.it_value.tv_nsec = 1000000; // 1 ms + its.it_interval = its.it_value; + signal(SIGRTMIN, timer_handler); + + if (timer_settime(timer_id, 0, &its, NULL) == -1) { + perror("timer_settime"); + exit(EXIT_FAILURE); + } + clock_gettime(CLOCK_MONOTONIC, &start); + for (int i = 0; i < ITERATIONS; i++) { + while (!timer_expired) { + struct timespec ts = {0, 100}; + nanosleep(&ts, NULL); + } + + clock_gettime(CLOCK_MONOTONIC, &end); + jitter_data[i] = ((end.tv_sec - start.tv_sec) * NS_PER_SEC + (end.tv_nsec - start.tv_nsec)) - its.it_interval.tv_nsec; + timer_expired = 0; + start = end; + } + save_results("timer.csv", jitter_data); +} + +void benchmark_usleep() { + long long jitter_data[ITERATIONS]; + + for (int i = 0; i < ITERATIONS; i++) { + clock_gettime(CLOCK_MONOTONIC, &start); + usleep(1000); // 1 ms + clock_gettime(CLOCK_MONOTONIC, &end); + + jitter_data[i] = ((end.tv_sec - start.tv_sec) * NS_PER_SEC + (end.tv_nsec - start.tv_nsec)) - 1000000; + } + save_results("usleep.csv", jitter_data); +} + +int main() { + configure_realtime_scheduling(); + lock_memory(); + + printf("Getting nanosleep benchmark\n"); + benchmark_nanosleep(); + + printf("Getting signal benchmark\n"); + benchmark_signal_latency(); + + printf("Getting timer benchmark\n"); + benchmark_timer(); + + printf("Getting usleep benchmark\n"); + benchmark_usleep(); + + return 0; +}