[CT420]: Finish Assignment 2
This commit is contained in:
@ -1,25 +1,28 @@
|
||||
// Compile code with gcc -o bm1 bm1.c -lrt -Wall -O2
|
||||
// Execute code with sudo ./bm1
|
||||
// Compile code with gcc -o merged merged.c -lrt -Wall -O2
|
||||
// Execute code with sudo ./merged
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <signal.h>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
#include <sched.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h> // Standard I/O functions
|
||||
#include <stdlib.h> // Standard library functions
|
||||
#include <time.h> // Time-related functions
|
||||
#include <signal.h> // Signal handling
|
||||
#include <sys/mman.h> // Memory locking
|
||||
#include <unistd.h> // POSIX standard functions
|
||||
#include <sched.h> // Scheduling policies
|
||||
#include <errno.h> // Error handling
|
||||
#include <string.h> // String manipulation
|
||||
#include <limits.h> // Limits of integral types
|
||||
|
||||
#define ITERATIONS 10000
|
||||
#define NS_PER_SEC 1000000000L
|
||||
// Constants
|
||||
#define ITERATIONS 10000 // Number of benchmark iterations
|
||||
#define NS_PER_SEC 1000000000L // Nanoseconds per second
|
||||
|
||||
timer_t timer_id;
|
||||
volatile sig_atomic_t timer_expired = 0;
|
||||
volatile sig_atomic_t signal_received = 0;
|
||||
struct timespec start, end, sleep_time;
|
||||
// Global Variables
|
||||
timer_t timer_id; // Timer identifier
|
||||
volatile sig_atomic_t timer_expired = 0; // Flag for timer expiration
|
||||
volatile sig_atomic_t signal_received = 0; // Flag for signal reception
|
||||
struct timespec start, end, sleep_time; // Time structures for benchmarking
|
||||
|
||||
// Function to save benchmark results to a CSV file
|
||||
void save_results(const char *filename, long long *data) {
|
||||
FILE *file = fopen(filename, "w");
|
||||
if (!file) {
|
||||
@ -33,16 +36,19 @@ void save_results(const char *filename, long long *data) {
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
// Signal handler for signal-based latency measurement
|
||||
void signal_handler(int signum) {
|
||||
signal_received = 1;
|
||||
clock_gettime(CLOCK_MONOTONIC, &end);
|
||||
signal_received = 1; // Mark signal as received
|
||||
clock_gettime(CLOCK_MONOTONIC, &end); // Capture end time
|
||||
}
|
||||
|
||||
// Timer signal handler
|
||||
void timer_handler(int signum) {
|
||||
timer_expired = 1;
|
||||
clock_gettime(CLOCK_MONOTONIC, &end);
|
||||
timer_expired = 1; // Mark timer as expired
|
||||
clock_gettime(CLOCK_MONOTONIC, &end); // Capture end time
|
||||
}
|
||||
|
||||
// Configures real-time scheduling with FIFO priority
|
||||
void configure_realtime_scheduling() {
|
||||
struct sched_param param;
|
||||
param.sched_priority = sched_get_priority_max(SCHED_FIFO);
|
||||
@ -52,6 +58,7 @@ void configure_realtime_scheduling() {
|
||||
}
|
||||
}
|
||||
|
||||
// Locks memory to prevent paging for real-time performance
|
||||
void lock_memory() {
|
||||
if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1) {
|
||||
perror("mlockall");
|
||||
@ -59,10 +66,11 @@ void lock_memory() {
|
||||
}
|
||||
}
|
||||
|
||||
// Measures jitter of nanosleep function
|
||||
void benchmark_nanosleep() {
|
||||
long long jitter_data[ITERATIONS];
|
||||
sleep_time.tv_sec = 0;
|
||||
sleep_time.tv_nsec = 1000000; // 1 ms
|
||||
sleep_time.tv_nsec = 1000000; // 1 ms sleep
|
||||
|
||||
for (int i = 0; i < ITERATIONS; i++) {
|
||||
clock_gettime(CLOCK_MONOTONIC, &start);
|
||||
@ -74,14 +82,15 @@ void benchmark_nanosleep() {
|
||||
save_results("nanosleep.csv", jitter_data);
|
||||
}
|
||||
|
||||
// Measures latency of sending and handling a signal
|
||||
void benchmark_signal_latency() {
|
||||
long long latency_data[ITERATIONS];
|
||||
signal(SIGUSR1, signal_handler);
|
||||
signal(SIGUSR1, signal_handler); // Register signal handler
|
||||
|
||||
for (int i = 0; i < ITERATIONS; i++) {
|
||||
clock_gettime(CLOCK_MONOTONIC, &start);
|
||||
kill(getpid(), SIGUSR1);
|
||||
while (!signal_received);
|
||||
kill(getpid(), SIGUSR1); // Send signal to itself
|
||||
while (!signal_received); // Wait for signal to be handled
|
||||
|
||||
latency_data[i] = (end.tv_sec - start.tv_sec) * NS_PER_SEC + (end.tv_nsec - start.tv_nsec);
|
||||
signal_received = 0;
|
||||
@ -89,6 +98,7 @@ void benchmark_signal_latency() {
|
||||
save_results("signal_latency.csv", latency_data);
|
||||
}
|
||||
|
||||
// Measures jitter of a real-time timer
|
||||
void benchmark_timer() {
|
||||
long long jitter_data[ITERATIONS];
|
||||
struct sigevent sev;
|
||||
@ -126,12 +136,13 @@ void benchmark_timer() {
|
||||
save_results("timer.csv", jitter_data);
|
||||
}
|
||||
|
||||
// Measures jitter of usleep function
|
||||
void benchmark_usleep() {
|
||||
long long jitter_data[ITERATIONS];
|
||||
|
||||
for (int i = 0; i < ITERATIONS; i++) {
|
||||
clock_gettime(CLOCK_MONOTONIC, &start);
|
||||
usleep(1000); // 1 ms
|
||||
usleep(1000); // Sleep for 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;
|
||||
@ -139,9 +150,10 @@ void benchmark_usleep() {
|
||||
save_results("usleep.csv", jitter_data);
|
||||
}
|
||||
|
||||
// Main function to execute all benchmarks
|
||||
int main() {
|
||||
configure_realtime_scheduling();
|
||||
lock_memory();
|
||||
configure_realtime_scheduling(); // Set high priority scheduling
|
||||
lock_memory(); // Prevent memory paging
|
||||
|
||||
printf("Getting nanosleep benchmark\n");
|
||||
benchmark_nanosleep();
|
||||
|
@ -0,0 +1,73 @@
|
||||
import pandas as pd
|
||||
import matplotlib.pyplot as plt
|
||||
import os
|
||||
import argparse
|
||||
|
||||
parser = argparse.ArgumentParser(description="Plot specified metric from CSV files.")
|
||||
parser.add_argument("metric", choices=["min", "max", "mean", "std"], help="Metric to plot (min, max, mean, std)")
|
||||
args = parser.parse_args()
|
||||
|
||||
metric_to_plot = args.metric.lower()
|
||||
valid_metrics = {"min": "Min", "max": "Max", "mean": "Mean", "std": "Std"}
|
||||
|
||||
csv_files = [
|
||||
("../../data/Locking Enabled/1. Low CPU Load, No Swap/usleep.csv", "Locking Enabled, Low CPU Load, No Swap"),
|
||||
("../../data/Locking Enabled/2. Medium CPU Load, No Swap/usleep.csv", "Locking Enabled, Medium CPU Load, No Swap"),
|
||||
("../../data/Locking Enabled/3. High CPU Load, No Swap/usleep.csv", "Locking Enabled, High CPU Load, No Swap"),
|
||||
("../../data/Locking Enabled/4. Medium CPU Load, Swap/usleep.csv", "Locking Enabled, Medium CPU Load, Swap"),
|
||||
("../../data/Locking Enabled/5. High CPU Load, Swap/usleep.csv", "Locking Enabled, High CPU Load, Swap"),
|
||||
("../../data/Locking Disabled/1. Low CPU Load, No Swap/usleep.csv", "Locking Disabled, Low CPU Load, No Swap"),
|
||||
("../../data/Locking Disabled/2. Medium CPU Load, No Swap/usleep.csv", "Locking Disabled, Medium CPU Load, No Swap"),
|
||||
("../../data/Locking Disabled/3. High CPU Load, No Swap/usleep.csv", "Locking Disabled, High CPU Load, No Swap"),
|
||||
("../../data/Locking Disabled/4. Medium CPU Load, Swap/usleep.csv", "Locking Disabled, Medium CPU Load, Swap"),
|
||||
("../../data/Locking Disabled/5. High CPU Load, Swap/usleep.csv", "Locking Disabled, High CPU Load, Swap")
|
||||
]
|
||||
|
||||
column_name = "Latency/Jitter (ns)"
|
||||
|
||||
stats = {
|
||||
"Metric": [],
|
||||
"Label": [],
|
||||
"Value": []
|
||||
}
|
||||
|
||||
for file, label in csv_files:
|
||||
if os.path.exists(file):
|
||||
df = pd.read_csv(file)
|
||||
|
||||
if column_name not in df.columns:
|
||||
print(f"Warning: Column '{column_name}' not found in {file}. Available columns: {list(df.columns)}")
|
||||
continue
|
||||
|
||||
values = df[column_name].dropna()
|
||||
if values.empty:
|
||||
print(f"Warning: Column '{column_name}' in {file} is empty after removing NaN values.")
|
||||
continue
|
||||
|
||||
stats["Metric"].append(valid_metrics[metric_to_plot])
|
||||
stats["Label"].append(label)
|
||||
if metric_to_plot == "min":
|
||||
stats["Value"].append(values.min())
|
||||
elif metric_to_plot == "max":
|
||||
stats["Value"].append(values.max())
|
||||
elif metric_to_plot == "mean":
|
||||
stats["Value"].append(values.mean())
|
||||
elif metric_to_plot == "std":
|
||||
stats["Value"].append(values.std())
|
||||
else:
|
||||
print(f"Warning: File {file} not found.")
|
||||
|
||||
stats_df = pd.DataFrame(stats)
|
||||
|
||||
if stats_df.empty:
|
||||
print("Error: No valid data found. Ensure the column name is correct and files are properly formatted.")
|
||||
else:
|
||||
fig, ax = plt.subplots(figsize=(16,4))
|
||||
ax.bar(stats_df["Label"], stats_df["Value"], color="black")
|
||||
|
||||
ax.set_xticklabels(stats_df["Label"], rotation=45, ha="right")
|
||||
ax.set_ylabel("Jitter (ns)")
|
||||
ax.set_title(f"{valid_metrics[metric_to_plot]} usleep()")
|
||||
|
||||
plt.tight_layout()
|
||||
plt.show()
|
Reference in New Issue
Block a user