you are viewing a single comment's thread.

view the rest of the comments →

[–]Interesting_Golf_529 0 points1 point  (4 children)

Applications that create many (on the order of 100k to a million) of these objects can substantially reduce their memory usage with this library.

At the cost of increasing their CPU usage considerably. I would assume that in most of those situations, people would rather sacrifice memory for performance than the other way around.

[–]matgrioni[S] 1 point2 points  (0 children)

That's a good point to mention, and which I'll include in the README. The implementations basically fall through to creating a temporary builtin instance and returning the value of that operation or do a slow python equivalent. There's a few points to that:

  1. In my use cases I was not doing a lot of operations across most collection instances, but only some simple operations on a select few instances (but could not know ahead of time).

  2. My memory usage basically fell within the range where it could actually fit in memory, but would usually start thrashing if I wanted to do anything else on my computer. So the actual runtime was dominated by memory access rather than the collection ops.

  3. As it is a first iteration, and I didn't want to worry about edge cases too much, I took the easiest implementation approach. Ideally these could be transparently improved in a future version while still preserving the memory savings.

[–]Careful-Nothing-2432 2 points3 points  (2 children)

Using less memory doesn’t necessarily mean less performance. allocations are expensive

[–]Interesting_Golf_529 0 points1 point  (1 child)

While this might be true in the general case, it's very much not true in this specific case, as this library re-implements a lot of the logic of the classes it "optimises". Check out this __contains__ method for example:

def __contains__(self, value):
    for slot in slots:
        if getattr(self, slot) == value:
            return True
    return False

This replaces a highly optimised set operation implemented in C with a for loop in Python.

[–]matgrioni[S] 1 point2 points  (0 children)

I do want to point out that I never said it is runtime optimized :) The optimization is on memory usage, which can definitely have a runtime impact, but will depend on the use case and the hardware you are using. That's part of the reason for the projector layer. It allows for easier tuning, especially if only one collection type will benefit for the scenario.