Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
polynomial_stats.hpp
Go to the documentation of this file.
1#pragma once
2
4#include <cstddef>
5#include <cstdint>
6#include <cstdlib>
7#include <iomanip>
8#include <sstream>
9#include <string>
10#include <utility>
11
12namespace bb {
13
19template <typename Fr> size_t min_bytes_for_value(const Fr& val)
20{
21 // Check limbs from most significant to least significant
22 for (int limb = 3; limb >= 0; --limb) {
23 if (val.data[limb] != 0) {
24 // Count bytes needed for this limb
25 uint64_t v = val.data[limb];
26 size_t bytes_in_limb = 0;
27 while (v > 0) {
28 bytes_in_limb++;
29 v >>= 8;
30 }
31 return (static_cast<size_t>(limb) * 8) + bytes_in_limb;
32 }
33 }
34 return 0; // all limbs are zero
35}
36
45template <typename ProverPolynomials> void analyze_prover_polynomials(ProverPolynomials& polynomials)
46{
47 using Polynomial = std::remove_reference_t<decltype(*polynomials.get_unshifted().begin())>;
48 using Fr = typename Polynomial::FF;
49
50 auto unshifted = polynomials.get_unshifted();
51 auto all_labels = polynomials.get_labels();
52
53 struct PolyStats {
54 std::string name;
55 size_t alloc_size = 0; // number of allocated coefficients
56 size_t virtual_size = 0; // total virtual size including zero padding
57 size_t num_zeros = 0; // coefficients that are exactly 0
58 size_t fit_4bytes = 0; // non-zero coefficients fitting in <= 4 bytes
59 size_t fit_8bytes = 0; // non-zero coefficients fitting in <= 8 bytes
60 size_t fit_16bytes = 0; // non-zero coefficients fitting in <= 16 bytes
61 size_t fit_32bytes = 0; // non-zero coefficients needing > 16 bytes (up to 32)
62 size_t actual_mem = 0; // actual memory in bytes (alloc_size * 32)
63 double compressed_mem = 0; // ideal compressed memory in bytes
64 };
65
66 std::vector<PolyStats> all_stats;
67 PolyStats totals;
68 totals.name = "TOTAL";
69
70 size_t idx = 0;
71 for (auto& poly : unshifted) {
72 PolyStats stats;
73 stats.name = (idx < all_labels.size()) ? all_labels[idx] : "unknown_" + std::to_string(idx);
74 idx++;
75
76 if (poly.is_empty()) {
77 all_stats.push_back(std::move(stats));
78 continue;
79 }
80
81 stats.alloc_size = poly.size();
82 stats.virtual_size = poly.virtual_size();
83 stats.actual_mem = stats.alloc_size * sizeof(Fr);
84
85 const Fr* data = poly.data();
86 for (size_t i = 0; i < stats.alloc_size; ++i) {
87 const Fr& elem = data[i];
88 // Zero in Montgomery form is still {0,0,0,0}
89 if (elem.data[0] == 0 && elem.data[1] == 0 && elem.data[2] == 0 && elem.data[3] == 0) {
90 stats.num_zeros++;
91 continue;
92 }
93
94 Fr standard = elem.from_montgomery_form();
95 size_t bytes_needed = min_bytes_for_value(standard);
96
97 if (bytes_needed <= 4) {
98 stats.fit_4bytes++;
99 stats.compressed_mem += 4;
100 } else if (bytes_needed <= 8) {
101 stats.fit_8bytes++;
102 stats.compressed_mem += 8;
103 } else if (bytes_needed <= 16) {
104 stats.fit_16bytes++;
105 stats.compressed_mem += 16;
106 } else {
107 stats.fit_32bytes++;
108 stats.compressed_mem += 32;
109 }
110 }
111
112 // Accumulate totals
113 totals.alloc_size += stats.alloc_size;
114 totals.virtual_size += stats.virtual_size;
115 totals.num_zeros += stats.num_zeros;
116 totals.fit_4bytes += stats.fit_4bytes;
117 totals.fit_8bytes += stats.fit_8bytes;
118 totals.fit_16bytes += stats.fit_16bytes;
119 totals.fit_32bytes += stats.fit_32bytes;
120 totals.actual_mem += stats.actual_mem;
121 totals.compressed_mem += stats.compressed_mem;
122
123 all_stats.push_back(std::move(stats));
124 }
125
126 // Format and print the report
127 auto mb = [](auto bytes) { return static_cast<double>(bytes) / (1024.0 * 1024.0); };
128
129 std::ostringstream oss;
130 oss << "\n=== Polynomial Memory Analysis ===\n";
131 oss << std::left << std::setw(36) << "Polynomial"
132 << " | " << std::right << std::setw(10) << "AllocSize"
133 << " | " << std::setw(10) << "Zeros"
134 << " | " << std::setw(10) << "<=4B"
135 << " | " << std::setw(10) << "<=8B"
136 << " | " << std::setw(10) << "<=16B"
137 << " | " << std::setw(10) << "<=32B"
138 << " | " << std::setw(10) << "Mem(MB)"
139 << " | " << std::setw(10) << "Compr(MB)"
140 << "\n";
141 oss << std::string(140, '-') << "\n";
142
143 auto print_row = [&](const PolyStats& s) {
144 if (s.alloc_size == 0 && s.name != "TOTAL") {
145 return; // skip empty polynomials
146 }
147 oss << std::left << std::setw(36) << s.name << " | " << std::right << std::setw(10) << s.alloc_size << " | "
148 << std::setw(10) << s.num_zeros << " | " << std::setw(10) << s.fit_4bytes << " | " << std::setw(10)
149 << s.fit_8bytes << " | " << std::setw(10) << s.fit_16bytes << " | " << std::setw(10) << s.fit_32bytes
150 << " | " << std::setw(10) << std::fixed << std::setprecision(2) << mb(s.actual_mem) << " | "
151 << std::setw(10) << std::fixed << std::setprecision(2) << mb(s.compressed_mem) << "\n";
152 };
153
154 for (const auto& s : all_stats) {
155 print_row(s);
156 }
157 oss << std::string(140, '-') << "\n";
158 print_row(totals);
159
160 double savings_pct =
161 totals.actual_mem > 0 ? 100.0 * (1.0 - totals.compressed_mem / static_cast<double>(totals.actual_mem)) : 0.0;
162 oss << "\nTotal actual memory: " << std::fixed << std::setprecision(2) << mb(totals.actual_mem) << " MB\n";
163 oss << "Total compressed memory: " << std::fixed << std::setprecision(2) << mb(totals.compressed_mem) << " MB\n";
164 oss << "Potential savings: " << std::fixed << std::setprecision(1) << savings_pct << "%\n";
165
166 info(oss.str());
167}
168
169} // namespace bb
#define info(...)
Definition log.hpp:93
typename ECCVMFlavor::ProverPolynomials ProverPolynomials
Entry point for Barretenberg command-line interface.
Definition api.hpp:5
void analyze_prover_polynomials(ProverPolynomials &polynomials)
Analyze prover polynomials and print per-polynomial statistics about value sizes.
size_t min_bytes_for_value(const Fr &val)
Compute the minimum number of bytes needed to represent a field element's value.
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
std::string to_string(bb::avm2::ValueTag tag)
std::string name
Curve::ScalarField Fr
std::byte * data
BB_INLINE constexpr field from_montgomery_form() const noexcept