Le lun. 21 sept. 2020 à 21:46, Antoine Pitrou <solip...@pitrou.net> a écrit :
> > The main benefit is the memory usage. For example, list(range(200))
> > uses 1656 bytes instead of 7262 (4x less memory).
>
> Hmm, how come? Aren't those tiny integers singletons already?

These numbers come from the code:

    import sys
    def size(l):
        return sys.getsizeof(l) + sum(sys.getsizeof(item) for item in l)

    print(size(list(range(200))), "bytes")

The code doesn't ignore the object size of singletons but count their
memory as if they are allocated on the heap memory.

It took a shortcut: I counted as if my implementation would support
any number, and not only existing Python singletons.

On my current implementation, list(range(200))) doesn't use more or
less memory, but the same amount.


> > Sadly, my current simple implementation is 1.1x slower than the
> > reference. I suspect that adding a condition to Py_INCREF() and
> > Py_DECREF() explains a large part of this overhead.
>
> And adding a condition in every place an object is inspected.  Even
> something as simple as Py_TYPE() is not a mere lookup anymore.

You're right that Py_TYPE() also gets a condition to check if the
pointer is tagged:
https://github.com/vstinner/cpython/blob/tagged_ptr/Include/object.h#L203

By the way, Py_INCREF() and Py_DECREF() use:

if (_Py_TAGPTR_IS_TAGGED(op)) {
    // Tagged pointers are immutable
    return;
}

https://github.com/vstinner/cpython/blob/tagged_ptr/Include/object.h#L497


> > It would be nice to use tagged pointers for a wide range of integer
> > numbers, but I wrote a simple implementation: _Py_TAGPTR_UNBOX() has
> > to return a borrowed reference. This function should return a strong
> > reference to support a larger range.
>
> Hmm, it sounds a bit weird.  The point of tagged pointers, normally, is
> to avoid creating objects at all.  If you create an object dynamically
> each time a tagged pointer is "dereferenced", then I suspect you won't
> gain anything.

Sure, functions could be optimized to avoid the creation of temporary
objects. I wrote a simple implementation which leaves the code as it
is, but "unbox" tagged pointers when a function access directly object
members. Example in listobject.c:

    vl = (PyLongObject*)_Py_TAGPTR_UNBOX(v);
    wl = (PyLongObject*)_Py_TAGPTR_UNBOX(w);
    v0 = Py_SIZE(vl) == 0 ? 0 : (sdigit)vl->ob_digit[0];
    w0 = Py_SIZE(wl) == 0 ? 0 : (sdigit)wl->ob_digit[0];

"vl->ob_digit" crashes if vl is a tagged pointer.

My first goal was to write a *correct* (working) implementation, not
really an optimized implementation.

That's why I'm calling for help to attempt to optimize it ;-)

Victor
-- 
Night gathers, and now my watch begins. It shall not end until my death.
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/GQQ56I236ZUU3WOR5PS6N5WIEWNNOD47/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to