---
title: "Performance"
description: "Six habits that keep tick and render callbacks cheap."
---

> Documentation Index
> Fetch the complete documentation index at: https://aesthetic-docs.pages.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Performance

Every script and everything it `require`s is compiled to JVM bytecode. There is nothing to
opt into; the rest is how the callbacks are written.

**Read settings once.** Every `setting:get()` crosses into Java. In a hot callback, copy the
values into locals first:

```lua
module:event("render_2d", function(render)
local argb = color:get()
for i = 1, #list do
    -- use argb, not color:get()
end
end)
```

**Collect in `tick`, draw in render.** `world:players()` and `world:entities()` walk every
entity, which is too much per frame. Build the list once per tick (20/s) and only project and
draw in `render_2d`. Stored handles stay live, so their methods still return current values.
The [2D ESP example](/examples#2d-esp) is built this way.

**Project with `projection.entity_box(id)`.** It interpolates the live entity by id and
allocates nothing on the script side.

**Localize hot functions.** `local entity_box = projection.entity_box` before a loop skips
the repeated table lookups.

**Subscribe to the slowest event that works.** `frame` fires every frame and `packet_send`
on every packet. If once per tick is enough, use `tick`.

**Keep coroutines out of hot paths.** Creating them in a loop is expensive.

Source: https://aesthetic-docs.pages.dev/performance/index.md
