Repository navigation
Curios API
Minecraft 1.20.1 / Forge: this page documents that build and its measurements. For the separate 170-control Minecraft 1.21.1 port, see Minecraft 1.21.1 NeoForge.
Six controls for Curios API 5.14.1+1.20.1 (mod id curios): slot lookups with one map probe, a modifier map that is only allocated when used, a quick answer for other mods' capability queries, a tick skip for entities without slots, tag keys that are kept, and one fix that stops two threads from corrupting the shared slot caches. Curios is a shared library, so a saving per call is multiplied by every mod that uses it. Every switch checks the code it would change against the tested build; another build is left untouched with one WARN line (see How the patches are applied).
| Key | Target | Side | Since | Kind | Result |
|---|---|---|---|---|---|
curios_foreign_capability_fast_path |
Curios API 5.14.1+1.20.1 | BOTH | 1.0.21 | opt | other capabilities skip the slot lookup |
curios_lazy_modifier_map |
Curios API 5.14.1+1.20.1 | BOTH | 1.0.8 | opt | 392 → 0 B when idle |
curios_slot_map_lookup |
Curios API 5.14.1+1.20.1 | BOTH | 1.0.6 | opt | 12.76 → 10.16 ns |
curios_slotless_tick_skip |
Curios API 5.14.1+1.20.1 | BOTH | 1.0.28 | opt | 409 → 9 ns per tick handler call with 25 capability providers |
curios_tag_predicate_keys |
Curios API 5.14.1+1.20.1 | BOTH | 1.0.30 | opt | 161 → 41 ns and 96 → 0 bytes per slot tag test |
curios_thread_safe_caches |
Curios API 5.14.1+1.20.1 | BOTH | 1.0.30 | fix | fix: 11,439 errors with 8 threads before, none after |
Since: 1.0.6 · Script (1.0.19 and earlier): furious6-CuriosEntityManager.js
Patched: top.theillusivec4.curios.common.data.CuriosEntityManager.getEntitySlots
Mixin (since 1.0.20): CuriosEntityManagerMixin
What upstream did. Probed the immutable entity-slot map twice (containsKey, then get).
What the patch does. A single get for ImmutableMap instances, returning the same map or the same empty map; any other map implementation keeps the original two-probe path.
What stays the same. Exact returned map identity, missing and null keys, API routes, reload and synchronisation.
Measured. Successful lookup with 96 entries: 12.76 → 10.16 ns on the client; the server case was neutral because the JIT already removed the second probe; zero allocation both ways.
Since: 1.0.8 · Script (1.0.19 and earlier): furious8-curios.js
Patched: top.theillusivec4.curios.common.capability.CurioInventoryCapability$CurioInventoryWrapper.clearCachedSlotModifiers
Mixin (since 1.0.20): CurioInventoryWrapperMixin
What upstream did. Constructed a Guava HashMultimap with its bookkeeping and view wrappers even when no slot attribute would be added, on every call.
What the patch does. Collects slot modifiers lazily in the same underlying Guava-created HashMap/HashSets (expected sizes 12/2) and skips the final traversal when nothing was accumulated.
What stays the same. Every inventory traversal, attribute event, removal callback and ordering; nothing is cached across calls. 280,852 additional comparisons against Guava covered collisions, duplicates, nulls and iteration order.
Measured. No cached modifiers 64.88 → 20.52 ns and 392 → 0 B; cached modifiers with empty items 219.05 → 178.37 ns and 392 → 0 B; actual slot-modifier removal 7,820.68 → 7,288.03 ns and 24,904 → 24,040 B.
Since: 1.0.21 · Side: BOTH · Mixin: ForeignCapabilityMixin
Patched: top.theillusivec4.curios.common.capability.CurioInventoryCapability$Provider.getCapability
What upstream did. Curios attaches its capability provider to living entities, and Forge asks that provider about every capability anyone queries on such an entity. The provider looked up the entity's slot map first and only then checked whether the query was for the Curios inventory at all, so every other mod's capability query paid a slot-map lookup.
What the patch does. Returns LazyOptional.empty() at once for any capability other than the Curios inventory. That is the same empty singleton the original returns for such a query on both of its paths. Curios inventory queries run unchanged; the method body is otherwise Curios' own (LGPL-3.0).
What stays the same. The object returned for every capability: in the 1.0.21 client run the providers of the client player and of the server player returned the same object as the original logic for all 159 registered capabilities and for a null capability.
Measured. The slot-map lookup no longer runs for foreign queries; it was 0.25 % of the server thread and 0.09 % of the client render thread in profiles.
Since 1.0.34. Only for an entity that has a world. On a living entity built without one, Curios' slot lookup fails for every capability, and that failure is kept as it was.
Since: 1.0.28 · Target: Curios API 5.14.1+1.20.1 · Side: BOTH · Kind: opt
Mixins: CuriosEventHandlerSlotlessMixin, CapabilityProviderCuriosAccessor, LivingEntityCuriosStateMixin
Curios tick skips the lookup on entities without slots. Curios' tick handler runs for every living entity every tick and starts by looking up the Curios inventory: a walk over all of the entity's capability providers. For an entity type no datapack gives slots to (animals, fish, villagers, most modded mobs) Curios' own provider answers empty and the walk finds nothing. Once that walk has come back empty on an entity, the answer is reused while the type still has no slots and the entity keeps the same, valid capabilities. An entity on which another mod answers the inventory is never skipped, and a datapack reload that adds slots is seen at once.
Measured: 409 -> 9 ns per tick handler call with 25 capability providers, 16 -> 9 ns with Curios' provider alone, on real classes; 317,976 checks identical.
Since: 1.0.30 · Target: Curios API 5.14.1+1.20.1 · Side: BOTH · Kind: opt
Mixin: TagPredicateKeysMixin
Curios slot tag keys kept. Curios checks whether an item fits a slot with its built-in "curios:tag" test, which builds two resource locations and looks up two tag keys every time it runs. Every item tooltip runs it once per slot type of the player (14 here), and JEI's search index asks for the tooltip of every item when you join a world. Now the two tag keys are made once per slot id and kept; they are the very keys the test would build, and the item checks run as before, so every answer is the same. Slot ids that are not plain lowercase paths still build their keys every time, exactly as before.
Idea: found in our own join profile (Curios' tooltip handler was 12% of JEI's index build); no outside mod
Measured: offline on Curios' own classes, 188,081 checks identical (82,040 answers, 23,445 exceptions, 8 threads, tag reloads); the test took 161 -> 41 ns and 96 -> 0 bytes per call, one item tooltip's slot checks 2.7 -> 1.1 us.
Since: 1.0.30 · Target: Curios API 5.14.1+1.20.1 · Side: BOTH · Kind: fix
Mixins: SlotAttributeMapMixin, SlotUuidMapMixin
Curios: the shared slot-attribute and slot-UUID caches can no longer be corrupted by two threads. Curios keeps two plain hash maps, one object per slot type (the slot's attribute) and one UUID per slot, filled by whichever thread asks first. In single player the client asks while drawing item tooltips and the built-in server asks while equipment changes, so both threads can fill the same map at once. That can throw an error out of the middle of a tooltip or an equipment update, or lose an entry so that one slot type ends up with two attribute objects (bonuses added under one and removed under the other). Each map has a single method that reads and fills it; that method now runs under its own lock. The maps, the order of their calls and every answer stay exactly the same for a single thread, including unusual slot names, so nothing changes except that two threads take turns.
Measured: offline on Curios' own classes, 8 threads filling the caches together (300 rounds) gave 11,439 errors and 183 slot types with two attribute objects before the fix and none after; 17,179 single-thread checks identical (classes, names, UUIDs, which calls create a new object, map order).
Bons and Furious is licensed GPL-3.0-only with upstream notices retained. Target mod names identify compatibility targets and do not imply endorsement; their code, assets and licenses remain their authors' property. All measurements on this wiki are focused method, phase or reproduction measurements from the pack the mod was built for, taken on the historical build named in each entry; they are not whole-game FPS or TPS promises and are not additive.
Bons and Furious
Minecraft 1.20.1 / Forge 1.0.34
- Home
- Installation and configuration
- How the patches are applied
- All controls
- Measurements and caveats
- Whole-modpack benchmark
- Troubleshooting and log messages
- Generation context fixes
- Version history
Compatibility
- Compatibility
- Known conflicts and workarounds
- Tested mod list
- Redundant mods
- Compatibility and target versions
Controls by mod
- Minecraft (51)
- Forge (6)
- Ad Astra (1)
- Alex's Caves (4)
- Alex's Mobs (2)
- Almost Unified (1)
- AmbientSounds (3)
- Architectury API (1)
- Ars Nouveau (2)
- Artifacts (1)
- Better Combat (1)
- Bosses of Mass Destruction (1)
- Butterflies (1)
- ChunkSending (1)
- CIT Reforged (1)
- Citadel (1)
- CoFH Core (1)
- Colorwheel (1)
- Cooking for Blockheads (1)
- Create (4)
- Critters and Companions (1)
- Cryptic Foes (2)
- Cucumber (1)
- Curios API (6)
- Distant Horizons (17)
- Dungeons Delight (1)
- Dynamic Trees (2)
- Embeddium (13)
- Entity Model Features (4)
- Entity Texture Features (1)
- EntityCulling (1)
- FancyMenu (1)
- Farmer's Delight (2)
- FD Bosses (2)
- Fowl Play (2)
- Fusion (2)
- GeckoLib (5)
- Goblins Tyranny (2)
- Hostile Villages (2)
- Ice and Fire (6)
- ImmediatelyFast (3)
- Immersive Engineering (1)
- Jaden's Nether Expansion (1)
- JEI (7)
- Kiwi (1)
- L2 Library (2)
- Legendary Monsters (1)
- Lionfish API (2)
- ModernFix (4)
- Mowzie's Mobs (1)
- Mutant Monsters (1)
- Nether Depths Upgrade (1)
- Occult (1)
- Oculus (12)
- Oh The Biomes We've Gone (1)
- Particular (1)
- Pehkui (1)
- Pipez (2)
- Placebo (1)
- Presence Footsteps (1)
- Radium Re-Reforged (8)
- Regions Unexplored (1)
- Relics (2)
- Ribbits (1)
- Ryoamic Lights (2)
- Sake's Structures (1)
- Scorched (1)
- Scuba Gear (1)
- Simply Swords (1)
- SlashBlade: Resharped (1)
- Slice & Dice (1)
- Spawn (4)
- Storage Drawers (2)
- Structure Gel API (1)
- Structurify (3)
- TaCZ (2)
- TerraBlender (2)
- Terramity (1)
- Under the Moon (1)
- Valkyrien Skies (15)
- Trackwork model repair
- Living Engineering (moved out in 1.0.20)
Links