Skip to content

Commit 63a217b

Browse files
committed
Track metrics for core and std crates
The crate that we compute metrics for is now configurable when invoking `kani_std_analysis.py`. Should we find a need for further crates beyond `core` or `std` we just need to invoke it more times.
1 parent b764eeb commit 63a217b

File tree

5 files changed

+59
-15
lines changed

5 files changed

+59
-15
lines changed

doc/mdbook-metrics/src/main.rs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,21 @@ fn run_kani_metrics_script() -> Result<(), Error> {
4444
Command::new("python")
4545
.args(&[
4646
"kani_std_analysis.py",
47+
"--crate",
48+
"core",
49+
"--plot-only",
50+
"--plot-dir",
51+
&tools_path.to_string_lossy(),
52+
])
53+
.stdout(std::process::Stdio::null())
54+
.stderr(std::process::Stdio::null())
55+
.status()?;
56+
57+
Command::new("python")
58+
.args(&[
59+
"kani_std_analysis.py",
60+
"--crate",
61+
"std",
4762
"--plot-only",
4863
"--plot-dir",
4964
&tools_path.to_string_lossy(),
@@ -83,12 +98,19 @@ fn add_graphs(chapter: &mut Chapter) {
8398
8499
Note that these metrics are for x86-64 architectures.
85100
86-
## `core`
101+
### `core`
87102
![Unsafe Metrics](core_unsafe_metrics.png)
88103
89104
![Safe Abstractions Metrics](core_safe_abstractions_metrics.png)
90105
91106
![Safe Metrics](core_safe_metrics.png)
107+
108+
### `std`
109+
![Unsafe Metrics](std_unsafe_metrics.png)
110+
111+
![Safe Abstractions Metrics](std_safe_abstractions_metrics.png)
112+
113+
![Safe Metrics](std_safe_metrics.png)
92114
"#;
93115

94116
chapter.content.push_str(new_content);

scripts/kani-std-analysis/kani_std_analysis.py

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,10 @@
2828
# - See #TODOs for known limitations.
2929

3030
# Process the results from Kani's std-analysis.sh script for each crate.
31-
# TODO For now, we just handle "core", but we should process all crates in the library.
3231
class GenericSTDMetrics():
33-
def __init__(self, results_dir):
32+
def __init__(self, results_dir, crate):
3433
self.results_directory = results_dir
34+
self.crate = crate
3535
self.unsafe_fns_count = 0
3636
self.safe_abstractions_count = 0
3737
self.safe_fns_count = 0
@@ -44,7 +44,7 @@ def __init__(self, results_dir):
4444
# Read {crate}_overall_counts.csv
4545
# and return the number of unsafe functions and safe abstractions
4646
def read_overall_counts(self):
47-
file_path = f"{self.results_directory}/core_scan_overall.csv"
47+
file_path = f"{self.results_directory}/{self.crate}_scan_overall.csv"
4848
with open(file_path, 'r') as f:
4949
csv_reader = csv.reader(f, delimiter=';')
5050
counts = {row[0]: int(row[1]) for row in csv_reader if len(row) >= 2}
@@ -56,7 +56,7 @@ def read_overall_counts(self):
5656
# and return an array of the unsafe functions and the safe abstractions
5757
def read_scan_functions(self):
5858
expected_header_start = "name;is_unsafe;has_unsafe_ops"
59-
file_path = f"{self.results_directory}/core_scan_functions.csv"
59+
file_path = f"{self.results_directory}/{self.crate}_scan_functions.csv"
6060

6161
with open(file_path, 'r') as f:
6262
csv_reader = csv.reader(f, delimiter=';', quotechar='"')
@@ -90,19 +90,19 @@ def read_std_analysis(self):
9090

9191
# Sanity checks
9292
if len(self.unsafe_fns) != self.unsafe_fns_count:
93-
print(f"Number of unsafe functions does not match core_scan_functions.csv")
93+
print(f"Number of unsafe functions does not match {self.crate}_scan_functions.csv")
9494
print(f"UNSAFE_FNS_COUNT: {self.unsafe_fns_count}")
9595
print(f"UNSAFE_FNS length: {len(self.unsafe_fns)}")
9696
sys.exit(1)
9797

9898
if len(self.safe_abstractions) != self.safe_abstractions_count:
99-
print(f"Number of safe abstractions does not match core_scan_functions.csv")
99+
print(f"Number of safe abstractions does not match {self.crate}_scan_functions.csv")
100100
print(f"SAFE_ABSTRACTIONS_COUNT: {self.safe_abstractions_count}")
101101
print(f"SAFE_ABSTRACTIONS length: {len(self.safe_abstractions)}")
102102
sys.exit(1)
103103

104104
if len(self.safe_fns) != self.safe_fns_count:
105-
print(f"Number of safe functions does not match core_scan_functions.csv")
105+
print(f"Number of safe functions does not match {self.crate}_scan_functions.csv")
106106
print(f"SAFE_FNS_COUNT: {self.safe_fns_count}")
107107
print(f"SAFE_FNS length: {len(self.safe_fns)}")
108108
sys.exit(1)
@@ -140,7 +140,8 @@ def read_kani_list_data(self, kani_list_filepath):
140140
# Generate metrics about Kani's application to the standard library over time
141141
# by reading past metrics from metrics_file, then computing today's metrics.
142142
class KaniSTDMetricsOverTime():
143-
def __init__(self, metrics_file):
143+
def __init__(self, metrics_file, crate):
144+
self.crate = crate
144145
self.dates = []
145146
self.unsafe_metrics = ['total_unsafe_fns', 'unsafe_fns_under_contract', 'verified_unsafe_fns_under_contract']
146147
self.safe_abstr_metrics = ['total_safe_abstractions', 'safe_abstractions_under_contract', 'verified_safe_abstractions_under_contract']
@@ -190,7 +191,7 @@ def compute_metrics(self, kani_list_filepath, analysis_results_dir):
190191

191192
# Process the `kani list` and `std-analysis.sh` data
192193
kani_data = KaniListSTDMetrics(kani_list_filepath)
193-
generic_metrics = GenericSTDMetrics(analysis_results_dir)
194+
generic_metrics = GenericSTDMetrics(analysis_results_dir, self.crate)
194195

195196
print("Comparing kani-list output to std-analysis.sh output and computing metrics...")
196197

@@ -280,12 +281,28 @@ def plot_single(self, data, title, filename, plot_dir):
280281
print(f"PNG graph generated: {outfile}")
281282

282283
def plot(self, plot_dir):
283-
self.plot_single(self.unsafe_plot_data, title="Contracts on Unsafe Functions in core", filename="core_unsafe_metrics.png", plot_dir=plot_dir)
284-
self.plot_single(self.safe_abstr_plot_data, title="Contracts on Safe Abstractions in core", filename="core_safe_abstractions_metrics.png", plot_dir=plot_dir)
285-
self.plot_single(self.safe_plot_data, title="Contracts on Safe Functions in core", filename="core_safe_metrics.png", plot_dir=plot_dir)
284+
self.plot_single(
285+
self.unsafe_plot_data,
286+
title=f"Contracts on Unsafe Functions in {self.crate}",
287+
filename=f"{self.crate}_unsafe_metrics.png",
288+
plot_dir=plot_dir)
289+
self.plot_single(
290+
self.safe_abstr_plot_data,
291+
title=f"Contracts on Safe Abstractions in {self.crate}",
292+
filename=f"{self.crate}_safe_abstractions_metrics.png",
293+
plot_dir=plot_dir)
294+
self.plot_single(
295+
self.safe_plot_data,
296+
title=f"Contracts on Safe Functions in {self.crate}",
297+
filename=f"{self.crate}_safe_metrics.png",
298+
plot_dir=plot_dir)
286299

287300
def main():
288301
parser = argparse.ArgumentParser(description="Generate metrics about Kani's application to the standard library.")
302+
parser.add_argument('--crate',
303+
type=str,
304+
required=True,
305+
help="Name of standard library crate to produce metrics for")
289306
parser.add_argument('--metrics-file',
290307
type=str,
291308
default="metrics-data.json",
@@ -308,7 +325,7 @@ def main():
308325

309326
args = parser.parse_args()
310327

311-
metrics = KaniSTDMetricsOverTime(args.metrics_file)
328+
metrics = KaniSTDMetricsOverTime(args.metrics_file, args.crate)
312329

313330
if args.plot_only:
314331
metrics.plot(args.plot_dir)
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"results": [
3+
]
4+
}

scripts/run-kani.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,8 @@ main() {
309309
pushd scripts/kani-std-analysis
310310
pip install -r requirements.txt
311311
echo "Computing Kani-specific metrics..."
312-
./kani_std_analysis.py --kani-list-file $current_dir/kani-list.json
312+
./kani_std_analysis.py --crate core --kani-list-file $current_dir/kani-list.json
313+
./kani_std_analysis.py --crate std --kani-list-file $current_dir/kani-list.json
313314
popd
314315
rm kani-list.json
315316
fi

0 commit comments

Comments
 (0)