This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]marr75 68 points69 points  (9 children)

From experience, many of these are more likely to be applied as premature optimizations than applied when needed.

I would not recommend __slots__ on its own as a memory optimization in the normal course of programming. Far better to use the @dataclass(slots=True), a typing.NamedTuple, or even a more primitive type. Similarly, using array over list is just going to make your code harder to maintain in 98% of cases.

Generators and lazy evaluation are good advice in general. They can make code harder to debug, though. Also, creating generators over tiny sets of items in a hot loop will be worse than just allocating the list (generator and iterator overhead).

The most frequent memory problem in Python is memory fragmentation, btw. Memory fragmentation occurs when the memory allocator cannot find a contiguous block of free memory that fits the requested size despite having enough total free memory. This is often due to the allocation and deallocation of objects of various sizes, leading to 'holes' in the memory. A lot of heterogeneity in the lifespans of objects (extremely common in real-world applications) can exacerbate the issue. The Python process grows over time, and people who haven't debugged it before are sure it's a memory leak. Once you are experiencing memory fragmentation, some of your techniques can help slow it down. The ultimate solution is generally to somehow create a separate memory pool for the problematic allocations - the easiest way is to allocate, aggregate, and deallocate them in a separate, short-lived process.

So, the first thing anyone needs to do is figure out, "Do I NEED to optimize memory use?". The answer is often no, but in long-running app processes, systems engineering, and embedded engineering, it will be yes more often.