PEP 669: Low Impact Monitoring for CPython

Most of the design and discussion has focused on semantics, not syntax. So the names might not be the best. Suggestions for improvement are very welcome. PY_START occurs within the callee, so the call has already happened, whereas C_CALL happens before the call.

I was trying to infer a pattern from the names, but if there isn’t one, that’s OK too.

Would you prefer it if C_CALL were changed to CALL and included Python functions?

I wouldn’t want C and Python functions mixed together.

No. Callbacks must be callable Python objects. You can implement those in C, or C++ or Rust, provided the resulting object is callable. Using the vectorcall protocol will give you near C function-pointer performance.

I don’t know what “vectorcall protocol” means, but I will figure it out when the time comes.

For a coverage tool, Python will be plenty fast enough. The trick is to return DISABLE and only get called once per location.

I have a sense overall that you have a specific idea about how a coverage tool will work, and that coverage.py doesn’t work quite that way. In particular, there are a number of reasons why getting called just once per location wouldn’t always be sufficient. There are options in coverage.py that require collecting more data than that: branch coverage and contexts are two options that would mean I can’t disable an event after it is fired.

All branches from that point. I can see the advantage of tracking each direction independently, but it would be a special case and would impact performance and memory consumption.

You’ve placed great emphasis on the idea of disabling a callback after it has fired. In order to measure branch coverage, I need to know all of the branches that have been taken. If I disable the branch event once I’ve received it, and that disables all branches from that point, then I don’t have the information I need. That’s why I said it would be useless to disable the branch event if it didn’t take the destination into account.

Using JUMP and BRANCH is more efficient than line based tracing. Using line numbers will continue to work, though.

I haven’t worked this all through, so I might not be understanding your idea completely. JUMP and BRANCH would give me data about bytecode offsets. If I track that information, then I need to map that back to line numbers to produce a report for the user. Is that right? Can you say more about why JUMP and BRANCH are more efficient than line-based?

I definitely don’t want to have to understand the specifics of individual bytecode operations, but I don’t think you are saying that.

3 Likes