diff --git a/packages/schema-type/gas-report.json b/packages/schema-type/gas-report.json new file mode 100644 index 0000000000..79ce1f0213 --- /dev/null +++ b/packages/schema-type/gas-report.json @@ -0,0 +1,110 @@ +[ + { + "file": "test/solidity/SchemaType.t.sol", + "test": "testGas", + "name": "getStaticByteLength: uint8", + "gasUsed": 124 + }, + { + "file": "test/solidity/SchemaType.t.sol", + "test": "testGas", + "name": "getStaticByteLength: uint32", + "gasUsed": 123 + }, + { + "file": "test/solidity/SchemaType.t.sol", + "test": "testGas", + "name": "getStaticByteLength: uint256", + "gasUsed": 123 + }, + { + "file": "test/solidity/SchemaType.t.sol", + "test": "testGas", + "name": "getStaticByteLength: int8", + "gasUsed": 123 + }, + { + "file": "test/solidity/SchemaType.t.sol", + "test": "testGas", + "name": "getStaticByteLength: int32", + "gasUsed": 123 + }, + { + "file": "test/solidity/SchemaType.t.sol", + "test": "testGas", + "name": "getStaticByteLength: int256", + "gasUsed": 123 + }, + { + "file": "test/solidity/SchemaType.t.sol", + "test": "testGas", + "name": "getStaticByteLength: bytes1", + "gasUsed": 123 + }, + { + "file": "test/solidity/SchemaType.t.sol", + "test": "testGas", + "name": "getStaticByteLength: bytes4", + "gasUsed": 123 + }, + { + "file": "test/solidity/SchemaType.t.sol", + "test": "testGas", + "name": "getStaticByteLength: bytes32", + "gasUsed": 123 + }, + { + "file": "test/solidity/SchemaType.t.sol", + "test": "testGas", + "name": "getStaticByteLength: bool", + "gasUsed": 123 + }, + { + "file": "test/solidity/SchemaType.t.sol", + "test": "testGas", + "name": "getStaticByteLength: address", + "gasUsed": 165 + }, + { + "file": "test/solidity/SchemaType.t.sol", + "test": "testGas", + "name": "getStaticByteLength: uint8[]", + "gasUsed": 166 + }, + { + "file": "test/solidity/SchemaType.t.sol", + "test": "testGas", + "name": "getStaticByteLength: uint32[]", + "gasUsed": 166 + }, + { + "file": "test/solidity/SchemaType.t.sol", + "test": "testGas", + "name": "getStaticByteLength: uint256[]", + "gasUsed": 166 + }, + { + "file": "test/solidity/SchemaType.t.sol", + "test": "testGas", + "name": "getStaticByteLength: int256[]", + "gasUsed": 166 + }, + { + "file": "test/solidity/SchemaType.t.sol", + "test": "testGas", + "name": "getStaticByteLength: bytes32[]", + "gasUsed": 166 + }, + { + "file": "test/solidity/SchemaType.t.sol", + "test": "testGas", + "name": "getStaticByteLength: bytes", + "gasUsed": 166 + }, + { + "file": "test/solidity/SchemaType.t.sol", + "test": "testGas", + "name": "getStaticByteLength: string", + "gasUsed": 166 + } +] diff --git a/packages/schema-type/package.json b/packages/schema-type/package.json index 274665ff9d..1b3e609a9e 100644 --- a/packages/schema-type/package.json +++ b/packages/schema-type/package.json @@ -29,6 +29,7 @@ "clean": "pnpm run clean:js", "clean:js": "rimraf dist/typescript", "dev": "tsup --watch", + "gas-report": "mud-gas-report --save gas-report.json", "test": "vitest typecheck --run && vitest --run && forge test" }, "dependencies": { @@ -36,6 +37,7 @@ "viem": "1.1.7" }, "devDependencies": { + "@latticexyz/gas-report": "workspace:*", "ds-test": "https://github.com/dapphub/ds-test.git#c9ce3f25bde29fc5eb9901842bf02850dfd2d084", "forge-std": "https://github.com/foundry-rs/forge-std.git#b4f121555729b3afb3c5ffccb62ff4b6e2818fd3", "rimraf": "^3.0.2", diff --git a/packages/schema-type/remappings.txt b/packages/schema-type/remappings.txt index fff7781446..c4d992480e 100644 --- a/packages/schema-type/remappings.txt +++ b/packages/schema-type/remappings.txt @@ -1,2 +1,3 @@ ds-test/=node_modules/ds-test/src/ forge-std/=node_modules/forge-std/src/ +@latticexyz/=node_modules/@latticexyz/ diff --git a/packages/schema-type/src/solidity/SchemaType.sol b/packages/schema-type/src/solidity/SchemaType.sol index 7067cdaec1..17536170df 100644 --- a/packages/schema-type/src/solidity/SchemaType.sol +++ b/packages/schema-type/src/solidity/SchemaType.sol @@ -214,24 +214,17 @@ enum SchemaType { function getStaticByteLength(SchemaType schemaType) pure returns (uint256) { uint256 index = uint8(schemaType); - if (index < 32) { - // uint8-256 - return index + 1; - } else if (index < 64) { - // int8-256, offset by 32 - return index + 1 - 32; - } else if (index < 96) { - // bytes1-32, offset by 64 - return index + 1 - 64; - } - - // Other static types - if (schemaType == SchemaType.BOOL) { - return 1; + if (index < 97) { + // SchemaType enum elements are cyclically ordered for optimal static length lookup + // indexes: 00-31, 32-63, 64-95, 96, 97, ... + // lengths: 01-32, 01-32, 01-32, 01, 20, (the rest are 0s) + unchecked { + return (index & 31) + 1; + } } else if (schemaType == SchemaType.ADDRESS) { return 20; + } else { + // Return 0 for all dynamic types + return 0; } - - // Return 0 for all dynamic types - return 0; } diff --git a/packages/schema-type/test/solidity/SchemaType.t.sol b/packages/schema-type/test/solidity/SchemaType.t.sol index 12d0598732..3b7684e524 100644 --- a/packages/schema-type/test/solidity/SchemaType.t.sol +++ b/packages/schema-type/test/solidity/SchemaType.t.sol @@ -3,9 +3,10 @@ pragma solidity >=0.8.0; import { Test } from "forge-std/Test.sol"; import { stdError } from "forge-std/StdError.sol"; +import { GasReporter } from "@latticexyz/gas-report/src/GasReporter.sol"; import { SchemaType } from "../../src/solidity/SchemaType.sol"; -contract SchemaTypeTest is Test { +contract SchemaTypeTest is Test, GasReporter { uint256 internal constant SCHEMA_TYPE_LENGTH = 198; function testGetStaticByteLength() public { @@ -53,4 +54,66 @@ contract SchemaTypeTest is Test { vm.expectRevert(stdError.enumConversionError); SchemaType(SCHEMA_TYPE_LENGTH).getStaticByteLength(); } + + function testGas() public { + startGasReport("getStaticByteLength: uint8"); + SchemaType.UINT8.getStaticByteLength(); + endGasReport(); + startGasReport("getStaticByteLength: uint32"); + SchemaType.UINT32.getStaticByteLength(); + endGasReport(); + startGasReport("getStaticByteLength: uint256"); + SchemaType.UINT256.getStaticByteLength(); + endGasReport(); + + startGasReport("getStaticByteLength: int8"); + SchemaType.INT8.getStaticByteLength(); + endGasReport(); + startGasReport("getStaticByteLength: int32"); + SchemaType.INT32.getStaticByteLength(); + endGasReport(); + startGasReport("getStaticByteLength: int256"); + SchemaType.INT256.getStaticByteLength(); + endGasReport(); + + startGasReport("getStaticByteLength: bytes1"); + SchemaType.BYTES1.getStaticByteLength(); + endGasReport(); + startGasReport("getStaticByteLength: bytes4"); + SchemaType.BYTES4.getStaticByteLength(); + endGasReport(); + startGasReport("getStaticByteLength: bytes32"); + SchemaType.BYTES32.getStaticByteLength(); + endGasReport(); + + startGasReport("getStaticByteLength: bool"); + SchemaType.BOOL.getStaticByteLength(); + endGasReport(); + startGasReport("getStaticByteLength: address"); + SchemaType.ADDRESS.getStaticByteLength(); + endGasReport(); + + startGasReport("getStaticByteLength: uint8[]"); + SchemaType.UINT8_ARRAY.getStaticByteLength(); + endGasReport(); + startGasReport("getStaticByteLength: uint32[]"); + SchemaType.UINT32_ARRAY.getStaticByteLength(); + endGasReport(); + startGasReport("getStaticByteLength: uint256[]"); + SchemaType.UINT256_ARRAY.getStaticByteLength(); + endGasReport(); + + startGasReport("getStaticByteLength: int256[]"); + SchemaType.INT256_ARRAY.getStaticByteLength(); + endGasReport(); + startGasReport("getStaticByteLength: bytes32[]"); + SchemaType.BYTES32_ARRAY.getStaticByteLength(); + endGasReport(); + startGasReport("getStaticByteLength: bytes"); + SchemaType.BYTES.getStaticByteLength(); + endGasReport(); + startGasReport("getStaticByteLength: string"); + SchemaType.STRING.getStaticByteLength(); + endGasReport(); + } } diff --git a/packages/store/gas-report.json b/packages/store/gas-report.json index 03d8ac4b9e..de59342b6d 100644 --- a/packages/store/gas-report.json +++ b/packages/store/gas-report.json @@ -99,7 +99,7 @@ "file": "test/KeyEncoding.t.sol", "test": "testRegisterAndGetSchema", "name": "register KeyEncoding schema", - "gasUsed": 64686 + "gasUsed": 63192 }, { "file": "test/Mixed.t.sol", @@ -111,7 +111,7 @@ "file": "test/Mixed.t.sol", "test": "testRegisterAndGetSchema", "name": "register Mixed schema", - "gasUsed": 61218 + "gasUsed": 60210 }, { "file": "test/Mixed.t.sol", @@ -123,7 +123,7 @@ "file": "test/Mixed.t.sol", "test": "testSetAndGet", "name": "get record from Mixed", - "gasUsed": 13458 + "gasUsed": 13135 }, { "file": "test/PackedCounter.t.sol", @@ -153,7 +153,7 @@ "file": "test/Schema.t.sol", "test": "testEncodeDecodeSchema", "name": "encode schema with 6 entries [SchemaLib.encode]", - "gasUsed": 6040 + "gasUsed": 5639 }, { "file": "test/Schema.t.sol", @@ -195,7 +195,7 @@ "file": "test/Schema.t.sol", "test": "testValidate", "name": "validate schema", - "gasUsed": 18266 + "gasUsed": 16381 }, { "file": "test/Slice.t.sol", @@ -369,7 +369,7 @@ "file": "test/StoreCoreGas.t.sol", "test": "testAccessEmptyData", "name": "access static field of non-existing record", - "gasUsed": 2974 + "gasUsed": 2914 }, { "file": "test/StoreCoreGas.t.sol", @@ -423,7 +423,7 @@ "file": "test/StoreCoreGas.t.sol", "test": "testHooks", "name": "set static field on table with subscriber", - "gasUsed": 32051 + "gasUsed": 31943 }, { "file": "test/StoreCoreGas.t.sol", @@ -471,7 +471,7 @@ "file": "test/StoreCoreGas.t.sol", "test": "testRegisterAndGetSchema", "name": "StoreCore: register schema", - "gasUsed": 54869 + "gasUsed": 54509 }, { "file": "test/StoreCoreGas.t.sol", @@ -531,25 +531,25 @@ "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "set static field (1 slot)", - "gasUsed": 37985 + "gasUsed": 37925 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "get static field (1 slot)", - "gasUsed": 2975 + "gasUsed": 2915 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "set static field (overlap 2 slot)", - "gasUsed": 35007 + "gasUsed": 34887 }, { "file": "test/StoreCoreGas.t.sol", "test": "testSetAndGetField", "name": "get static field (overlap 2 slot)", - "gasUsed": 3875 + "gasUsed": 3755 }, { "file": "test/StoreCoreGas.t.sol", @@ -627,7 +627,7 @@ "file": "test/StoreMetadata.t.sol", "test": "testSetAndGet", "name": "get record from StoreMetadataTable", - "gasUsed": 12689 + "gasUsed": 12486 }, { "file": "test/StoreSwitch.t.sol", @@ -735,7 +735,7 @@ "file": "test/Vector2.t.sol", "test": "testRegisterAndGetSchema", "name": "register Vector2 schema", - "gasUsed": 57995 + "gasUsed": 57391 }, { "file": "test/Vector2.t.sol", @@ -747,6 +747,6 @@ "file": "test/Vector2.t.sol", "test": "testSetAndGet", "name": "get Vector2 record", - "gasUsed": 5090 + "gasUsed": 4970 } ] diff --git a/packages/world/gas-report.json b/packages/world/gas-report.json index 6b7808feea..8a8503e015 100644 --- a/packages/world/gas-report.json +++ b/packages/world/gas-report.json @@ -3,67 +3,67 @@ "file": "test/KeysInTableModule.t.sol", "test": "testInstallComposite", "name": "install keys in table module", - "gasUsed": 1286951 + "gasUsed": 1278450 }, { "file": "test/KeysInTableModule.t.sol", "test": "testInstallGas", "name": "install keys in table module", - "gasUsed": 1286951 + "gasUsed": 1278450 }, { "file": "test/KeysInTableModule.t.sol", "test": "testInstallGas", "name": "set a record on a table with keysInTableModule installed", - "gasUsed": 193905 + "gasUsed": 192836 }, { "file": "test/KeysInTableModule.t.sol", "test": "testInstallSingleton", "name": "install keys in table module", - "gasUsed": 1286951 + "gasUsed": 1278450 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookCompositeGas", "name": "install keys in table module", - "gasUsed": 1286951 + "gasUsed": 1278450 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookCompositeGas", "name": "change a composite record on a table with keysInTableModule installed", - "gasUsed": 30072 + "gasUsed": 29884 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookCompositeGas", "name": "delete a composite record on a table with keysInTableModule installed", - "gasUsed": 292632 + "gasUsed": 288706 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookGas", "name": "install keys in table module", - "gasUsed": 1286951 + "gasUsed": 1278450 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookGas", "name": "change a record on a table with keysInTableModule installed", - "gasUsed": 28686 + "gasUsed": 28498 }, { "file": "test/KeysInTableModule.t.sol", "test": "testSetAndDeleteRecordHookGas", "name": "delete a record on a table with keysInTableModule installed", - "gasUsed": 153524 + "gasUsed": 151360 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testGetKeysWithValueGas", "name": "install keys with value module", - "gasUsed": 626518 + "gasUsed": 623327 }, { "file": "test/KeysWithValueModule.t.sol", @@ -81,79 +81,79 @@ "file": "test/KeysWithValueModule.t.sol", "test": "testInstall", "name": "install keys with value module", - "gasUsed": 626518 + "gasUsed": 623327 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testInstall", "name": "set a record on a table with KeysWithValueModule installed", - "gasUsed": 165629 + "gasUsed": 165159 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetAndDeleteRecordHook", "name": "install keys with value module", - "gasUsed": 626518 + "gasUsed": 623327 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetAndDeleteRecordHook", "name": "change a record on a table with KeysWithValueModule installed", - "gasUsed": 135282 + "gasUsed": 134812 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetAndDeleteRecordHook", "name": "delete a record on a table with KeysWithValueModule installed", - "gasUsed": 54297 + "gasUsed": 54015 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetField", "name": "install keys with value module", - "gasUsed": 626518 + "gasUsed": 623327 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetField", "name": "set a field on a table with KeysWithValueModule installed", - "gasUsed": 173712 + "gasUsed": 173182 }, { "file": "test/KeysWithValueModule.t.sol", "test": "testSetField", "name": "change a field on a table with KeysWithValueModule installed", - "gasUsed": 138070 + "gasUsed": 137540 }, { "file": "test/query.t.sol", "test": "testCombinedHasHasValueNotQuery", "name": "CombinedHasHasValueNotQuery", - "gasUsed": 169289 + "gasUsed": 163229 }, { "file": "test/query.t.sol", "test": "testCombinedHasHasValueQuery", "name": "CombinedHasHasValueQuery", - "gasUsed": 79072 + "gasUsed": 77052 }, { "file": "test/query.t.sol", "test": "testCombinedHasNotQuery", "name": "CombinedHasNotQuery", - "gasUsed": 233194 + "gasUsed": 222589 }, { "file": "test/query.t.sol", "test": "testCombinedHasQuery", "name": "CombinedHasQuery", - "gasUsed": 146486 + "gasUsed": 139921 }, { "file": "test/query.t.sol", "test": "testCombinedHasValueNotQuery", "name": "CombinedHasValueNotQuery", - "gasUsed": 145184 + "gasUsed": 139124 }, { "file": "test/query.t.sol", @@ -165,19 +165,19 @@ "file": "test/query.t.sol", "test": "testHasQuery", "name": "HasQuery", - "gasUsed": 33097 + "gasUsed": 31582 }, { "file": "test/query.t.sol", "test": "testHasQuery1000Keys", "name": "HasQuery with 1000 keys", - "gasUsed": 11312135 + "gasUsed": 10806630 }, { "file": "test/query.t.sol", "test": "testHasQuery100Keys", "name": "HasQuery with 100 keys", - "gasUsed": 1060038 + "gasUsed": 1009033 }, { "file": "test/query.t.sol", @@ -189,132 +189,132 @@ "file": "test/query.t.sol", "test": "testNotValueQuery", "name": "NotValueQuery", - "gasUsed": 72252 + "gasUsed": 70232 }, { "file": "test/SnapSyncModule.t.sol", "test": "testSnapSyncGas", "name": "Call snap sync on a table with 1 record", - "gasUsed": 43866 + "gasUsed": 42620 }, { "file": "test/SnapSyncModule.t.sol", "test": "testSnapSyncGas", "name": "Call snap sync on a table with 2 records", - "gasUsed": 62553 + "gasUsed": 60802 }, { "file": "test/UniqueEntityModule.t.sol", "test": "testInstall", "name": "install unique entity module", - "gasUsed": 824003 + "gasUsed": 818196 }, { "file": "test/UniqueEntityModule.t.sol", "test": "testInstall", "name": "get a unique entity nonce (non-root module)", - "gasUsed": 73377 + "gasUsed": 72422 }, { "file": "test/UniqueEntityModule.t.sol", "test": "testInstallRoot", "name": "installRoot unique entity module", - "gasUsed": 794078 + "gasUsed": 789214 }, { "file": "test/UniqueEntityModule.t.sol", "test": "testInstallRoot", "name": "get a unique entity nonce (root module)", - "gasUsed": 73377 + "gasUsed": 72422 }, { "file": "test/World.t.sol", "test": "testDeleteRecord", "name": "Delete record", - "gasUsed": 16152 + "gasUsed": 16058 }, { "file": "test/World.t.sol", "test": "testPushToField", "name": "Push data to the table", - "gasUsed": 96511 + "gasUsed": 96417 }, { "file": "test/World.t.sol", "test": "testRegisterFallbackSystem", "name": "Register a fallback system", - "gasUsed": 87012 + "gasUsed": 85624 }, { "file": "test/World.t.sol", "test": "testRegisterFallbackSystem", "name": "Register a root fallback system", - "gasUsed": 78196 + "gasUsed": 76808 }, { "file": "test/World.t.sol", "test": "testRegisterFunctionSelector", "name": "Register a function selector", - "gasUsed": 107607 + "gasUsed": 106219 }, { "file": "test/World.t.sol", "test": "testRegisterNamespace", "name": "Register a new namespace", - "gasUsed": 161669 + "gasUsed": 160613 }, { "file": "test/World.t.sol", "test": "testRegisterRootFunctionSelector", "name": "Register a root function selector", - "gasUsed": 94099 + "gasUsed": 92711 }, { "file": "test/World.t.sol", "test": "testRegisterTable", "name": "Register a new table in the namespace", - "gasUsed": 262388 + "gasUsed": 260715 }, { "file": "test/World.t.sol", "test": "testSetField", "name": "Write data to a table field", - "gasUsed": 44813 + "gasUsed": 44625 }, { "file": "test/World.t.sol", "test": "testSetMetadata", "name": "Set metadata", - "gasUsed": 283384 + "gasUsed": 282542 }, { "file": "test/World.t.sol", "test": "testSetRecord", "name": "Write data to the table", - "gasUsed": 42690 + "gasUsed": 42502 }, { "file": "test/WorldDynamicUpdate.t.sol", "test": "testPopFromField", "name": "pop 1 address (cold)", - "gasUsed": 38043 + "gasUsed": 37949 }, { "file": "test/WorldDynamicUpdate.t.sol", "test": "testPopFromField", "name": "pop 1 address (warm)", - "gasUsed": 22833 + "gasUsed": 22739 }, { "file": "test/WorldDynamicUpdate.t.sol", "test": "testUpdateInField", "name": "updateInField 1 item (cold)", - "gasUsed": 40377 + "gasUsed": 40283 }, { "file": "test/WorldDynamicUpdate.t.sol", "test": "testUpdateInField", "name": "updateInField 1 item (warm)", - "gasUsed": 25579 + "gasUsed": 25485 } ] diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c11f505d2c..b41b71f7a0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -755,6 +755,9 @@ importers: specifier: 1.1.7 version: 1.1.7(typescript@5.0.4) devDependencies: + '@latticexyz/gas-report': + specifier: workspace:* + version: link:../gas-report ds-test: specifier: https://github.com/dapphub/ds-test.git#c9ce3f25bde29fc5eb9901842bf02850dfd2d084 version: github.com/dapphub/ds-test/c9ce3f25bde29fc5eb9901842bf02850dfd2d084