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