From a42bd2e5da6fd051635b139dfc1042efd72b5f27 Mon Sep 17 00:00:00 2001 From: slc Date: Sun, 11 Jan 2026 01:06:44 -0800 Subject: [PATCH 1/3] boxplot --- eval/distribution_comparison_boxplots.py | 47 ++++++++++++++++-------- 1 file changed, 32 insertions(+), 15 deletions(-) diff --git a/eval/distribution_comparison_boxplots.py b/eval/distribution_comparison_boxplots.py index 66e41a6..d21bdae 100644 --- a/eval/distribution_comparison_boxplots.py +++ b/eval/distribution_comparison_boxplots.py @@ -12,12 +12,14 @@ from matplotlib import patches as mpatches from matplotlib.patches import Rectangle from matplotlib import rcParams +from matplotlib import ticker +from matplotlib.gridspec import GridSpec import numpy as np from datetime import datetime, timedelta import data_cache -# Increase all font sizes by 8 points from their defaults -rcParams.update({key: rcParams[key] + 8 for key in rcParams if "size" in key and isinstance(rcParams[key], (int, float))}) +# Increase all font sizes by 16 points from their defaults +rcParams.update({key: rcParams[key] + 16 for key in rcParams if "size" in key and isinstance(rcParams[key], (int, float))}) # ============================================================================ # CONFIGURATION SECTION @@ -246,14 +248,16 @@ def generate_distribution_comparison(block_dir, zns_dir, distribution, metric, o print(f"Found {len(block_runs)} block runs and {len(zns_runs)} ZNS runs") - # Create figure with 6 subplots (1 row x 6 columns) + # Create figure with 6 subplots (1 row x 6 columns) using GridSpec for custom widths # Subplots are 2/5 original height, but all spacing preserved num_subplots = len(RATIOS) * len(CHUNK_SIZES) # 2 ratios * 3 chunk sizes = 6 - fig, axes = plt.subplots(1, num_subplots, figsize=(5 * num_subplots, 5.38)) - # Ensure axes is always a list - if num_subplots == 1: - axes = [axes] + # Width ratios: 1077MiB subplots (indices 2 and 5) are half as wide since they have 2 boxes instead of 4 + width_ratios = [1, 1, 0.5, 1, 1, 0.5] + + fig = plt.figure(figsize=(5 * num_subplots, 5.38)) + gs = GridSpec(1, num_subplots, figure=fig, width_ratios=width_ratios) + axes = [fig.add_subplot(gs[0, i]) for i in range(num_subplots)] # First pass: collect all data to find global maximum for y-axis all_subplot_data = [] @@ -390,9 +394,18 @@ def generate_distribution_comparison(block_dir, zns_dir, distribution, metric, o # Create boxplot for this subplot if current_data: + # Adjust box width based on number of boxes so they're consistent across subplots + # Base width is 0.8 for 4 boxes, scale proportionally for fewer boxes + # Exception: 1077MiB boxes are made thicker since they have fewer boxes + num_boxes = len(current_data) + if chunk_size == 1129316352: # 1077MiB + box_width = 0.8 # Full width like regular boxplots + else: + box_width = 0.8 * (num_boxes / 4) if num_boxes > 0 else 0.8 + bp = axes[idx].boxplot(current_data, showfliers=show_outliers, - widths=0.8, + widths=box_width, medianprops=dict(linewidth=2, color='black'), patch_artist=True) @@ -400,6 +413,7 @@ def generate_distribution_comparison(block_dir, zns_dir, distribution, metric, o for i, (box, color, hatch) in enumerate(zip(bp['boxes'], colors, hatches)): box.set_facecolor(color) box.set_hatch(hatch) + box.set_hatch_linewidth(3.0) box.set_alpha(0.7) # Set x-axis labels (empty for cleaner look, or could add device labels) @@ -407,7 +421,10 @@ def generate_distribution_comparison(block_dir, zns_dir, distribution, metric, o axes[idx].set_xticklabels([], rotation=45, fontsize=10) # Add chunk size label below subplot - axes[idx].set_xlabel(CHUNK_SIZE_LABELS[chunk_size], fontsize=16, weight='bold') + axes[idx].set_xlabel(CHUNK_SIZE_LABELS[chunk_size], fontsize=28, weight='bold') + + # Use scalar formatter without scientific notation + axes[idx].yaxis.set_major_formatter(ticker.ScalarFormatter(useOffset=False, useMathText=False)) # Rotate y-axis labels for label in axes[idx].get_yticklabels(): @@ -424,10 +441,10 @@ def generate_distribution_comparison(block_dir, zns_dir, distribution, metric, o idx += 1 # Add y-axis label on the far left - fig.text(0.02, 0.5, metric_label, va='center', rotation='vertical', fontsize=22, weight='bold') + fig.text(-0.005, 0.5, metric_label, va='center', rotation='vertical', fontsize=22, weight='bold') # Adjust layout (do these BEFORE computing positions) - subplots at 2/5 height with proportional spacing - plt.subplots_adjust(wspace=0.05, hspace=0.0) + plt.subplots_adjust(wspace=0.2, hspace=0.0) plt.tight_layout(pad=0.0) plt.subplots_adjust(top=0.851, bottom=0.279, left=0.05) @@ -451,8 +468,8 @@ def generate_distribution_comparison(block_dir, zns_dir, distribution, metric, o g2_width = g2_right - g2_left # Vertical placement of the grey boxes in figure coords - box_y = 0.93 - box_h = 0.06 + box_y = 0.85 + box_h = 0.10 # Grey box for Ratio 1:2 fig.add_artist( @@ -491,7 +508,7 @@ def generate_distribution_comparison(block_dir, zns_dir, distribution, metric, o "Ratio: 1:2", ha='center', va='center', - fontsize=20, + fontsize=26, weight='bold', zorder=2, ) @@ -501,7 +518,7 @@ def generate_distribution_comparison(block_dir, zns_dir, distribution, metric, o "Ratio: 1:10", ha='center', va='center', - fontsize=20, + fontsize=26, weight='bold', zorder=2, ) From 8572ab9915956d718c0b7e9a3ecdb277f980db28 Mon Sep 17 00:00:00 2001 From: slc Date: Sun, 11 Jan 2026 00:45:28 -0800 Subject: [PATCH 2/3] ecdfs --- eval/distribution_comparison_ecdfs.py | 29 ++++++++++++++------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/eval/distribution_comparison_ecdfs.py b/eval/distribution_comparison_ecdfs.py index 98a0228..0d54017 100644 --- a/eval/distribution_comparison_ecdfs.py +++ b/eval/distribution_comparison_ecdfs.py @@ -18,8 +18,8 @@ from datetime import datetime, timedelta import data_cache -# Increase all font sizes by 8 points from their defaults -rcParams.update({key: rcParams[key] + 8 for key in rcParams if "size" in key and isinstance(rcParams[key], (int, float))}) +# Increase all font sizes by 16 points from their defaults +rcParams.update({key: rcParams[key] + 16 for key in rcParams if "size" in key and isinstance(rcParams[key], (int, float))}) # ============================================================================ # CONFIGURATION SECTION @@ -410,8 +410,10 @@ def generate_distribution_comparison(block_dir, zns_dir, distribution, output_fi print(f"Warning: No run found for {device} {eviction_type} chunk={chunk_size} dist={distribution} ratio={ratio}") # Configure subplot - current_ax.set_xlabel(CHUNK_SIZE_LABELS[chunk_size], fontsize=16, weight='bold') - current_ax.set_ylabel('Cumulative Probability (%)', fontsize=18) + current_ax.set_xlabel(CHUNK_SIZE_LABELS[chunk_size], fontsize=28, weight='bold') + if idx == 0: + ylabel = current_ax.set_ylabel('Cumulative Probability (%)', fontsize=25) + ylabel.set_position((-0.1, 0.3)) current_ax.set_ylim(0, 100) # Configure x-axis scale @@ -441,7 +443,6 @@ def exp_formatter(x, pos): current_ax.xaxis.set_major_formatter(FuncFormatter(exp_formatter)) else: - current_ax.set_xlim(left=0) # Use MaxNLocator to ensure nice, evenly-spaced tick intervals current_ax.xaxis.set_major_locator(MaxNLocator(nbins=6, integer=False, prune=None)) @@ -480,13 +481,13 @@ def exp_formatter(x, pos): Line2D([0], [0], color='#f781bf', linestyle='--', linewidth=LINE_WIDTH, label='Block (Chunk LRU)', alpha=0.8), ] - fig.legend(ncols=4, handles=legend_lines, bbox_to_anchor=(subplot_center, 0.02), + fig.legend(ncols=4, handles=legend_lines, bbox_to_anchor=(subplot_center, -0.09), loc='center', fontsize="large", columnspacing=2.0, frameon=False) # Add a background box for the x-axis label to make it stand out - label_y = 0.08 - label_width = 0.12 - label_height = 0.04 + label_y = 0.01 + label_width = 0.18 + label_height = 0.08 fig.add_artist( Rectangle( (subplot_center - label_width/2, label_y - label_height/2), @@ -502,7 +503,7 @@ def exp_formatter(x, pos): # Add x-axis label at the bottom, centered over the subplots fig.text(subplot_center, label_y, 'Latency (ms)', ha='center', va='center', - fontsize=18, weight='bold', zorder=11) + fontsize=30, weight='bold', zorder=11) # First 3 subplots -> Ratio 1:2, next 3 -> Ratio 1:10 group1 = axes_bboxes[0:3] @@ -518,8 +519,8 @@ def exp_formatter(x, pos): g2_width = g2_right - g2_left # Vertical placement of the grey boxes in figure coords - box_y = 0.93 - box_h = 0.06 + box_y = 0.85 + box_h = 0.10 # Grey box for Ratio 1:2 fig.add_artist( @@ -558,7 +559,7 @@ def exp_formatter(x, pos): "Ratio: 1:2", ha='center', va='center', - fontsize=20, + fontsize=26, weight='bold', zorder=2, ) @@ -568,7 +569,7 @@ def exp_formatter(x, pos): "Ratio: 1:10", ha='center', va='center', - fontsize=20, + fontsize=26, weight='bold', zorder=2, ) From 82f45e157c6d74bd18ed4a297aeee3e7191feacd Mon Sep 17 00:00:00 2001 From: slc Date: Sun, 11 Jan 2026 01:03:25 -0800 Subject: [PATCH 3/3] change wt plots --- eval/boxplot_wt.py | 16 +++++++++++++--- eval/ecdf_wt.py | 27 +++++++++++++++++++-------- 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/eval/boxplot_wt.py b/eval/boxplot_wt.py index 6062580..4e3c7b6 100755 --- a/eval/boxplot_wt.py +++ b/eval/boxplot_wt.py @@ -9,10 +9,11 @@ import matplotlib.pyplot as plt from matplotlib import patches as mpatches from matplotlib import rcParams +from matplotlib import ticker import data_cache -# Increase all font sizes by 8 points from their defaults -rcParams.update({key: rcParams[key] + 8 for key in rcParams if "size" in key and isinstance(rcParams[key], (int, float))}) +# Increase all font sizes by 16 points from their defaults +rcParams.update({key: rcParams[key] + 16 for key in rcParams if "size" in key and isinstance(rcParams[key], (int, float))}) # ============================================================================ # CONFIGURATION SECTION @@ -296,9 +297,14 @@ def generate_boxplot(block_dir, zns_dir, output_file, sample_size=None, show_out # Create boxplot (identical to distribution_comparison_boxplots.py) if current_data: + # Adjust box width based on number of boxes so they're consistent across subplots + # Base width is 0.8 for 4 boxes, scale proportionally for fewer boxes + num_boxes = len(current_data) + box_width = 0.8 * (num_boxes / 4) if num_boxes > 0 else 0.8 + bp = ax.boxplot(current_data, showfliers=show_outliers, - widths=0.8, + widths=box_width, medianprops=dict(linewidth=2, color='black'), patch_artist=True) @@ -306,6 +312,7 @@ def generate_boxplot(block_dir, zns_dir, output_file, sample_size=None, show_out for i, (box, color, hatch) in enumerate(zip(bp['boxes'], colors, hatches)): box.set_facecolor(color) box.set_hatch(hatch) + box.set_hatch_linewidth(3.0) box.set_alpha(0.7) # Set x-axis labels (empty for cleaner look) @@ -318,6 +325,9 @@ def generate_boxplot(block_dir, zns_dir, output_file, sample_size=None, show_out # Set y-axis label ax.set_ylabel(metric_label, fontsize=22, weight='bold') + # Use scalar formatter without scientific notation + ax.yaxis.set_major_formatter(ticker.ScalarFormatter(useOffset=False, useMathText=False)) + # Rotate y-axis labels for label in ax.get_yticklabels(): label.set_rotation(45) diff --git a/eval/ecdf_wt.py b/eval/ecdf_wt.py index a468dcc..f85d340 100755 --- a/eval/ecdf_wt.py +++ b/eval/ecdf_wt.py @@ -14,8 +14,8 @@ import numpy as np import data_cache -# Increase all font sizes by 8 points from their defaults -rcParams.update({key: rcParams[key] + 8 for key in rcParams if "size" in key and isinstance(rcParams[key], (int, float))}) +# Increase all font sizes by 16 points from their defaults +rcParams.update({key: rcParams[key] + 16 for key in rcParams if "size" in key and isinstance(rcParams[key], (int, float))}) # ============================================================================ # CONFIGURATION SECTION @@ -391,8 +391,8 @@ def generate_ecdf(block_dir, zns_dir, output_file, metric_type="get_total", samp print(f"Warning: No run found for {device} {eviction_type}") # Configure subplot - # ax.set_xlabel("64KiB", fontsize=16, weight='bold') - ax.set_ylabel('Cumulative Probability (%)', fontsize=18) + # ax.set_xlabel("64KiB", fontsize=28, weight='bold') + ax.set_ylabel('Cumulative Probability (%)', fontsize=25) ax.set_ylim(0, 100) # Configure x-axis scale @@ -422,7 +422,6 @@ def exp_formatter(x, pos): ax.xaxis.set_major_formatter(FuncFormatter(exp_formatter)) else: - ax.set_xlim(left=0) # Use MaxNLocator to ensure nice, evenly-spaced tick intervals ax.xaxis.set_major_locator(MaxNLocator(nbins=6, integer=False, prune=None)) @@ -454,14 +453,26 @@ def exp_formatter(x, pos): Line2D([0], [0], color='#f781bf', linestyle='--', linewidth=LINE_WIDTH, label='Block (Chunk LRU)', alpha=0.8), ] - fig.legend(ncols=4, handles=legend_lines, bbox_to_anchor=(subplot_center, 0.02), + fig.legend(ncols=4, handles=legend_lines, bbox_to_anchor=(subplot_center, -0.09), loc='center', fontsize="large", columnspacing=2.0, frameon=False) # Add a background box for the x-axis label to make it stand out - label_y = 0.08 + label_y = 0.01 + label_width = 0.18 + label_height = 0.08 + fig.add_artist( + Rectangle( + (subplot_center - label_width/2, label_y - label_height/2), + label_width, + label_height, + facecolor='white', + edgecolor='none', + zorder=10, + ) + ) # Add x-axis label at the bottom, centered over the subplot fig.text(subplot_center, label_y, 'Latency (ms)', ha='center', va='center', - fontsize=18, weight='bold', zorder=11) + fontsize=30, weight='bold', zorder=11) # Save figure plt.savefig(output_file, bbox_inches='tight', dpi=100)