This demo comes from the official Maya Python API documentation.
It's a utility module with three functions that pull events out of Maya's
built-in MProfiler and write them to disk as JSON or CSV. Useful for
performance analysis: capture a profiling session, export it, then analyze it
in a spreadsheet or feed it to a separate visualization tool.
ℹ️ The module is not a plugin despite having
initializePlugin/uninitializePluginstubs at the bottom — those are no-ops. The real entry points are the three public functions, called from the Script Editor.
MProfiler— Maya's built-in profiling system. Records timing events for evaluation, redraw, file I/O, and anything else instrumented withMProfilingScope. This module shows how to read those events back out.- Reading profiler events —
getEventCount(),getEventName(i),getEventDuration(i),getEventTime(i),getEventCategory(i), etc. - Categories & names as enums — events reference a category ID and a name string; the example shows both the indexed (compact) and non-indexed (human-readable) representations.
- Filtering by duration — the
durationMinparameter lets you skip events shorter than a threshold, which is how you strip noise out of a profile. - JSON vs CSV output tradeoffs — JSON keeps structure and supports the indexed form (smaller files); CSV is the right choice when the goal is to open the data in Excel / Numbers / Google Sheets.
| Concept | Where to learn it |
|---|---|
maya.cmds basics |
introduction/helloCube.py |
| OpenMaya API 1.0 | ../cameraMessageCmd/cameraMessageTest/ |
Python file I/O (open) |
standard Python tutorial |
The json and csv modules |
Python standard library docs |
What MProfiler is |
Maya docs → Profiling API (MProfiler, MProfilingScope) |
You don't need to have written a plugin before — this module is just a set of functions you import and call.
profilerDump/
├── README.md ← this file
└── profilerDump.py ← the utility module
The .py is bundled here directly (it's a public Autodesk docs listing).
Maya's profiler records timestamped events whenever instrumented code runs —
evaluation of a node, a redraw, a file open, a plugin's custom work, etc.
You can see them visually in Window → General Editors → Profiler
(the timeline view). Each event has:
- a time (when it started) and a duration (how long it took),
- a name (what the event is) and a category (which group it belongs to, e.g. "Rendering", "DAG", "Animation"),
- a thread id and CPU id (which thread ran it),
- an optional description (free text),
- a color (used by the UI).
This module reads all of those fields out programmatically. The typical workflow: enable the profiler, do something slow in Maya, then call one of the functions below to dump everything to a file you can analyze offline.
Dumps every event (above durationMin) to a JSON file.
profilerDump.profilerToJSON('out.json', useIndex=True, durationMin=0.0)useIndex=True— emit a compact form where event names and categories are written once as lists at the top ("eventNames": [...],"categories": [...]), and each event references them by integer index ("nameIdx": 3,"catIdx": 1). Much smaller files, but harder to read.useIndex=False— write the full strings inline ("name": "evaluate","category": "DAG"). Bigger files, but self-contained and greppable.durationMin— only include events whose duration is greater than this value (in whatever unitMProfilerreports). Set to0.0to keep everything; raise it to strip noise.
The output JSON looks roughly like:
{
"version": 1,
"eventCount": 12345,
"cpuCount": 8,
"categories": ["DAG", "Rendering", "Animation"],
"eventNames": ["evaluate", "draw", "compute"],
"events": [
{ "time": 0.001, "nameIdx": 0, "desc": "...", "catIdx": 0,
"duration": 0.4, "tDuration": 0.4, "tId": 1234, "cpuId": 0, "colorId": 5 }
],
"eventsWritten": 12345
}Tiny helper: reads a JSON file (e.g. produced by profilerToJSON), sorts the
keys, pretty-prints with 4-space indent, and writes it back out. Useful for
diffing two captures or making the indexed form more readable.
profilerDump.profilerFormatJSON('out.json', 'out_pretty.json')Same data as profilerToJSON, but in CSV. This is what you want when the
goal is spreadsheet analysis — open the file in Excel, sort by Duration
descending, and the slowest events jump to the top.
profilerDump.profilerToCSV('out.csv', durationMin=0.0)Columns: Event Time, Event Name, Description, Event Category, Duration, Thread Duration, Thread Id, CPU Id, Color Id.
Before you can dump anything, there must be events to dump. Either:
- Open
Window → General Editors → Profilerand hit Record, do something in the scene (play, render, evaluate), then Stop, or - programmatically:
import maya.cmds as cmds cmds.profiler(action='enable') # ... do work ... cmds.profiler(action='disable')
Place profilerDump.py on PYTHONPATH (or alongside your other Maya
scripts), then in the Script Editor:
import profilerDumpimport profilerDump
# JSON, human-readable, no duration filter
profilerDump.profilerToJSON('capture.json', useIndex=False, durationMin=0.0)
# JSON, compact indexed form, skip events under 1ms
profilerDump.profilerToJSON('capture_compact.json', useIndex=True, durationMin=0.001)
# CSV for spreadsheet analysis
profilerDump.profilerToCSV('capture.csv', durationMin=0.0)The files appear in Maya's current working directory (use absolute paths if you want them somewhere specific).
profilerDump.profilerFormatJSON('capture_compact.json', 'capture_compact_pretty.json')The whole module is ~250 lines of straightforward iteration. Read it in this order:
profilerToJSON— the biggest function. Notice the structure:om.MProfiler.getEventCount()→ how many events are there?om.MProfiler.getAllCategories(categories)→ fill a list of category names.- Loop every event index
i, callinggetEventName/Duratuson/Time/...to pull fields. - The
strippedlambda filters out non-printable ASCII — important because event names come back as rawbytesand may contain control chars from some plugin sources.
profilerFormatJSON— justjson.load+json.dumps(..., sort_keys, indent=4)+ write. Five lines of real logic.profilerToCSV— almost identical toprofilerToJSONbut writes viacsv.writerinstead of manual string concatenation. Notequoting=csv.QUOTE_NONNUMERIC— it auto-quotes strings and leaves numbers bare, which is what spreadsheets expect.
Key API calls you'll reuse anywhere you touch MProfiler:
| Method | Returns |
|---|---|
MProfiler.getEventCount() |
total number of recorded events |
MProfiler.getEventName(i) |
bytes — name of event i |
MProfiler.getEventDuration(i) |
float — how long event i took |
MProfiler.getEventTime(i) |
float — when event i started |
MProfiler.getEventCategory(i) |
int — category ID of event i |
MProfiler.getCategoryName(catId) |
bytes — human-readable category name |
MProfiler.getThreadId(i) |
int — thread that ran event i |
MProfiler.getCPUId(i) |
int — CPU core that ran event i |
MProfiler.getAllCategories(list) |
fills the passed list with all category names |
OpenMaya.MProfiler— https://help.autodesk.com/cloudhelp/2027/ENU/MAYA-API-REF/py_ref/class_open_maya_1_1_m_profiler.htmlOpenMaya.MProfilingScope— the RAII class used to create eventscmds.profiler— the MEL command for controlling the profiler UI- Python standard library:
json,csv
- Capture and analyze your scene. Enable the profiler, play your scene for a few seconds, then export CSV. Open in a spreadsheet, sort by Duration descending, and identify the top 5 slowest event types. This is the core workflow for performance debugging.
- Add a
--categoryfilter. ModifyprofilerToCSVto accept a category name (or list) and skip events that don't match. Useful when you only care about Rendering or Animation events. - Add a thread breakdown. Group events by
ThreadIdand print the total duration per thread. This tells you whether work is balanced across threads or concentrated on one. - Strip the indexed form. Read an indexed JSON output back and resolve
the indexes to full names — i.e. decode
nameIdx: 3toname: "evaluate". Good practice working with two representations of the same data. - Port to API 2.0. Rewrite using
import maya.api.OpenMaya as om. Most calls are identical; the main change is thatgetEventName(i)returns astrdirectly (no.decode('ascii')needed). Good API-1.0-to-2.0 practice. - Generate a flame graph. Take the CSV output and feed it to a tool like
speedscopeor a Python flame-graph library. You've now built the data pipeline half of a serious performance tool. - Add error handling. What happens if
open(...)fails (disk full, permission denied)? What ifgetEventCount()returns 0? Wrap the public functions intry/exceptand print friendly errors instead of crashing.
- You must capture first. All three functions silently return if
getEventCount() == 0. If your output file is empty or missing, you forgot to enable the profiler before running. getEventName(i)returnsbytes, notstr(API 1.0). The code calls.decode('ascii', 'replace')on it before writing. Forget the decode and you'll get Pythonb'...'literals in your JSON.- The
strippedlambda matters. Some instrumented code emits event names or descriptions with non-printable characters (control codes, stray UTF-8). Stripping to printable ASCII (32–126) avoids corrupt JSON / CSV. - Indexed JSON requires client-side decode.
nameIdx: 3is meaningless without the matchingeventNameslist at the top of the file. If you strip that list when post-processing, you've lost the data. - CSV
quoting=csv.QUOTE_NONNUMERICquotes strings, not numbers. If you add a new column that's a string but you forget the writer assumes it's a float, the writer will crash. Usecsv.QUOTE_MINIMALif you're unsure. - The
initializePlugin/uninitializePluginstubs are no-ops. Don't load this file as a plugin — it won't do anything. Justimportit. - Output paths are relative to Maya's CWD. On Windows that's usually
C:\Users\<user>\Documents\maya\projects\default\or similar. Pass absolute paths to be sure where files land. getEventCategory(i)returns an int, not a name. You must callgetCategoryName(int)to resolve it. CallinggetCategoryNameon the event index directly is a common mistake.- The file writes are not atomic. If Maya crashes mid-dump you get a half-written JSON. For production tools, write to a temp file then rename on success.
Autodesk, Maya Python API 2.0 Reference — python/api1/profilerDump.py, Maya 2027 (ENU). https://help.autodesk.com/cloudhelp/2027/ENU/MAYA-API-REF/py_ref/python_2api1_2profiler_dump_8py-example.html