png to svg

This commit is contained in:
Domingo Dirutigliano
2025-06-16 22:44:23 +02:00
parent c8398dbd39
commit d019e504fd
14 changed files with 11352 additions and 76 deletions

View File

@@ -94,7 +94,7 @@ Firegex 2.5.0 changes the way the threads are assigned to the packets, this is d
The charts are labeled as follows: `[version]-[n_thread]T` eg. `2.5.0-8T` means Firegex version 2.5.0 with 8 threads. The charts are labeled as follows: `[version]-[n_thread]T` eg. `2.5.0-8T` means Firegex version 2.5.0 with 8 threads.
![Firegex Benchmark](results/Benchmark-chart.png) ![Firegex Benchmark](results/Benchmark-chart.svg)
From the benchmark above we can't see the real advantage of multithreading in 2.5.1, we can better see the advantage of multithreading in the chart below where a fake load in filtering is done. From the benchmark above we can't see the real advantage of multithreading in 2.5.1, we can better see the advantage of multithreading in the chart below where a fake load in filtering is done.
@@ -107,7 +107,7 @@ for (int i=0; i<50000; i++){
} }
``` ```
![Firegex Benchmark](results/Benchmark-chart-with-load.png) ![Firegex Benchmark](results/Benchmark-chart-with-load.svg)
In the chart above we can see that the 2.5.1 version with 8 threads has a better performance than the 2.5.1 version with 1 threads, and we can see it as much as the load increases. In the chart above we can see that the 2.5.1 version with 8 threads has a better performance than the 2.5.1 version with 1 threads, and we can see it as much as the load increases.
@@ -118,15 +118,14 @@ The code used to test matches the following regex with the python re module:
(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\]) (?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])
``` ```
![nfproxy benchmarks](results/whisker_nfproxy.png) ![nfproxy benchmarks](results/whisker_nfproxy.svg)
![nfproxy benchmarks](results/istogramma_nfproxy.png) ![nfproxy benchmarks](results/istogramma_nfproxy.svg)
# Comparing nfproxy with nfregex # Comparing nfproxy with nfregex
Nfproxy has obviously a worse performance than nfregex, but it is more flexible and can be used in more complex scenarios. Nfproxy has obviously a worse performance than nfregex, but it is more flexible and can be used in more complex scenarios.
![nfproxy benchmarks](results/whisker_compare.png) ![nfproxy benchmarks](results/whisker_compare.svg)
![nfproxy benchmarks](results/istrogramma_compare.png)
![nfproxy benchmarks](results/istrogramma_compare.svg)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 302 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 450 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 176 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 243 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 176 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 137 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 41 KiB

View File

@@ -1,16 +1,15 @@
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
import numpy as np import numpy as np
import csv import csv
from matplotlib.ticker import MaxNLocator from matplotlib.ticker import MaxNLocator
from matplotlib import cm from matplotlib import cm
plt.style.use('fivethirtyeight') plt.style.use("fivethirtyeight")
colors = cm.Set1.colors # Use a different strong color palette colors = cm.Set1.colors # Use a different strong color palette
plt.rcParams['figure.facecolor'] = 'white' plt.rcParams["figure.facecolor"] = "white"
plt.rcParams['axes.edgecolor'] = 'white' plt.rcParams["axes.edgecolor"] = "white"
plt.rcParams['axes.linewidth'] = 1.5 plt.rcParams["axes.linewidth"] = 1.5
plt.rcParams['legend.facecolor'] = 'white' plt.rcParams["legend.facecolor"] = "white"
files = [ files = [
("2.5.1 1T", "results/2.5.1-1T.csv"), ("2.5.1 1T", "results/2.5.1-1T.csv"),
@@ -21,30 +20,30 @@ files = [
("2.4.0 8T", "results/2.4.0-8T.csv"), ("2.4.0 8T", "results/2.4.0-8T.csv"),
] ]
output = "results/Benchmark-chart.png" output = "results/Benchmark-chart.svg"
data_dict = {} data_dict = {}
for label, file in files: for label, file in files:
with open(file, 'r') as csvfile: with open(file, "r") as csvfile:
reader = csv.reader(csvfile) reader = csv.reader(csvfile)
data = [list(map(float, row)) for row in reader] data = [list(map(float, row)) for row in reader]
data_dict[label] = data data_dict[label] = data
fig, ax = plt.subplots() fig, ax = plt.subplots()
ax.set_facecolor('white') ax.set_facecolor("white")
for label in data_dict.keys(): for label in data_dict.keys():
data = data_dict[label] data = data_dict[label]
ax.plot( ax.plot(
list(map(lambda d: int(d[0]), data)), list(map(lambda d: int(d[0]), data)),
list(map(lambda d: d[1], data)), list(map(lambda d: d[1], data)),
label=label label=label,
) )
ax.set_xlabel("N. of regex", fontname="Roboto", fontsize=12) ax.set_xlabel("N. of regex", fontname="Roboto", fontsize=12)
ax.set_ylabel("MB/s", fontname="Roboto", fontsize=12) ax.set_ylabel("MB/s", fontname="Roboto", fontsize=12)
ax.legend(prop={'family': 'Roboto', 'size': 10}) ax.legend(prop={"family": "Roboto", "size": 10})
ax.legend( ax.legend(
title_fontsize=12, title_fontsize=12,
loc="upper center", loc="upper center",
@@ -54,16 +53,16 @@ ax.legend(
borderpad=1, borderpad=1,
fontsize=10, fontsize=10,
fancybox=True, fancybox=True,
ncol=len(data_dict.keys()) # Make the legend horizontal ncol=len(data_dict.keys()), # Make the legend horizontal
) )
ax.set_xticks(np.arange(0, max(map(lambda d: int(d[0]), data)), step=3)) ax.set_xticks(np.arange(0, max(map(lambda d: int(d[0]), data)), step=3))
ax.set_yticks(np.arange(0, max(map(lambda d: d[1], data)), step=300)) ax.set_yticks(np.arange(0, max(map(lambda d: d[1], data)), step=300))
plt.subplots_adjust(bottom=0.2) # Adjust the bottom margin to make space for the legend plt.subplots_adjust(bottom=0.2) # Adjust the bottom margin to make space for the legend
ax.set_title("Firegex benchmark (nfregex)", fontweight='bold', fontname="Roboto", pad=20) ax.set_title("Firegex benchmark (nfregex)", fontweight="bold", fontname="Roboto", pad=20)
fig.set_size_inches(12, 8) # Set the figure size to make the image larger fig.set_size_inches(12, 8) # Set the figure size to make the image larger
# plt.show() # plt.show()
plt.savefig(output, dpi=300, bbox_inches='tight') plt.savefig(output, dpi=300, bbox_inches="tight")
plt.close() plt.close()
files = [ files = [
@@ -71,30 +70,30 @@ files = [
("2.5.1 8T", "results/2.5.1-8T-withload.csv"), ("2.5.1 8T", "results/2.5.1-8T-withload.csv"),
] ]
output = "results/Benchmark-chart-with-load.png" output = "results/Benchmark-chart-with-load.svg"
data_dict = {} data_dict = {}
for label, file in files: for label, file in files:
with open(file, 'r') as csvfile: with open(file, "r") as csvfile:
reader = csv.reader(csvfile) reader = csv.reader(csvfile)
data = [list(map(float, row)) for row in reader] data = [list(map(float, row)) for row in reader]
data_dict[label] = data data_dict[label] = data
fig, ax = plt.subplots() fig, ax = plt.subplots()
ax.set_facecolor('white') ax.set_facecolor("white")
for label in data_dict.keys(): for label in data_dict.keys():
data = data_dict[label] data = data_dict[label]
ax.plot( ax.plot(
list(map(lambda d: int(d[0]), data)), list(map(lambda d: int(d[0]), data)),
list(map(lambda d: d[1], data)), list(map(lambda d: d[1], data)),
label=label label=label,
) )
ax.set_xlabel("N. of regex", fontname="Roboto", fontsize=12) ax.set_xlabel("N. of regex", fontname="Roboto", fontsize=12)
ax.set_ylabel("MB/s", fontname="Roboto", fontsize=12) ax.set_ylabel("MB/s", fontname="Roboto", fontsize=12)
ax.legend(prop={'family': 'Roboto', 'size': 10}) ax.legend(prop={"family": "Roboto", "size": 10})
ax.legend( ax.legend(
title_fontsize=12, title_fontsize=12,
loc="upper center", loc="upper center",
@@ -104,12 +103,12 @@ ax.legend(
borderpad=1, borderpad=1,
fontsize=10, fontsize=10,
fancybox=True, fancybox=True,
ncol=len(data_dict.keys()) ncol=len(data_dict.keys()),
) )
ax.set_xticks(np.arange(0, max(map(lambda d: int(d[0]), data)), step=3)) ax.set_xticks(np.arange(0, max(map(lambda d: int(d[0]), data)), step=3))
ax.set_yticks(np.arange(0, max(map(lambda d: d[1], data)), step=150)) ax.set_yticks(np.arange(0, max(map(lambda d: d[1], data)), step=150))
plt.subplots_adjust(bottom=0.2) plt.subplots_adjust(bottom=0.2)
ax.set_title("Load test firegex (nfregex)", fontweight='bold', fontname="Roboto", pad=20) ax.set_title("Load test firegex (nfregex)", fontweight="bold", fontname="Roboto", pad=20)
fig.set_size_inches(12, 8) fig.set_size_inches(12, 8)
# Calculate the minimum and maximum y values across all data # Calculate the minimum and maximum y values across all data
@@ -123,7 +122,7 @@ ax.set_ylim(y_min - (y_max - y_min) * 0.1, y_max + (y_max - y_min) * 0.1)
ax.yaxis.set_major_locator(MaxNLocator(integer=True)) ax.yaxis.set_major_locator(MaxNLocator(integer=True))
# plt.show() # plt.show()
plt.savefig(output, dpi=300, bbox_inches='tight') plt.savefig(output, dpi=300, bbox_inches="tight")
plt.close() plt.close()
files_nfproxy = [ files_nfproxy = [
@@ -131,13 +130,13 @@ files_nfproxy = [
("NfProxy 8T", "results/comparemark_nfproxy_8T.csv"), ("NfProxy 8T", "results/comparemark_nfproxy_8T.csv"),
] ]
output_whisker = "results/whisker_nfproxy.png" output_whisker = "results/whisker_nfproxy.svg"
output_histogram = "results/istogramma_nfproxy.png" output_histogram = "results/istogramma_nfproxy.svg"
# Read and process data for nfproxy # Read and process data for nfproxy
data_nfproxy = {} data_nfproxy = {}
for label, file in files_nfproxy: for label, file in files_nfproxy:
with open(file, 'r') as csvfile: with open(file, "r") as csvfile:
reader = csv.reader(csvfile) reader = csv.reader(csvfile)
next(reader) # Skip the header next(reader) # Skip the header
data = [(float(row[0]), float(row[1])) for row in reader] data = [(float(row[0]), float(row[1])) for row in reader]
@@ -146,7 +145,7 @@ for label, file in files_nfproxy:
# Generate whisker plot for nfproxy # Generate whisker plot for nfproxy
fig, ax = plt.subplots() fig, ax = plt.subplots()
ax.set_facecolor('white') ax.set_facecolor("white")
y_max = max([max(data) for data in data_nfproxy.values()]) y_max = max([max(data) for data in data_nfproxy.values()])
y_min = min([min(data) for data in data_nfproxy.values()]) y_min = min([min(data) for data in data_nfproxy.values()])
@@ -161,15 +160,17 @@ for i, (label, data) in enumerate(data_nfproxy.items()):
capprops=dict(color="black", linewidth=1.3), capprops=dict(color="black", linewidth=1.3),
medianprops=dict(color="black", linewidth=1.3), medianprops=dict(color="black", linewidth=1.3),
patch_artist=True, # Enable filling the box with color patch_artist=True, # Enable filling the box with color
widths=0.35 # Increase the width of the boxes widths=0.35, # Increase the width of the boxes
) )
ax.set_yticks(np.arange(0, int(y_max) + 100, step=100)) # Ensure the range includes y_max ax.set_yticks(
np.arange(0, int(y_max) + 100, step=100)
) # Ensure the range includes y_max
# Set the y-axis limits to skip unused parts # Set the y-axis limits to skip unused parts
ax.set_ylim(y_min - (y_max - y_min) * 0.1, y_max + (y_max - y_min) * 0.1) ax.set_ylim(y_min - (y_max - y_min) * 0.1, y_max + (y_max - y_min) * 0.1)
ax.set_title("NFProxy Benchmarks", fontweight='bold', fontname="Roboto", pad=20) ax.set_title("NFProxy Benchmarks", fontweight="bold", fontname="Roboto", pad=20)
ax.set_ylabel("MB/s", fontname="Roboto", fontsize=12) ax.set_ylabel("MB/s", fontname="Roboto", fontsize=12)
fig.set_size_inches(12, 8) fig.set_size_inches(12, 8)
@@ -181,7 +182,7 @@ plt.close()
average_data = {label: np.mean(data) for label, data in data_nfproxy.items()} average_data = {label: np.mean(data) for label, data in data_nfproxy.items()}
fig, ax = plt.subplots() fig, ax = plt.subplots()
ax.set_facecolor('white') ax.set_facecolor("white")
y_max = max(average_data.values()) y_max = max(average_data.values())
bars = ax.bar( bars = ax.bar(
@@ -189,11 +190,13 @@ bars = ax.bar(
average_data.values(), average_data.values(),
color=[colors[i % len(colors)] for i in range(len(average_data))], color=[colors[i % len(colors)] for i in range(len(average_data))],
edgecolor="black", edgecolor="black",
width=0.4 # Make the bars narrower width=0.4, # Make the bars narrower
) )
ax.set_yticks(np.arange(0, int(y_max) + 100, step=100)) # Ensure the range includes y_max ax.set_yticks(
ax.set_title("NFProxy Benchmarks", fontweight='bold', fontname="Roboto", pad=20) np.arange(0, int(y_max) + 100, step=100)
) # Ensure the range includes y_max
ax.set_title("NFProxy Benchmarks", fontweight="bold", fontname="Roboto", pad=20)
ax.set_ylabel("Average MB/s", fontname="Roboto", fontsize=12) ax.set_ylabel("Average MB/s", fontname="Roboto", fontsize=12)
ax.set_xticklabels(average_data.keys(), fontname="Roboto", fontsize=12) ax.set_xticklabels(average_data.keys(), fontname="Roboto", fontsize=12)
@@ -201,21 +204,21 @@ ax.set_xticklabels(average_data.keys(), fontname="Roboto", fontsize=12)
for bar in bars: for bar in bars:
height = bar.get_height() height = bar.get_height()
ax.annotate( ax.annotate(
f'{height:.2f}', f"{height:.2f}",
xy=(bar.get_x() + bar.get_width() / 2, height), xy=(bar.get_x() + bar.get_width() / 2, height),
xytext=(0, 3), # Offset text above the bar xytext=(0, 3), # Offset text above the bar
textcoords="offset points", textcoords="offset points",
ha='center', ha="center",
va='bottom', va="bottom",
fontsize=10, fontsize=10,
fontname="Roboto" fontname="Roboto",
) )
fig.set_size_inches(12, 8) fig.set_size_inches(12, 8)
plt.tight_layout() plt.tight_layout()
# plt.show() # plt.show()
plt.savefig(output_histogram, dpi=300, bbox_inches='tight') plt.savefig(output_histogram, dpi=300, bbox_inches="tight")
plt.close() plt.close()
files_nfregex = [ files_nfregex = [
@@ -223,13 +226,13 @@ files_nfregex = [
("NfRegex 8T", "results/comparemark_nfregex_8T.csv"), ("NfRegex 8T", "results/comparemark_nfregex_8T.csv"),
] ]
output_whisker = "results/whisker_compare.png" output_whisker = "results/whisker_compare.svg"
output_histogram = "results/istrogramma_compare.png" output_histogram = "results/istrogramma_compare.svg"
# Read and process data for nfregex # Read and process data for nfregex
data_nfregex = {} data_nfregex = {}
for label, file in files_nfregex: for label, file in files_nfregex:
with open(file, 'r') as csvfile: with open(file, "r") as csvfile:
reader = csv.reader(csvfile) reader = csv.reader(csvfile)
next(reader) # Skip the header next(reader) # Skip the header
data = [(float(row[0]), float(row[1])) for row in reader] data = [(float(row[0]), float(row[1])) for row in reader]
@@ -241,7 +244,7 @@ combined_data = {**data_nfproxy, **data_nfregex}
# Generate whisker plot for combined data # Generate whisker plot for combined data
fig, ax = plt.subplots() fig, ax = plt.subplots()
ax.set_facecolor('white') ax.set_facecolor("white")
y_max = max([max(data) for data in combined_data.values()]) y_max = max([max(data) for data in combined_data.values()])
y_min = min([min(data) for data in combined_data.values()]) y_min = min([min(data) for data in combined_data.values()])
@@ -255,64 +258,79 @@ for i, (label, data) in enumerate(combined_data.items()):
capprops=dict(color="black", linewidth=1.3), capprops=dict(color="black", linewidth=1.3),
medianprops=dict(color="black", linewidth=1.3), medianprops=dict(color="black", linewidth=1.3),
patch_artist=True, # Enable filling the box with color patch_artist=True, # Enable filling the box with color
widths=0.6 # Increase the width of the boxes widths=0.6, # Increase the width of the boxes
) )
ax.set_xticks(range(len(combined_data.keys()))) ax.set_xticks(range(len(combined_data.keys())))
ax.set_xticklabels(combined_data.keys(), fontname="Roboto", fontsize=10) ax.set_xticklabels(combined_data.keys(), fontname="Roboto", fontsize=10)
ax.set_yticks(np.arange(0, int(y_max) + 100, step=250)) # Ensure the range includes y_max ax.set_yticks(
np.arange(0, int(y_max) + 100, step=250)
) # Ensure the range includes y_max
plt.subplots_adjust(bottom=0.12) plt.subplots_adjust(bottom=0.12)
# Set the y-axis limits to skip unused parts # Set the y-axis limits to skip unused parts
ax.set_ylim(y_min - (y_max - y_min) * 0.1, y_max + (y_max - y_min) * 0.1) ax.set_ylim(y_min - (y_max - y_min) * 0.1, y_max + (y_max - y_min) * 0.1)
ax.set_title("Combined Benchmarks (NFProxy vs NFRegex)", fontweight='bold', fontname="Roboto", pad=20) ax.set_title(
"Combined Benchmarks (NFProxy vs NFRegex)",
fontweight="bold",
fontname="Roboto",
pad=20,
)
ax.set_ylabel("MB/s", fontname="Roboto", fontsize=12) ax.set_ylabel("MB/s", fontname="Roboto", fontsize=12)
fig.set_size_inches(14, 8) fig.set_size_inches(14, 8)
# plt.show() # plt.show()
plt.savefig(output_whisker, dpi=300, bbox_inches='tight') plt.savefig(output_whisker, dpi=300, bbox_inches="tight")
plt.close() plt.close()
# Generate bar chart with average data for combined data # Generate bar chart with average data for combined data
average_combined_data = {label: np.mean(data) for label, data in combined_data.items()} average_combined_data = {label: np.mean(data) for label, data in combined_data.items()}
fig, ax = plt.subplots() fig, ax = plt.subplots()
ax.set_facecolor('white') ax.set_facecolor("white")
y_max = max(average_combined_data.values()) y_max = max(average_combined_data.values())
bars = ax.bar( bars = ax.bar(
average_combined_data.keys(), average_combined_data.keys(),
average_combined_data.values(), average_combined_data.values(),
color=[colors[0 if "nfregex" in ele.lower() else 1] for ele in average_combined_data], color=[
colors[0 if "nfregex" in ele.lower() else 1] for ele in average_combined_data
],
edgecolor="black", edgecolor="black",
width=0.4 # Make the bars narrower width=0.4, # Make the bars narrower
) )
ax.set_xticks(range(len(average_combined_data.keys()))) ax.set_xticks(range(len(average_combined_data.keys())))
ax.set_xticklabels(average_combined_data.keys(), fontname="Roboto", fontsize=10) ax.set_xticklabels(average_combined_data.keys(), fontname="Roboto", fontsize=10)
ax.set_yticks(np.arange(0, int(y_max) + 100, step=200)) # Ensure the range includes y_max ax.set_yticks(
ax.set_title("Combined Benchmarks (NFProxy vs NFRegex)", fontweight='bold', fontname="Roboto", pad=20) np.arange(0, int(y_max) + 100, step=200)
) # Ensure the range includes y_max
ax.set_title(
"Combined Benchmarks (NFProxy vs NFRegex)",
fontweight="bold",
fontname="Roboto",
pad=20,
)
ax.set_ylabel("Average MB/s", fontname="Roboto", fontsize=12) ax.set_ylabel("Average MB/s", fontname="Roboto", fontsize=12)
# Annotate bars with their values # Annotate bars with their values
for bar in bars: for bar in bars:
height = bar.get_height() height = bar.get_height()
ax.annotate( ax.annotate(
f'{height:.2f}', f"{height:.2f}",
xy=(bar.get_x() + bar.get_width() / 2, height), xy=(bar.get_x() + bar.get_width() / 2, height),
xytext=(0, 3), # Offset text above the bar xytext=(0, 3), # Offset text above the bar
textcoords="offset points", textcoords="offset points",
ha='center', ha="center",
va='bottom', va="bottom",
fontsize=10, fontsize=10,
fontname="Roboto" fontname="Roboto",
) )
fig.set_size_inches(14, 8) fig.set_size_inches(14, 8)
plt.tight_layout() plt.tight_layout()
# plt.show() # plt.show()
plt.savefig(output_histogram, dpi=300, bbox_inches='tight') plt.savefig(output_histogram, dpi=300, bbox_inches="tight")
plt.close() plt.close()