Skip to content

Measurements Folder Added #164

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 9, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added measurements/CPU/Figure5.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
185 changes: 185 additions & 0 deletions measurements/CPU/client_cpu.graphml
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://www.yworks.com/xml/schema/graphml/1.1/ygraphml.xsd" xmlns:y="http://www.yworks.com/xml/graphml">
<key for="node" id="d6" yfiles.type="nodegraphics"/>
<key for="edge" id="d10" yfiles.type="edgegraphics"/>
<graph edgedefault="directed" id="1751872458057" projectName="client" authorName="saksham">
<node id="89497d28-c120-4d48-aa23-a071261aa603">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="50" width="233" x="487" y="313"/>
<y:Fill color="#ffcc00" opacity="1"/>
<y:BorderStyle color="#000" width="1"/>
<y:NodeLabel>B:funbody_cpu.py</y:NodeLabel>
<y:Shape type="rectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="2196c146-180c-4d14-bbaa-340f76e14809">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="50" width="100" x="107" y="102"/>
<y:Fill color="#ffcc00" opacity="1"/>
<y:BorderStyle color="#000" width="1"/>
<y:NodeLabel>OUT:</y:NodeLabel>
<y:Shape type="rectangle"/>
</y:ShapeNode>
</data>
</node>
<edge id="0" source="89497d28-c120-4d48-aa23-a071261aa603" target="2196c146-180c-4d14-bbaa-340f76e14809">
<data key="d10">
<y:GenericEdge configuration="com.yworks.bpmn.Connection">
<y:LineStyle width="1" type="solid"/>
<y:Arrows source="none" target="delta"/>
<y:EdgeLabel>0x2306_U1</y:EdgeLabel>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0">
<y:Point x="274.4881516587678" y="195.00000000000006"/>
</y:Path>
</y:GenericEdge>
</data>
</edge>
<actionHistory>
<tid>1751825758771</tid>
<inverse>
<actionName>DEL_NODE</actionName>
<parameters>WyI4OTQ5N2QyOC1jMTIwLTRkNDgtYWEyMy1hMDcxMjYxYWE2MDMiXQ==</parameters>
</inverse>
<equivalent>
<actionName>ADD_NODE</actionName>
<parameters>WyJCOmZ1bmJvZHlfdGhyb3VnaHB1dF90ZXN0LnB5Iix7IndpZHRoIjoyMzMsImhlaWdodCI6NTAsInNoYXBlIjoicmVjdGFuZ2xlIiwib3BhY2l0eSI6MSwiYmFja2dyb3VuZENvbG9yIjoiI2ZmY2MwMCIsImJvcmRlckNvbG9yIjoiIzAwMCIsImJvcmRlcldpZHRoIjoxfSwib3JkaW4iLHsieCI6NDg3LCJ5IjozMTN9LHt9LCI4OTQ5N2QyOC1jMTIwLTRkNDgtYWEyMy1hMDcxMjYxYWE2MDMiXQ==</parameters>
</equivalent>
<hash>e425a002ed1453f66a4fb1dad3ad2923</hash>
</actionHistory>
<actionHistory>
<tid>1751825761336</tid>
<inverse>
<actionName>SET_POS</actionName>
<parameters>WyI4OTQ5N2QyOC1jMTIwLTRkNDgtYWEyMy1hMDcxMjYxYWE2MDMiLHsieCI6MTAwLCJ5IjoxMDB9LHsieCI6NDg3LCJ5IjozMTN9XQ==</parameters>
</inverse>
<equivalent>
<actionName>SET_POS</actionName>
<parameters>WyI4OTQ5N2QyOC1jMTIwLTRkNDgtYWEyMy1hMDcxMjYxYWE2MDMiLHsieCI6NDg3LCJ5IjozMTN9LHsieCI6MTAwLCJ5IjoxMDB9XQ==</parameters>
</equivalent>
<hash>d7861c7337345a2010806e89311d85bf</hash>
</actionHistory>
<actionHistory>
<tid>1751825767651</tid>
<inverse>
<actionName>DEL_NODE</actionName>
<parameters>WyIyMTk2YzE0Ni0xODBjLTRkMTQtYmJhYS0zNDBmNzZlMTQ4MDkiXQ==</parameters>
</inverse>
<equivalent>
<actionName>ADD_NODE</actionName>
<parameters>WyJPVVQ6Iix7IndpZHRoIjoxMDAsImhlaWdodCI6NTAsInNoYXBlIjoicmVjdGFuZ2xlIiwib3BhY2l0eSI6MSwiYmFja2dyb3VuZENvbG9yIjoiI2ZmY2MwMCIsImJvcmRlckNvbG9yIjoiIzAwMCIsImJvcmRlcldpZHRoIjoxfSwib3JkaW4iLHsieCI6MTA3LCJ5IjoxMDJ9LHt9LCIyMTk2YzE0Ni0xODBjLTRkMTQtYmJhYS0zNDBmNzZlMTQ4MDkiXQ==</parameters>
</equivalent>
<hash>19b85e105d5758f18c55915fbce84663</hash>
</actionHistory>
<actionHistory>
<tid>1751825770936</tid>
<inverse>
<actionName>SET_POS</actionName>
<parameters>WyIyMTk2YzE0Ni0xODBjLTRkMTQtYmJhYS0zNDBmNzZlMTQ4MDkiLHsieCI6MTAwLCJ5IjoxMDB9LHsieCI6MTA3LCJ5IjoxMDJ9XQ==</parameters>
</inverse>
<equivalent>
<actionName>SET_POS</actionName>
<parameters>WyIyMTk2YzE0Ni0xODBjLTRkMTQtYmJhYS0zNDBmNzZlMTQ4MDkiLHsieCI6MTA3LCJ5IjoxMDJ9LHsieCI6MTAwLCJ5IjoxMDB9XQ==</parameters>
</equivalent>
<hash>03b8818572c5800d88c583073a1ef559</hash>
</actionHistory>
<actionHistory>
<tid>1751825773370</tid>
<inverse>
<actionName>DEL_EDGE</actionName>
<parameters>WyI5MWE2MzJkYS0wZDgwLTQ3NzctYmQyZi05MDhiMGY1ZDgwOGQiXQ==</parameters>
</inverse>
<equivalent>
<actionName>ADD_EDGE</actionName>
<parameters>W3sic291cmNlSUQiOiI4OTQ5N2QyOC1jMTIwLTRkNDgtYWEyMy1hMDcxMjYxYWE2MDMiLCJ0YXJnZXRJRCI6IjIxOTZjMTQ2LTE4MGMtNGQxNC1iYmFhLTM0MGY3NmUxNDgwOSIsImxhYmVsIjoiMHgyMzAwX1UxIiwic3R5bGUiOnsidGhpY2tuZXNzIjoxLCJiYWNrZ3JvdW5kQ29sb3IiOm51bGwsInNoYXBlIjoic29saWQifSwiaWQiOiI5MWE2MzJkYS0wZDgwLTQ3NzctYmQyZi05MDhiMGY1ZDgwOGQifV0=</parameters>
</equivalent>
<hash>1dd8b4edaeed282d75d1daeb3195b728</hash>
</actionHistory>
<actionHistory>
<tid>1751826367735</tid>
<inverse>
<actionName>UPDATE_EDGE</actionName>
<parameters>WyI3NmRjNzIxNi0wMzE2LTQ2OWQtOWFhNy1lN2Q3NDAwNGNkOTUiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwMF9VMSIsdHJ1ZV0=</parameters>
</inverse>
<equivalent>
<actionName>UPDATE_EDGE</actionName>
<parameters>WyI3NmRjNzIxNi0wMzE2LTQ2OWQtOWFhNy1lN2Q3NDAwNGNkOTUiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwMV9VMSIsdHJ1ZV0=</parameters>
</equivalent>
<hash>ca298c11df338ea36bce176af0fe3b69</hash>
</actionHistory>
<actionHistory>
<tid>1751826515156</tid>
<inverse>
<actionName>UPDATE_EDGE</actionName>
<parameters>WyI3NmRjNzIxNi0wMzE2LTQ2OWQtOWFhNy1lN2Q3NDAwNGNkOTUiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwMV9VMSIsdHJ1ZV0=</parameters>
</inverse>
<equivalent>
<actionName>UPDATE_EDGE</actionName>
<parameters>WyI3NmRjNzIxNi0wMzE2LTQ2OWQtOWFhNy1lN2Q3NDAwNGNkOTUiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwMl9VMSIsdHJ1ZV0=</parameters>
</equivalent>
<hash>c6ee9fdcb90f48bc1de9bdc44b7da91f</hash>
</actionHistory>
<actionHistory>
<tid>1751826596605</tid>
<inverse>
<actionName>UPDATE_EDGE</actionName>
<parameters>WyI3NmRjNzIxNi0wMzE2LTQ2OWQtOWFhNy1lN2Q3NDAwNGNkOTUiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwMl9VMSIsdHJ1ZV0=</parameters>
</inverse>
<equivalent>
<actionName>UPDATE_EDGE</actionName>
<parameters>WyI3NmRjNzIxNi0wMzE2LTQ2OWQtOWFhNy1lN2Q3NDAwNGNkOTUiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwM19VMSIsdHJ1ZV0=</parameters>
</equivalent>
<hash>b79566da6d5ea6c2cf2cbb618da677d2</hash>
</actionHistory>
<actionHistory>
<tid>1751826901740</tid>
<inverse>
<actionName>UPDATE_EDGE</actionName>
<parameters>WyI3NmRjNzIxNi0wMzE2LTQ2OWQtOWFhNy1lN2Q3NDAwNGNkOTUiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwM19VMSIsdHJ1ZV0=</parameters>
</inverse>
<equivalent>
<actionName>UPDATE_EDGE</actionName>
<parameters>WyI3NmRjNzIxNi0wMzE2LTQ2OWQtOWFhNy1lN2Q3NDAwNGNkOTUiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwNF9VMSIsdHJ1ZV0=</parameters>
</equivalent>
<hash>ba871dc0f4bc75adee32e34c87854508</hash>
</actionHistory>
<actionHistory>
<tid>1751827730897</tid>
<inverse>
<actionName>UPDATE_EDGE</actionName>
<parameters>WyI3NmRjNzIxNi0wMzE2LTQ2OWQtOWFhNy1lN2Q3NDAwNGNkOTUiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwNF9VMSIsdHJ1ZV0=</parameters>
</inverse>
<equivalent>
<actionName>UPDATE_EDGE</actionName>
<parameters>WyI3NmRjNzIxNi0wMzE2LTQ2OWQtOWFhNy1lN2Q3NDAwNGNkOTUiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwNV9VMSIsdHJ1ZV0=</parameters>
</equivalent>
<hash>8bb2b4d5cd9d445722b307d6bdb3d9fd</hash>
</actionHistory>
<actionHistory>
<tid>1751828973865</tid>
<inverse>
<actionName>UPDATE_EDGE</actionName>
<parameters>WyI3NmRjNzIxNi0wMzE2LTQ2OWQtOWFhNy1lN2Q3NDAwNGNkOTUiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwNV9VMSIsdHJ1ZV0=</parameters>
</inverse>
<equivalent>
<actionName>UPDATE_EDGE</actionName>
<parameters>WyI3NmRjNzIxNi0wMzE2LTQ2OWQtOWFhNy1lN2Q3NDAwNGNkOTUiLHsidGhpY2tuZXNzIjoxLCJzaGFwZSI6InNvbGlkIn0sIjB4MjMwNl9VMSIsdHJ1ZV0=</parameters>
</equivalent>
<hash>3609737de0e0d000c3d43a620f592090</hash>
</actionHistory>
<actionHistory>
<tid>1751872486908</tid>
<inverse>
<actionName>UPDATE_NODE</actionName>
<parameters>WyI4OTQ5N2QyOC1jMTIwLTRkNDgtYWEyMy1hMDcxMjYxYWE2MDMiLHsid2lkdGgiOjIzMywiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJCOmZ1bmJvZHlfdGhyb3VnaHB1dF90ZXN0LnB5Iix0cnVlXQ==</parameters>
</inverse>
<equivalent>
<actionName>UPDATE_NODE</actionName>
<parameters>WyI4OTQ5N2QyOC1jMTIwLTRkNDgtYWEyMy1hMDcxMjYxYWE2MDMiLHsid2lkdGgiOjIzMywiaGVpZ2h0Ijo1MCwib3BhY2l0eSI6MSwic2hhcGUiOiJyZWN0YW5nbGUiLCJiYWNrZ3JvdW5kQ29sb3IiOiIjZmZjYzAwIiwiYm9yZGVyQ29sb3IiOiIjMDAwIiwiYm9yZGVyV2lkdGgiOjF9LCJCOmZ1bmJvZHlfY3B1LnB5Iix0cnVlXQ==</parameters>
</equivalent>
<hash>a0691587adb56f1c913b278379ea8cd5</hash>
</actionHistory>
</graph>
</graphml>
88 changes: 88 additions & 0 deletions measurements/CPU/funbody_cpu.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# funbody_throughput_test.py (MODIFIED FOR RESOURCE MONITORING & CORRECTED)
import time
import concore
import os
import json
import threading
import psutil
import csv

# --- MONITORING FUNCTION (to be run in a separate thread) ---
def monitor_resources(stop_event, output_list):
"""Monitors this script's CPU and memory usage."""
process = psutil.Process(os.getpid())
while not stop_event.is_set():
cpu_percent = process.cpu_percent(interval=0.5)
memory_mb = process.memory_info().rss / (1024 * 1024)
output_list.append({'cpu_percent': cpu_percent, 'memory_mb': memory_mb})

print("funbody (Receiver) using ZMQ REP socket for Throughput & Resource Test.")

TEST_DURATION = 10
message_count = 0
test_started = False
resource_records = []
start_time = 0

# --- Start Monitoring ---
stop_monitoring = threading.Event()
monitor_thread = threading.Thread(target=monitor_resources, args=(stop_monitoring, resource_records))
monitor_thread.start()

# --- Main Throughput Test Logic (CORRECTED) ---
concore.init_zmq_port(
port_name=PORT_NAME_B_OUT,
port_type="bind",
address="tcp://0.0.0.0:" + PORT_B_OUT, # Bind to all interfaces on the specified port
socket_type_str="REP"
)

print(f"Receiver waiting for messages on port {PORT_B_OUT}...")
while True:
# Wait for a message
message_str = concore.read(PORT_NAME_B_OUT, "stream", "{}")

# Send an acknowledgment immediately after receiving
concore.write(PORT_NAME_B_OUT, "reply", "{}") # ADDED: Send acknowledgment

if message_str is None:
continue # Or break, depending on desired behavior on timeout

try:
# Since concore.read now handles JSON parsing, this might not be needed
# but we keep it for validation of the message structure.
message_dict = message_str if isinstance(message_str, dict) else json.loads(message_str)
except (json.JSONDecodeError, TypeError):
continue

if isinstance(message_dict, dict) and 'type' in message_dict:
if message_dict['type'] == 'control':
if message_dict['value'] == 'START' and not test_started:
print("START signal received.")
test_started = True
start_time = time.perf_counter()
elif message_dict['value'] == 'STOP' and test_started:
print("STOP signal received.")
break # Exit the loop to end the test
elif message_dict['type'] == 'data' and test_started:
message_count += 1

# --- Stop Monitoring and Save Results ---
stop_monitoring.set()
monitor_thread.join()
concore.terminate_zmq()

if message_count > 0:
end_time = time.perf_counter()
duration = end_time - start_time
throughput = message_count / duration if duration > 0 else 0
print(f"\n--- TEST COMPLETE ---")
print(f"Received {message_count} messages in {duration:.2f} seconds.")
print(f"THROUGHPUT RESULT: {throughput:.2f} messages/second")

if resource_records:
with open('receiver_usage.csv', 'w', newline='') as f:
writer = csv.DictWriter(f, fieldnames=['cpu_percent', 'memory_mb'])
writer.writeheader()
writer.writerows(resource_records)
print("Receiver resource usage saved to receiver_usage.csv")
74 changes: 74 additions & 0 deletions measurements/CPU/funcall_cpu.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# funcall_throughput_test.py (MODIFIED FOR RESOURCE MONITORING & CORRECTED)
import time
import concore
import os
import json
import threading
import psutil
import csv

# --- MONITORING FUNCTION (to be run in a separate thread) ---
def monitor_resources(stop_event, output_list):
"""Monitors this script's CPU and memory usage."""
process = psutil.Process(os.getpid())
while not stop_event.is_set():
# Get CPU (as a percentage) and Memory (RSS in MB)
cpu_percent = process.cpu_percent(interval=0.5)
memory_mb = process.memory_info().rss / (1024 * 1024)
output_list.append({'cpu_percent': cpu_percent, 'memory_mb': memory_mb})

print("funcall (Sender) using ZMQ REQ socket for Throughput & Resource Test.")

TEST_DURATION = 10
message_count = 0
resource_records = []

# --- Start Monitoring ---
stop_monitoring = threading.Event()
monitor_thread = threading.Thread(target=monitor_resources, args=(stop_monitoring, resource_records))
monitor_thread.start()

# --- Main Throughput Test Logic (CORRECTED) ---
concore.init_zmq_port(
port_name=PORT_NAME_IN_A,
port_type="connect",
address="tcp://192.168.0.109:" + PORT_IN_A, # Use 127.0.0.1 for local, or the receiver's IP
socket_type_str="REQ"
)
print(f"Sender starting. Will send data for {TEST_DURATION} seconds.")

# Send START signal and wait for reply
start_signal = json.dumps({"type": "control", "value": "START"})
concore.write(PORT_NAME_IN_A, "stream", start_signal)
concore.read(PORT_NAME_IN_A, "reply", "{}") # ADDED: Wait for acknowledgment

time.sleep(1)
start_time = time.perf_counter()

# Loop for the test duration
while (time.perf_counter() - start_time) < TEST_DURATION:
data_message = json.dumps({"type": "data", "value": message_count})
concore.write(PORT_NAME_IN_A, "stream", data_message)
concore.read(PORT_NAME_IN_A, "reply", "{}") # ADDED: Wait for acknowledgment
message_count += 1

time.sleep(1)

# Send STOP signal and wait for reply
stop_signal = json.dumps({"type": "control", "value": "STOP"})
concore.write(PORT_NAME_IN_A, "stream", stop_signal)
concore.read(PORT_NAME_IN_A, "reply", "{}") # ADDED: Wait for acknowledgment

print(f"Sender finished. Sent approximately {message_count} messages.")

# --- Stop Monitoring and Save Results ---
stop_monitoring.set()
monitor_thread.join()
concore.terminate_zmq()

if resource_records:
with open('sender_usage.csv', 'w', newline='') as f:
writer = csv.DictWriter(f, fieldnames=['cpu_percent', 'memory_mb'])
writer.writeheader()
writer.writerows(resource_records)
print("Sender resource usage saved to sender_usage.csv")
42 changes: 42 additions & 0 deletions measurements/CPU/plot_fig5.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt

# Load all data and calculate averages
try:
avg_cpu_sender_zmq = pd.read_csv('sender_usage.csv')['cpu_percent'].mean()
avg_mem_sender_zmq = pd.read_csv('sender_usage.csv')['memory_mb'].mean()

# In a real test, you would also measure the receiver. For simplicity, we plot sender.
# avg_cpu_receiver_zmq = pd.read_csv('receiver_zmq_usage.csv')['cpu_percent'].mean()
# avg_mem_receiver_zmq = pd.read_csv('receiver_zmq_usage.csv')['memory_mb'].mean()

# Create placeholder data for Mediator until you run the test
avg_cpu_sender_mediator = 25.5 # Example value
avg_mem_sender_mediator = 60.2 # Example value

except FileNotFoundError:
print("One or more CSV files not found. Using placeholder data.")
# Placeholder data for plotting if you haven't run the experiment yet
avg_cpu_sender_zmq, avg_mem_sender_zmq = 15.0, 45.0
avg_cpu_sender_mediator, avg_mem_sender_mediator = 25.5, 60.2

# Prepare data for plotting
data = {
'Protocol': ['Mediator', 'ZeroMQ', 'Mediator', 'ZeroMQ'],
'Metric': ['CPU Usage (%)', 'CPU Usage (%)', 'Memory Usage (MB)', 'Memory Usage (MB)'],
'Value': [avg_cpu_sender_mediator, avg_cpu_sender_zmq, avg_mem_sender_mediator, avg_mem_sender_zmq]
}
df_plot = pd.DataFrame(data)

# Create the grouped bar chart
plt.figure(figsize=(10, 7))
sns.barplot(x='Metric', y='Value', hue='Protocol', data=df_plot, palette={'Mediator': '#F44336', 'ZeroMQ': '#4CAF50'})

plt.title('Figure 5: Resource Utilization During Throughput Test (Sender)', fontsize=16)
plt.xlabel('Performance Metric', fontsize=12)
plt.ylabel('Average Usage', fontsize=12)
plt.legend(title='Protocol')
plt.grid(axis='y', linestyle='--', alpha=0.7)

plt.show()
Loading