Skip to content

zeroize: remove internal use of optimization_barrier - #1535

Merged
tarcieri merged 1 commit into
masterfrom
zeroize/remove-internal-use-of-optimization-barrier
Sep 11, 2026
Merged

tarcieri merged 1 commit into
masterfrom
zeroize/remove-internal-use-of-optimization-barrier

Conversation

@tarcieri

@tarcieri tarcieri commented Sep 9, 2026

Copy link
Copy Markdown
Member

We replaced our previous use of compiler fences with optimization_barrier under the assumption it would be a zero-cost abstraction, but per #1504 that is not the case as it caused a performance regression.

The use of either of these was effectively redundant and a belt-and-suspenders defense as volatile writes alone are already sufficient to guarantee zeroization will not be removed by the compiler.

This removes the use of optimization_barrier to restore the previous performance.

Closes #1504.

@tarcieri
tarcieri force-pushed the zeroize/remove-internal-use-of-optimization-barrier branch from c788dab to e8fa876 Compare September 9, 2026 16:20
We replaced our previous use of compiler fences with
`optimization_barrier` under the assumption it would be a zero-cost
abstraction, but per #1504 that is not the case as it caused a
performance regression.

The use of either of these was effectively redundant and a
belt-and-suspenders defense as volatile writes alone are already
sufficient to guarantee zeroization will not be removed by the compiler.

This removes the use of `optimization_barrier` to restore the previous
performance.

Closes #1504.
@tarcieri
tarcieri force-pushed the zeroize/remove-internal-use-of-optimization-barrier branch from e8fa876 to e4f62e9 Compare September 9, 2026 16:21
@tarcieri

tarcieri commented Sep 9, 2026

Copy link
Copy Markdown
Member Author

@ctz if you can take a look it would be good to confirm this closes #1504

@tarcieri
tarcieri merged commit cfe22d1 into master Sep 11, 2026
27 checks passed
@tarcieri
tarcieri deleted the zeroize/remove-internal-use-of-optimization-barrier branch September 11, 2026 21:10
@ctz

ctz commented Sep 14, 2026

Copy link
Copy Markdown

@ctz if you can take a look it would be good to confirm this closes #1504

Sorry, I was at rustconf. Here's some quick micro-benchmarks that represent rustls's use of this crate, over this PR:


array_u8/zeroize/32     time:   [3.3618 ns 3.3792 ns 3.3971 ns]
                        thrpt:  [8.7730 GiB/s 8.8195 GiB/s 8.8650 GiB/s]
                 change:
                        time:   [−9.6335% −8.7241% −7.5098%] (p = 0.00 < 0.05)
                        thrpt:  [+8.1196% +9.5579% +10.660%]
                        Performance has improved.
Found 3 outliers among 100 measurements (3.00%)
  2 (2.00%) high mild
  1 (1.00%) high severe

array_u8/zeroize/64     time:   [6.6666 ns 6.7019 ns 6.7373 ns]
                        thrpt:  [8.8469 GiB/s 8.8936 GiB/s 8.9408 GiB/s]
                 change:
                        time:   [−77.116% −76.847% −76.491%] (p = 0.00 < 0.05)
                        thrpt:  [+325.36% +331.90% +336.98%]
                        Performance has improved.
Found 3 outliers among 100 measurements (3.00%)
  2 (2.00%) high mild
  1 (1.00%) high severe

vec_u8/zeroize/16       time:   [2.5408 ns 2.5478 ns 2.5580 ns]
                        thrpt:  [5.8253 GiB/s 5.8487 GiB/s 5.8648 GiB/s]
                 change:
                        time:   [−21.162% −19.126% −16.770%] (p = 0.00 < 0.05)
                        thrpt:  [+20.149% +23.649% +26.842%]
                        Performance has improved.
Found 9 outliers among 100 measurements (9.00%)
  3 (3.00%) low severe
  1 (1.00%) low mild
  2 (2.00%) high mild
  3 (3.00%) high severe

vec_u8/zeroize/64       time:   [7.3721 ns 7.3799 ns 7.3877 ns]
                        thrpt:  [8.0681 GiB/s 8.0766 GiB/s 8.0852 GiB/s]
                 change:
                        time:   [−27.878% −26.661% −25.086%] (p = 0.00 < 0.05)
                        thrpt:  [+33.486% +36.353% +38.653%]
                        Performance has improved.
Found 14 outliers among 100 measurements (14.00%)
  4 (4.00%) low severe
  2 (2.00%) low mild
  1 (1.00%) high mild
  7 (7.00%) high severe

vec_u8/zeroize/256      time:   [27.472 ns 27.511 ns 27.560 ns]
                        thrpt:  [8.6508 GiB/s 8.6662 GiB/s 8.6786 GiB/s]
                 change:
                        time:   [−30.545% −29.055% −27.623%] (p = 0.00 < 0.05)
                        thrpt:  [+38.165% +40.955% +43.977%]
                        Performance has improved.
Found 21 outliers among 100 measurements (21.00%)
  5 (5.00%) low severe
  1 (1.00%) low mild
  7 (7.00%) high mild
  8 (8.00%) high severe

vec_u8/zeroize/1024     time:   [120.00 ns 122.37 ns 124.72 ns]
                        thrpt:  [7.6466 GiB/s 7.7935 GiB/s 7.9474 GiB/s]
                 change:
                        time:   [−30.512% −28.709% −27.003%] (p = 0.00 < 0.05)
                        thrpt:  [+36.993% +40.270% +43.909%]
                        Performance has improved.
Found 7 outliers among 100 measurements (7.00%)
  4 (4.00%) high mild
  3 (3.00%) high severe

vec_u8/zeroize/4096     time:   [457.32 ns 467.62 ns 479.21 ns]
                        thrpt:  [7.9604 GiB/s 8.1576 GiB/s 8.3415 GiB/s]
                 change:
                        time:   [−33.776% −31.678% −29.397%] (p = 0.00 < 0.05)
                        thrpt:  [+41.637% +46.365% +51.002%]
                        Performance has improved.
Found 5 outliers among 100 measurements (5.00%)
  2 (2.00%) high mild
  3 (3.00%) high severe

vec_u8/zeroize/16384    time:   [1.8056 µs 1.8401 µs 1.8728 µs]
                        thrpt:  [8.1478 GiB/s 8.2922 GiB/s 8.4509 GiB/s]
                 change:
                        time:   [−33.422% −31.830% −30.571%] (p = 0.00 < 0.05)
                        thrpt:  [+44.032% +46.691% +50.200%]
                        Performance has improved.
Found 9 outliers among 100 measurements (9.00%)
  6 (6.00%) high mild
  3 (3.00%) high severe

With that said, against a baseline impl on [u8; 64] (fill(0) followed by a black_box which observes all values):

array_u8/baseline/64    time:   [823.77 ps 827.93 ps 832.22 ps]
                        thrpt:  [71.621 GiB/s 71.993 GiB/s 72.356 GiB/s]
Found 2 outliers among 100 measurements (2.00%)
  1 (1.00%) high mild
  1 (1.00%) high severe

There appears to be a lot of scope in this crate to further improve performance. That could be achieved without abandoning volatile writes, if that is the firm desire of the maintainers. For example, [u8; 64] would ideally be 8 x 64-bit volatile writes, rather than 64 x 8-bit volatile writes.

@newpavlov

Copy link
Copy Markdown
Member

For example, [u8; 64] would ideally be 8 x 64-bit volatile writes, rather than 64 x 8-bit volatile writes.

Unfortunately, AFAIK it is not possible without specialization or breaking changes.

@ctz

ctz commented Sep 14, 2026

Copy link
Copy Markdown

For very common types, I think this can be achieved with a similar trick to Hash::hash_slice() without specialisation or a breaking change.

Here's a prototype of this: ctz@e01ef4c (disclosure: slop). I don't plan to open a PR with this change, but it demonstrates the principle. The performance gain of this change on [u8; 64] is about 4.2x, and lags memset by about 2x.

@newpavlov

newpavlov commented Sep 14, 2026

Copy link
Copy Markdown
Member

Note that DefaultIsZeroes is a safe non-sealed trait, so it could be theoretically implemented for NonZero*-like types.

@tarcieri

Copy link
Copy Markdown
Member Author

We could potentially expose a bzero-like free function that accepts &mut [u8] or *mut u8 and uses an optimized implementation, sort of like zeroize_flat_type.

This particular case was unfortunately running into some bad interactions between the Iterator-based Zeroize impl for [T; N] and optimization_barrier.

(Sidebar: some upstream support from LLVM here would be nice)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

zeroize 1.8.2 -> 1.9.0 performance regression

3 participants