Skip to content

Entity Model Features

BonsUnleashed edited this page Oct 7, 2026 · 3 revisions

Entity Model Features

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.

Four controls for Entity Model Features 3.2.4 (mod id entity_model_features, LGPL-3.0), all client-side: block-entity type strings built once, the animation compiler's variable lists indexed, model-part lookups remembered during each model setup, and cube vertices transformed in one reused vector. The sections distinguish per-call benchmarks from complete frame measurements. 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
emf_block_entity_type_string Entity Model Features 3.2.4 CLIENT 1.0.21 opt
emf_cube_vertex_vector Entity Model Features 3.2.4 CLIENT 1.0.29 opt
emf_hierarchical_id_memo Entity Model Features 3.2.4 CLIENT 1.0.26 opt
emf_variable_index Entity Model Features 3.2.4 CLIENT 1.0.26 opt

emf_block_entity_type_string

Since: 1.0.21 · Mixin: BlockEntityTypeStringMixin · Helper: bons.furious.patch.emf.TypeStrings Patched: traben.entity_model_features.models.animation.state.EMFEntityRenderStateViaReference.typeString

What upstream did. EMF looks up the model variation roots of every rendered block entity by a type string, which for block entities it rebuilt every frame as BlockEntityType.toString() (class name, @, identity hash) and then hashed again as a map key.

What the patch does. Redirects that one call to a helper that builds the string once per BlockEntityType and returns the same equal string afterwards, but only when the block entity uses EMF's own BlockEntity implementation of the method and the type's class keeps Object's toString, hashCode and equals (checked once per class through MethodHandles). Entities, and any block entity or type class with its own versions, keep EMF's method. No EMF code is copied.

What stays the same. The string, and therefore the map lookups: in the 1.0.21 client run all 376 loaded block entities gave the same string through the patch as through EMF's method, all of them on the fast path.

Measured. 69 → 10 ns per rendered block entity; 0.19 % of the render thread in a storage-heavy client profile.


emf_hierarchical_id_memo

Since: 1.0.26 · Target: Entity Model Features 3.2.4 · Side: CLIENT · Kind: opt

Mixins: HierarchicalIdMemoMixin

While EMF sets up a model variant's animations it looks up the part named at the start of every animation line and every part an expression uses. Most lines of Fresh Animations' models set variables (var., varb.), not parts, so each of those lookups missed twice and then went through every part name with several string operations, hundreds of times per variant. Within one setup the answers for that setup's part list are now remembered by name, a miss included. The part list is built before the first lookup and only read afterwards, so every answer is the one EMF computes; any other list, and every lookup outside a setup, goes to EMF's own code.

Measured: in game, 692 000 of its lookups checked against a fresh original lookup all returned the same part; with emf_variable_index it took the entity-renderer rebuild from 15.1-16.6 s to 8.8 s. Offline over all 253 animated models: identical answers; the lookups of one player variant setup 4.7 -> 0.11 ms.


emf_variable_index

Since: 1.0.26 · Target: Entity Model Features 3.2.4 · Side: CLIENT · Kind: opt

Mixins: VariableIndexMixin

EMF compiles every animated entity model variant into bytecode at each resource reload. Its variable handler kept the variable names in two lists, answered every variable reference with two list scans, and after every animation line compared every number variable with every true/false variable to check that no name was both. With Fresh Animations' player models (370-840 lines, about 500 and 90 names per variant, compiled again for every renderer that bakes a player layer) that was millions of string comparisons per variant. The handler now keeps two name-to-slot maps beside the lists and remembers whether a name ever landed in both: the same slots, the same lists and the same errors in the same order.

Measured: in game with Fresh Animations and its add-ons, rebuilding the entity renderers (every EMF animation compile, as at a resource reload) took 8.8 s instead of 15.1-16.6 s with this switch and emf_hierarchical_id_memo together, and 5.1 million of its answers checked against the original in game all matched. Offline on all 253 animated models plus 3 000 random sequences: identical slots, emitted code, lists and errors.


emf_cube_vertex_vector

Since: 1.0.29 · Target: Entity Model Features 3.2.4 · Side: CLIENT · Kind: opt

Mixin: EmfCubeVertexVectorMixin

EMF model cubes transform their vertices in one reused vector. Entity Model Features draws its custom model cubes (Fresh Animations and other EMF models) by creating a new vector for every vertex of every cube on every frame, and in play the JVM does not optimise it away: with many mobs on screen it was the largest single source of the render thread's garbage. On the render thread each vertex now goes through one reused vector holding the same four numbers, transformed by EMF's own call, so every vertex gets the same position. Other threads still create their own vector.

Measured: offline on the transformed class 1,083,028 vertex calls (60,000 cube renders, nested renders and another thread included) identical to the bit; 32 -> 0 bytes and 13.3 -> 11.5 ns per vertex with the client's ZGC when the JVM keeps the vector (as it does in play), no change when it removes it. EMF allocated 710 MB of these vectors in 38 s, 14.9% of the render thread's allocation, in the 1.0.26 client recording's crowded-mobs window.

Bons and Furious

Minecraft 1.20.1 / Forge 1.0.34

Compatibility

Controls by mod

Links

Clone this wiki locally