Skip to content

Use __slots__ to save memory on heavily-used data classes#59

Draft
bmjcode wants to merge 3 commits into
masterfrom
use-slots
Draft

Use __slots__ to save memory on heavily-used data classes#59
bmjcode wants to merge 3 commits into
masterfrom
use-slots

Conversation

@bmjcode
Copy link
Copy Markdown
Member

@bmjcode bmjcode commented May 24, 2026

This PR uses Python's __slots__ mechanism to reduce the memory footprint of several data classes associated with links, cache entries, and various internal uses. The classes in question all have well-known, fixed attributes, and there are typically tens of their objects in memory at any given time, so any improvements to them would be expected to have a measurable impact. In testing I found these changes lowered Frescobaldi's memory usage by several megabytes when displaying a large score.

bmjcode added 3 commits May 24, 2026 10:16
This can reduce Frescobaldi's memory usage by several megabytes when
displaying a large score since each point-and-click link is associated
with its own Link object.
This further reduces memory usage since each page has an associated
link.Links object, which is derived from Rectangles.
Comment thread qpageview/link.py
__slots__ = (
"fileName", "isExternal", "targetPage", "url", "tooltip", "area")

def __init__(self, left, top, right, bottom, url=None, tooltip=None):
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The original code here used class attributes to set defaults for their corresponding instance attributes, but class and instance attributes can't share names when using __slots__. Since these are only ever used as instance attributes in practice, the new code simply initializes them that way to start with.

Comment thread qpageview/link.py
self.tooltip = tooltip
self.url = url or ""
self.isExternal = ("://" in self.url)
self.tooltip = tooltip or ""
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the most concise way to always initialize these as instance variables. (Otherwise, we would have to add else blocks to all the if statements above since they can no longer fall back on their class counterparts.)

@fedelibre fedelibre mentioned this pull request May 25, 2026
@bmjcode bmjcode marked this pull request as draft May 26, 2026 10:40
@bmjcode
Copy link
Copy Markdown
Member Author

bmjcode commented May 26, 2026

I'm changing this to draft to not hold up 1.0.5, and because I promised #58 would be the last new PR for that release. But I do intend to come back to it when there's more time to test it properly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant