[Python-Dev] FW: [Python-Help] Python threads with suncc (Forte 6.1) compiler

Tim Peters tim.one@home.com
Sat, 4 Aug 2001 23:17:50 -0400

[Guido, on reworking select()]
> Yes, I think we do need this.  PyObject_AsFileDescriptor() calls the
> fileno() method which could be a Python call.

Ya, but for me to believe that *matters*, I have to believe people worried
about high-performance select are passing objects with Python-implemented
fileno methods to begin with.  That's quite a stretch, isn't it?  They have
to pay for fileno() calls regardless, the question is only whether they pay
it once or twice per object.

> Maybe we could use a more sophisticated construct where we use a short
> array allocated on the stack for lists of fewer than 100 (say) files
> but use malloc for larger ones?

Another idea:  screw it <wink>.  We have to allocate three lists anyway to
hold the results.  Allocate them at the start instead of the end, and then
they can do double-duty, holding the cached fileno() results across the
select() call.

Fleshing it out a little,

def list2set(inputlist, fdset):
    "Return (list of file descriptors, biggest fd seen); set fdset slots."
    n = len(inputlist)
    result = [None] * n
    if _MSC_VER:
        biggest = 0
        biggest = -1
     for i in range(n):
        obj = inputlist[i]
        fd = PyObject_AsFileDescriptor(obj)
        if fd == -1:
            return NULL, -1
        result[i] = obj, fd
        FD_SET(fd, fdset)
        if not _MSC_VER:
            biggest = max(biggest, fd)
    return result, biggest

# iolist is the result of an earlier list2set() call.  It gets shrunk
# to hold just the objects corresponding to the fds in fdset.

def set2list(iolist, fdset):
    lastindex = 0
    for obj, fd in iolist:
        if FD_ISSET(fd, fdset):
            iolist[lastindex] = obj
            lastindex += 1
    if lastindex < len(iolist):
        del iolist[lastindex:]

So it still does the perversely <wink> optimized caching, but no stack space
required, no free() calls, only the 3 malloc() calls that are needed anyway,
and up to 3 realloc() calls to shrink the output lists.  It does create a
bunch of 2-tuples, but they're on a free list and come cheap.