Fast path for .pos and similar getters: stop importing mcrfpy per property read #331

Closed
opened 2026-07-02 12:29:38 +00:00 by john · 0 comments
Owner

From the 2026-07-02 memory-model review. Internal fix, no API change.

Problem

UIDrawable::get_pos (src/UIDrawable.cpp:575-595) executes, per property read:

  1. PyImport_ImportModule("mcrfpy")
  2. PyObject_GetAttrString(module, "Vector")
  3. Py_BuildValue("(ff)")
  4. PyObject_CallObject (full Python-level constructor)

.pos is one of the hottest properties in game scripts; this is an import + attr lookup + tuple alloc + type call where a direct allocation would do.

Fix

All PyTypeObjects are inline C++17 definitions, so &mcrfpydef::PyVectorType is directly referenceable from anywhere (this is exactly why PyTypeCache was deleted). Replace the ceremony with tp_alloc on the type + set data = sf::Vector2f(x, y) -- same pattern get_color_member already uses via PyColor(...).pyObject().

Scope

  • Audit for other getters/helpers using the import-module-and-call pattern (grep PyImport_ImportModule outside init paths).
  • Micro-benchmark before/after (tight loop reading frame.pos); add to tests/benchmarks/.

Related: #255 (perf tracking), #326 (if proxies win that decision, this fast path is where the proxy would be constructed).

From the 2026-07-02 memory-model review. Internal fix, no API change. ## Problem `UIDrawable::get_pos` (`src/UIDrawable.cpp:575-595`) executes, **per property read**: 1. `PyImport_ImportModule("mcrfpy")` 2. `PyObject_GetAttrString(module, "Vector")` 3. `Py_BuildValue("(ff)")` 4. `PyObject_CallObject` (full Python-level constructor) `.pos` is one of the hottest properties in game scripts; this is an import + attr lookup + tuple alloc + type call where a direct allocation would do. ## Fix All PyTypeObjects are `inline` C++17 definitions, so `&mcrfpydef::PyVectorType` is directly referenceable from anywhere (this is exactly why PyTypeCache was deleted). Replace the ceremony with `tp_alloc` on the type + set `data = sf::Vector2f(x, y)` -- same pattern `get_color_member` already uses via `PyColor(...).pyObject()`. ## Scope - Audit for other getters/helpers using the import-module-and-call pattern (grep `PyImport_ImportModule` outside init paths). - Micro-benchmark before/after (tight loop reading `frame.pos`); add to `tests/benchmarks/`. Related: #255 (perf tracking), #326 (if proxies win that decision, this fast path is where the proxy would be constructed).
john closed this issue 2026-07-09 03:08:50 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
john/McRogueFace#331
No description provided.