Перейти к содержимому
Profiler Analyzer

Profiler Analyzer

Record a FiveM profile with profiler record and saveJSON, then read time per resource, worst frames, hitches, a flame graph and findings with fixes.

Эта документация пока на английском.

Open the tool Last updated

The Profiler Analyzer reads the JSON file the built-in FiveM profiler saves and turns it into a report you can act on: which resources eat your frame or tick time, which frames were the worst and what ran in them, which events and threads are heavy, when hitches happened, and plain advice on what to fix. It works for both server and client recordings and runs entirely in your browser.

What it is for

resmon tells you a resource averages 0.8 ms, but not why, not when, and not what it looked like in the frame where the game stuttered. The profiler records all of that, but its raw output is hard to read. Use this tool when:

  • Players report lag or rubber banding and you need to know which resource is responsible.
  • The server console prints hitch warnings and you want to know whether a script caused them.
  • You changed a resource and want proof that it got faster (the Compare tab).
  • You want to share a short, readable summary with a script’s developer.

How to record a profile

FiveM has a profiler built in on both sides. It records every resource tick and event handler with microsecond timing, including escrowed resources. The How to record card next to the drop zone has the same commands with copy buttons for Server console and Client F8.

Server (txAdmin Live Console or the FXServer window)

Terminal
profiler record 1200
profiler status
profiler saveJSON lag.json
  1. profiler record 1200 records 1200 ticks. The server runs 20 ticks per second, so that is one minute. Use 600 for a quick look.
  2. profiler status shows whether it is still recording. It stops by itself.
  3. profiler saveJSON lag.json writes the file next to your server.cfg with txAdmin, or wherever FXServer was started.

Record while the server is busy. Problems that only show with players online will not show on an empty server.

Client (F8 console)

Terminal
profiler record 1000
profiler status
profiler saveJSON lag.json

Stand where the game feels bad and do the laggy thing while it records. 1000 frames is 8-16 seconds depending on your FPS. The file ends up in %localappdata%\FiveM\FiveM.app\citizen\lag.json.

Client recordings store a small screenshot per frame, so they get big fast. Files of a few hundred MB are fine here.

Other profiler commands

Command What it does
profiler record start / profiler record stop Record until you stop it
profiler resource myresource 300 Records Lua function calls of one resource (* for all). Slower, but shows which function is heavy
profiler view Opens the raw trace in Chrome DevTools for a manual look
profiler save name Writes a binary file this tool cannot read. Use saveJSON

Quick start

  1. Record a profile as above.
  2. Drop the .json on the page, or press Choose a file. A gzipped .json.gz works too.
  3. Read the verdict at the top, then the Findings tab.
  4. Click the worst bars on the timeline to see exactly what ran in those frames.

No file handy? Try a sample loads a made-up server recording so you can look around. Its resource names are invented.

The report

File bar

Shows the file name, size, number of events and how long it took to read. Buttons:

Button What you get
Copy for Discord A short summary that fits in one Discord message (2000 characters)
Report .md <file>-report.md, the full report as Markdown
Timeline .png <file>-timeline.png, a picture of the current timeline
Open another Load a different file. You can also drop a new file anywhere on the page

Verdict

A one-line status (Healthy, Some pressure, Struggling or Overloaded), a title and a sentence explaining it. Read as shows whether the file was detected as a Server or Client recording and why; switch it if the guess is wrong.

The card on the right shows:

  • Scripts per tick (or frame), average: the big number.
  • p95 / p99: how bad the slow ticks or frames get.
  • Worst tick / frame: click it to open that frame.
  • FPS, avg / 1% low on the client, or Tick interval, p99 on the server.
  • Hitches, and how many of them came from scripts.
  • Recorded (ticks or frames) and Length.

Timeline

One bar per tick or frame. Two views:

  • Script time: what resources spent in each frame or tick.
  • Tick interval (server) or Frame time (client): the time between two ticks or frames for the whole server or game.

Amber and red mark the budgets below, and guide lines show 50 ms (a whole tick) or 60 and 30 FPS. Hover a bar for the numbers and the top three resources in it. Click a bar to open that frame. Drag to zoom, Ctrl + scroll to zoom, Shift + scroll to pan. Under the chart, Worst ticks / frames lists the eight worst with their time in the recording.

When you select a resource in the Resources tab, its own time is drawn in white on top of the timeline.

Frame detail

Opens under the timeline when you click a bar or a worst-frame button. It shows:

  • Scripts, Resource Manager Tick, and Until next tick (server) or Frame time with the FPS pace (client), marked heavy, over budget or hitch when they are.
  • A flame chart of exactly what ran in that frame, in order, left to right. Colours mark the type: frame, resource tick, event handler, thread or function. Hover a block for its duration, start and file lines. Click a block to zoom in, Whole tick / frame to zoom out.
  • On client recordings, the screenshot the game took at the end of that frame.
  • Heaviest resources in this frame: click one to open it in Resources.

Use the arrows to step to the previous or next frame.

Tabs

Findings

Rules that read the numbers and point at problems, grouped as Fix first, Worth fixing and Good to know (filter with the buttons at the top). Each finding lists the evidence and a concrete fix, with Open resource and buttons that jump to the frames involved. They cover:

  • Scripts taking a big part of every tick or frame.
  • A resource running code every frame (the Wait(0) loop pattern).
  • Heavy event handlers and heavy NUI callbacks.
  • Events that fire constantly or very often.
  • Spikes that repeat on a timer, and one-off big spikes.
  • Resources that run many small threads.
  • Hitches caused by scripts, and hitches not caused by scripts (streaming, the host, garbage collection).
  • Resources with no detail (JS and C#), Lua memory that keeps growing, short recordings and unclosed scopes.

If nothing stands out you get Nothing stands out, with the tip to record during the laggy moment or on the other side (client vs server).

Resources

A sortable table of every resource:

Column Meaning
Share Share of all script time in the recording
Avg Average ms per frame or tick over the whole recording, the same thing resmon shows
Worst Most time spent in a single frame or tick
Events Time spent in event handlers
Calls Number of calls
Active Share of frames or ticks where it ran

Times are exclusive: when resource A triggers an event in resource B, B’s handler counts for B, not twice. Filter by name; the table shows 60 rows until you press Show all.

Click a resource to open its detail: average, p95, worst and total time, Its worst ticks / frames, What triggered it (every tick, or which events, with calls, average, worst and total), Threads, handlers and functions with file and line numbers, and the Lua heap at the start and end when the file has it.

Flame graph

The whole recording merged by call path. The wider a block, the more total time it took. Hover for total, per tick or frame, share of all, self time and calls. Click a block to zoom in and use the path at the top to go back. Highlight a name marks every block that matches a resource or file and shows how much time the matches take in total.

Compare

Did your fix work? The loaded file is before. Drop a second recording taken after your change, ideally the same length and in the same spot, on Drop the “after” profile. You get:

  • A summary: scripts per tick or frame (average and 99th percentile), worst tick or frame, average FPS on the client and hitches per minute, each marked better, worse or about the same.
  • Per resource, average ms per tick / frame with before, after and the change. Green means less time after the change.

Numbers are per tick or frame, so two recordings of different length still line up. A warning shows if you compare a client recording with a server one. Remove after clears the second file.

Budgets

Client Server
Frame or tick 16.7 ms at 60 FPS 50 ms (20 ticks per second)
Scripts get heavy at 4 ms per frame 25 ms per tick
Hitch a frame over 50 ms ticks over 150 ms apart (the console’s hitch warning)
One resource worth a look 0.1 ms per frame, heavy from 0.5 ms 0.5 ms per tick, heavy from 2 ms

Script time is what resources spent in a frame or tick. Frame time and tick interval cover everything. When the gap is big but script time is small, the stall came from somewhere else, and the findings say so instead of blaming a script.

Examples

The most common finding is a loop that runs every frame even when it has nothing to do:

client.lua
-- runs every frame, all the time
CreateThread(function()
    while true do
        Wait(0)
        local coords = GetEntityCoords(PlayerPedId())
        if #(coords - shopCoords) < 2.0 then
            DrawMarker(2, shopCoords.x, shopCoords.y, shopCoords.z, 0, 0, 0, 0, 0, 0, 0.3, 0.3, 0.3, 255, 255, 255, 150, false, true, 2, false, nil, nil, false)
        end
    end
end)
client.lua
-- only runs every frame while the player is close
CreateThread(function()
    while true do
        local sleep = 1000
        local coords = GetEntityCoords(PlayerPedId())
        if #(coords - shopCoords) < 10.0 then
            sleep = 0
            DrawMarker(2, shopCoords.x, shopCoords.y, shopCoords.z, 0, 0, 0, 0, 0, 0, 0.3, 0.3, 0.3, 255, 255, 255, 150, false, true, 2, false, nil, nil, false)
        end
        Wait(sleep)
    end
end)

Record again after a change like this and drop both files into Compare.

Tips

  • Record on the side where the problem is. Client FPS drops need a client recording; server hitch warnings need a server one.
  • Record for long enough to catch the problem. A short recording gets a Short recording note.
  • For a resource that shows as heavy but has no named threads, run profiler resource <name> 300 for function-level detail.
  • The profiler adds a little overhead itself, so absolute numbers run slightly high. Compare recordings made the same way.

Limitations

  • The file never leaves your browser. There is no upload and no shared leaderboard.
  • Only Lua threads and handlers get names. JS and C# resources show up as a total per resource.
  • Files from profiler save (binary) cannot be read; use profiler saveJSON.
  • The sample file is synthetic, not a real server.