Skip to content

Commit 793e76c

Browse files
committed
perf: avoid checked division
1 parent eb18ae8 commit 793e76c

File tree

5 files changed

+110
-238
lines changed

5 files changed

+110
-238
lines changed

sqrt-gas-usage.log

Lines changed: 36 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,54 @@
11
No files changed, compilation skipped
22
Script ran successfully.
3-
Gas used: 500474424
3+
Gas used: 410409484
44

55
== Logs ==
66
===== all 8-bit numbers =====
7-
total gas used = 163529 / 256
8-
minimum = 74, 641, ...
9-
quartiles = ..., 641.0, ..., 641.0, ..., 641.0, ...
10-
average = 638.7 ± 35.3
11-
maximum = ..., 641, 641
7+
total gas used = 113549 / 256
8+
minimum = 74, 445, ...
9+
quartiles = ..., 445.0, ..., 445.0, ..., 445.0, ...
10+
average = 443.5 ± 23.1
11+
maximum = ..., 445, 445
1212

1313
===== all 16-bit numbers =====
14-
total gas used = 42008009 / 65536
15-
minimum = 74, 641, ...
16-
quartiles = ..., 641.0, ..., 641.0, ..., 641.0, ...
17-
average = 640.9 ± 2.2
18-
maximum = ..., 641, 641
14+
total gas used = 29163149 / 65536
15+
minimum = 74, 445, ...
16+
quartiles = ..., 445.0, ..., 445.0, ..., 445.0, ...
17+
average = 444.9 ± 1.4
18+
maximum = ..., 445, 445
1919

2020
===== all powers of two =====
21-
total gas used = 164096 / 256
22-
minimum = 641, 641, ...
23-
quartiles = ..., 641.0, ..., 641.0, ..., 641.0, ...
24-
average = 641.0 ± 0.0
25-
maximum = ..., 641, 641
21+
total gas used = 113920 / 256
22+
minimum = 445, 445, ...
23+
quartiles = ..., 445.0, ..., 445.0, ..., 445.0, ...
24+
average = 445.0 ± 0.0
25+
maximum = ..., 445, 445
2626

2727
===== almost powers of two =====
28-
total gas used = 163529 / 256
29-
minimum = 74, 641, ...
30-
quartiles = ..., 641.0, ..., 641.0, ..., 641.0, ...
31-
average = 638.7 ± 35.3
32-
maximum = ..., 641, 641
28+
total gas used = 113549 / 256
29+
minimum = 74, 445, ...
30+
quartiles = ..., 445.0, ..., 445.0, ..., 445.0, ...
31+
average = 443.5 ± 23.1
32+
maximum = ..., 445, 445
3333

3434
===== randomized values =====
35-
total gas used = 168034304 / 262144
36-
minimum = 641, 641, ...
37-
quartiles = ..., 641.0, ..., 641.0, ..., 641.0, ...
38-
average = 641.0 ± 0.0
39-
maximum = ..., 641, 641
35+
total gas used = 116654080 / 262144
36+
minimum = 445, 445, ...
37+
quartiles = ..., 445.0, ..., 445.0, ..., 445.0, ...
38+
average = 445.0 ± 0.0
39+
maximum = ..., 445, 445
4040

4141
===== uint16 * 1e18 =====
42-
total gas used = 42007935 / 65535
43-
minimum = 641, 641, ...
44-
quartiles = ..., 641.0, ..., 641.0, ..., 641.0, ...
45-
average = 641.0 ± 0.0
46-
maximum = ..., 641, 641
42+
total gas used = 29163075 / 65535
43+
minimum = 445, 445, ...
44+
quartiles = ..., 445.0, ..., 445.0, ..., 445.0, ...
45+
average = 445.0 ± 0.0
46+
maximum = ..., 445, 445
4747

4848
===== uint16 * 1e18 * 1e18 =====
49-
total gas used = 42007935 / 65535
50-
minimum = 641, 641, ...
51-
quartiles = ..., 641.0, ..., 641.0, ..., 641.0, ...
52-
average = 641.0 ± 0.0
53-
maximum = ..., 641, 641
49+
total gas used = 29163075 / 65535
50+
minimum = 445, 445, ...
51+
quartiles = ..., 445.0, ..., 445.0, ..., 445.0, ...
52+
average = 445.0 ± 0.0
53+
maximum = ..., 445, 445
5454

src/Common.sol

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -603,19 +603,17 @@ function sqrt(uint256 x) pure returns (uint256 result) {
603603
// most 128 bits, since it is the square root of a uint256. Newton's method converges quadratically (precision
604604
// doubles at every iteration). We thus need at most 7 iteration to turn our partial result with one bit of
605605
// precision into the expected uint128 result.
606-
unchecked {
607-
result = (result + x / result) >> 1;
608-
result = (result + x / result) >> 1;
609-
result = (result + x / result) >> 1;
610-
result = (result + x / result) >> 1;
611-
result = (result + x / result) >> 1;
612-
result = (result + x / result) >> 1;
613-
result = (result + x / result) >> 1;
606+
assembly ("memory-safe") {
607+
result := shr(1, add(result, div(x, result)))
608+
result := shr(1, add(result, div(x, result)))
609+
result := shr(1, add(result, div(x, result)))
610+
result := shr(1, add(result, div(x, result)))
611+
result := shr(1, add(result, div(x, result)))
612+
result := shr(1, add(result, div(x, result)))
613+
result := shr(1, add(result, div(x, result)))
614614

615615
// If x is not a perfect square, round the result toward zero.
616-
assembly ("memory-safe") {
617-
result := sub(result, gt(result, div(x, result)))
618-
}
616+
result := sub(result, gt(result, div(x, result)))
619617
}
620618
}
621619

z-gas-snapshot.log

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -123,8 +123,8 @@ Frac_Unit_Test:test_Frac() (gas: 481713)
123123
Frac_Unit_Test:test_Frac_Negative() (gas: 481714)
124124
Frac_Unit_Test:test_Frac_Zero() (gas: 3527)
125125
Frac_Unit_Test:test_Frac_Zero() (gas: 3645)
126-
Gm_Unit_Test:test_Gm() (gas: 1414253)
127-
Gm_Unit_Test:test_Gm() (gas: 787447)
126+
Gm_Unit_Test:test_Gm() (gas: 1410529)
127+
Gm_Unit_Test:test_Gm() (gas: 785487)
128128
Gm_Unit_Test:test_Gm_OneOperandZero() (gas: 109685)
129129
Gm_Unit_Test:test_Gm_OneOperandZero() (gas: 109708)
130130
Gm_Unit_Test:test_RevertWhen_ProductNegative_A() (gas: 3881)
@@ -254,8 +254,8 @@ SD59x18_Helpers_Fuzz_Test:testFuzz_Xor(int256,int256) (runs: 256, μ: 4580, ~: 4
254254
Sqrt_Unit_Test:test_RevertWhen_GtMaxPermitted() (gas: 3725)
255255
Sqrt_Unit_Test:test_RevertWhen_GtMaxPermitted() (gas: 3929)
256256
Sqrt_Unit_Test:test_RevertWhen_Negative() (gas: 3611)
257-
Sqrt_Unit_Test:test_Sqrt() (gas: 815412)
258-
Sqrt_Unit_Test:test_Sqrt() (gas: 817144)
257+
Sqrt_Unit_Test:test_Sqrt() (gas: 812472)
258+
Sqrt_Unit_Test:test_Sqrt() (gas: 814204)
259259
Sqrt_Unit_Test:test_Sqrt_Zero() (gas: 3687)
260260
Sqrt_Unit_Test:test_Sqrt_Zero() (gas: 3805)
261261
UD21x18_Casting_Fuzz_Test:testFuzz_IntoSD59x18(uint128) (runs: 256, μ: 3703, ~: 3703)

zasm/Msb.asm

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* "src/Common.sol":24452:24566 contract Msb {... */
1+
/* "src/Common.sol":24481:24595 contract Msb {... */
22
mstore(0x40, 0x80)
33
callvalue
44
dup1
@@ -18,7 +18,7 @@ tag_1:
1818
stop
1919

2020
sub_0: assembly {
21-
/* "src/Common.sol":24452:24566 contract Msb {... */
21+
/* "src/Common.sol":24481:24595 contract Msb {... */
2222
mstore(0x40, 0x80)
2323
callvalue
2424
dup1
@@ -37,7 +37,7 @@ sub_0: assembly {
3737
jumpi
3838
tag_2:
3939
revert(0x00, 0x00)
40-
/* "src/Common.sol":24471:24564 function run(uint256 x) external pure returns (uint256 result) {... */
40+
/* "src/Common.sol":24500:24593 function run(uint256 x) external pure returns (uint256 result) {... */
4141
tag_3:
4242
tag_4
4343
tag_5
@@ -151,7 +151,7 @@ sub_0: assembly {
151151
/* "src/Common.sol":13378:13413 or(result, lt(0x1, shr(result, x))) */
152152
or
153153
swap1
154-
/* "src/Common.sol":24471:24564 function run(uint256 x) external pure returns (uint256 result) {... */
154+
/* "src/Common.sol":24500:24593 function run(uint256 x) external pure returns (uint256 result) {... */
155155
jump
156156
tag_4:
157157
mload(0x40)
@@ -163,7 +163,7 @@ sub_0: assembly {
163163
0x20
164164
/* "#utility.yul":318:336 */
165165
add
166-
/* "src/Common.sol":24471:24564 function run(uint256 x) external pure returns (uint256 result) {... */
166+
/* "src/Common.sol":24500:24593 function run(uint256 x) external pure returns (uint256 result) {... */
167167
mload(0x40)
168168
dup1
169169
swap2
@@ -205,5 +205,5 @@ sub_0: assembly {
205205
pop
206206
jump // out
207207

208-
auxdata: 0xa26469706673582212207f6fdd0bbc77550c56baeb70f720bc4580bf36ce5597a717119fa030c366a44664736f6c634300081e0033
208+
auxdata: 0xa264697066735822122060f957b63f416ddd273f6cf69c2c8a3c1b9059d80d361027be9e5cc5f7aea87e64736f6c634300081e0033
209209
}

0 commit comments

Comments
 (0)