Operation Tiers
Different operators have different costs, and so does the operand: += and -= cost far more with a plain-number operand than between two values that already exist. Figures are for the default anti-cheat Compuon<int> on one x64 machine unless marked deferred; see the measurement note.
| Tier | Operations | Overhead ¹ | Notes |
|---|---|---|---|
| 0 | +, -, integer scalar *, << | 114 ns (x += y, both values built) | Cheap when both operands already exist. |
| 0 | +=, -= with a plain number or a temporary | 6.2 µs (x += 25), 6.6 µs (x -= Compuon<int>(25)) | Builds and destroys a temporary value; costs more than Tier 1. Integer-scalar * and << build none. |
| 1 | =, *, /, %, >>, &, |, ^, ~ | 5.9 µs (x = v) | Re-encodes the value. |
| 2 | ==, !=, <, >, <=, >= | not timed; a cache read took 0.2 ns | Reads the cached value of each side. |
Tier 0: 114 ns between built values
Addition, subtraction, integer-scalar multiplication and left shift update the protected value in place. Between two values that already exist, x += y took 114 ns, cheap enough for per-frame game logic. With a plain-number operand, += and -= first build a temporary protected value and destroy it afterwards: x += 25 took 6.2 µs and x -= Compuon<int>(25) 6.6 µs, more than a Tier 1 assignment. Integer-scalar *= and <<= take the plain number directly and build no temporary (not timed). In a per-frame path, build a fixed operand once and reuse it.¹
Compuon<int> hp(100); Compuon<int> regen(5); // built once, reused every tick Compuon<int> x(4); hp += regen; // both values built: 114 ns (x += y) hp += Compuon<int>(10); // temporary value per call: ~6.6 µs (x -= Compuon<int>(25)) hp -= 25; // plain number, same: ~6.2 µs (x += 25) x <<= 3; // Tier 0, not timed
Tier 1: 5.9 µs
Operations that re-encode the value from scratch. Assigning a plain number (x = v) took 5.9 µs; the other Tier 1 operators were not timed. Still usable per frame — 100 assignments come to about 0.59 ms, 3.5% of a 16.67 ms (60 Hz) frame.¹
Compuon<int> hp(100); Compuon<int> other(2); Compuon<int> mask(0x3F); hp = 50; // assignment: 5.9 µs (x = v) hp *= other; // multiply: Tier 1, not timed hp /= other; // division: Tier 1, not timed hp %= Compuon<int>(10); // modulo: Tier 1, not timed (plus a temporary value) hp >>= 1; // right shift: Tier 1, not timed hp &= mask; // bitwise AND/OR/XOR: Tier 1, not timed auto flipped = ~mask; // bitwise NOT (integer only): Tier 1, not timed
Tier 2: comparisons
Comparisons read the cached value of each side. They were not timed separately; a read of the cache took 0.2 ns, at the benchmark's resolution. Compare against a value that already exists or against a plain number: hp > Compuon<int>(0) first builds and destroys a temporary protected value, which took 6.1 µs on its own.¹
Compuon<int> hp(100); Compuon<int> other(100); bool dead = hp <= 0; // reads the cache bool same = hp == other; // reads both caches bool alive = hp > Compuon<int>(0); // builds a temporary value first
Deferred mode
Compuon<T, true>keeps no plaintext, so every read and every operation folds against the server's operand bundle, and a read then decodes. On the same machine a read (val()) took 37.1 µs, about 17 times verify() (2.2 µs); x += y took 30.7 µs, x += 25 75.9 µs and x = v 43.2 µs. A comparison reads each deferred side. Use deferred mode for values read occasionally, not every frame.¹
Performance Guidelines
¹ Measurement provenance: Compuon's internal operator benchmark (not yet in a released core), which times the operators as written on Compuon<int> and Compuon<int, true>, built with MSVC 19.51 x64 Release (/O2, LTCG link) against the Compuon core 0752031 library and run on one AMD Ryzen 7 5825U on 2026-09-28, with background load of about one core. Each figure is the median of three invocations of 9 runs. Min–max over the 27 runs: x += y 107–215 ns; x += 25 6,017–9,150 ns; x -= Compuon<int>(25) 6,327–9,276 ns; x = v 5,678–8,630 ns; cache read 0.2–0.5 ns; building and destroying a value 5,906–8,976 ns; verify() 2,098–3,964 ns; deferred val() 36,088–50,888 ns, x += y 29,813–42,663 ns, x += 25 73,575–105,403 ns, x = v 41,759–61,961 ns. Only the forms named were timed, and only on this CPU and compiler. They come from one build of the library, generated from one seed. Every SDK build comes from its own seed and times differently: on the same machine, builds from two other seeds took 113 ns and 366 ns for x += y, their other anti-cheat figures stayed within 14% of these, and their deferred figures were 0.6–1.1 times these. A re-run of the original build later the same day gave medians within 5% of these. Per-frame shares are the per-call median times 100, not a timed loop. An earlier revision of this page gave 340 ns for every Tier 0 op and 6.5 µs for Tier 1, from a single 2026-04-20 run on the same CPU model; the 340 ns was an add between two existing values, and that run put a compare at about 0.5 ns. Your numbers will differ with seed, CPU, compiler, and build flags — measure in your own build before committing to a budget.