Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Protocols to remove abstraction overhead #400

Open
steve-s opened this issue Jan 31, 2023 · 0 comments
Open

Protocols to remove abstraction overhead #400

steve-s opened this issue Jan 31, 2023 · 0 comments
Labels
API design HPy update in GraalPy This change requires a related change in GraalPy HPy update in PyPy This change requires a related change in PyPy

Comments

@steve-s
Copy link
Contributor

steve-s commented Jan 31, 2023

Protocols can help remove abstraction overhead when possible. For example,
consider the case of iterating over a sequence (list, tuple, array.array, etc.)
that happens to contain integers.

Design goals

  • Expose internal data representations, which might be more efficient than
    objects.

  • Make the direct access to native data structures explicit to allow
    implementors to adapt without being bound to internal details.

  • Keep the API similar for both simple object access and optimised data
    structures.

Considering the iteration protocol, which would look as follows:

void iterate_objects()
{
    /* If the object is not a sequence, we might want to fall back to generic iteration. */
    HPySequence seq = HPy_AsSequence(ctx, obj);
    if (HPy_Sequence_IsError(seq))
        goto not_a_sequence;
    HPy_Close(ctx, obj);   /* we'll be using only 'seq' in the sequel */
    HPy_ssize_t len = HPy_Sequence_Len(ctx, seq);
    for (int i=0; i<len; i++)
    {
        /* HPy_Sequence_GetItem will check a flag on seq to see if it can use a
           fast-path of direct indexing or it needs to go through a generic
           fallback. And the C compiler will hoist the check out of the loop,
           hopefully */
        HPy item = HPy_Sequence_GetItem(ctx, seq, i); /* like PyList_GET_ITEM */

        /* process 'item' */
        HPy_Close(ctx, item);
    }
    HPySequenceClose(ctx, seq);

not_a_sequence:
    HPy iterator = HPy_GetIter(ctx, obj);
    HPy_Close(ctx, obj); /* we have 'iterator' */
    while (true) {
        HPy item = HPy_IterNext(ctx, iterator);
        if (HPy_IsError(item)) goto oops;
        if (HPy_IsIterStop(item)) break;
        /* process 'item' */
        HPy_Close(ctx, item);
    }
    HPy_Close(ctx, iterator);
}

Optimised variant when a sequence of C long integers is expected:

void iterate_long()
{
    /* This is allowed to fail and you should be ready to handle the fallback. */
    HPySequence_long seq = HPy_AsSequence_long(ctx, obj);
    if (HPy_Sequence_IsError_long(seq))
        goto not_a_long_sequence;
    HPy_Close(ctx, obj);
    HPy_ssize_t len = HPy_Sequence_Len_long(ctx, seq);
    for (int i=0; i<len; i++) {
        long item = HPy_Sequence_GetItem_long(ctx, seq, i);
        /* process 'item' */
    }
    HPySequenceClose_long(ctx, seq);

not_a_long_sequence:
    /* ... */
}

(copied from docs/misc/protocols.rst)

@fangerer fangerer added API design HPy update in PyPy This change requires a related change in PyPy HPy update in GraalPy This change requires a related change in GraalPy labels Feb 1, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
API design HPy update in GraalPy This change requires a related change in GraalPy HPy update in PyPy This change requires a related change in PyPy
Projects
None yet
Development

No branches or pull requests

2 participants