Hacker Newsnew | past | comments | ask | show | jobs | submit | antocuni's commentslogin

yes (work in progress :))


Great, thank you, I will watch with interest. The killer feature seems to be interoperability with existing CPython libraries. Best of luck!


hello, spy author here.

> Why do blue functions disappear when redshifting? If you red shift blue then it goes down in frequency so you might get green or red. Perhaps my physics brain is just over thinking it!

yes I think you are overthinking :). It's not meant to be accurate physics of course.

The usage of colors to distinguish comptime vs runtim code comes from PyPy: in that context, we used "green" and "red", and initial versions of SPy used the same convention.

Then someone pointed out that green/red is not colorblind friendly and so I changed it to blue.

Having actual colors for the two phases is VERY useful for visualization: e.g. we already have a "spy --colorize" command which shows you which parts are blue and which are red.

As for "redshifting": the AST "before" has a mixture of blue and red colors, while the AST "after" has only red nodes, thus the final AST is "more red" than the first one, that's why I chose that name.


hello, author of the blog post and author of SPy here.

> how can you reliably import libraries?

the blog post specifies it but probably not in great level of detail. Calling python libs from spy will go through libpython.so (so essentially we will embed CPython). So CPython will import the library, and there will be a SPy<=>CPython interop layer to convert/proxy objects on the two worlds.


Thanks for the answer. I have to admit I missed the implications of embedding libpython. Sounds great.


This looks exactly what I'm trying to do with SPy -- although SPy is still "not there" and it's WIP. I literally wrote an intro post about it yesterday: https://antocuni.eu/2025/10/29/inside-spy-part-1-motivations...


SPy looks really interesting! I've run across projects like MyPyc before, but as you say they kill a lot of the "joy" of Python by removing things like decorators and operator overloading.

One question, more out of curiosity than any genuine need: do you (or do you plan to) support any kind of trait/interface based polymorphism? E.g. it's a pretty common idiom to have a function that works on "any iterable type" and that sort of thing, which seems like it would be best modeled as an interface. I guess you could argue that's at odds with Python's tradition of "duck typing" but then again, so is static typing in general so I'm not sure.


I haven't fully decided which route to take in that direction, but I think I'd like to support something similar do "go": you declare an interface (or, in python typing terms a Protocol) and then all the types which have the right methods automatically implement that interface/protocol


This is an enlightening post and I am very excited about SPy.

I only wish discussions happened elsewhere than Discord, e.g. Zulip, where you can have web-public channels, which is great for searchable documentation, and you can interact with channels by email if you so desire.


thank you for the feedback! I wasn't aware of these features of Zulip, there are way too many competing technologies in this space and I miss the days in which everybody was IRC and that's it.


I know... but given how Slack plays games with archiving, I'd be wary of entrusting user conversations to Discord (plus, there is https://drewdevault.com/2021/12/28/Dont-use-Discord-for-FOSS..., though it might be outdated).


From many points of view, what CPython JIT can do is a subset of what PyPy can do.

The biggest differences between the two JITs are: 1. PyPy is meta tracing, CPython is tracing 2. PyPy has "standard" code generation backends, CPython has copy&patch. 3. CPython so far uses "trace projection" while PyPy uses "trace recording".

(1+2) make CPython JIT much faster to compile and warmup than PyPy, although I suspect that most of the gain is because of (1). However, this comes at the expense of generality, because in PyPy you can automatically trace across all builtins, whereas in CPython you are limited to the bytecode.

Trace projection looked very interesting to me because it automatically solve a problem which I found everywhere in real world code: if you do trace recording, you don't know whether you will be actually able to close the loop, and so you must decide to give up after a certain threshold ("trace too long"). The problem is that there doesn't seem to be threshold which is generally good, so you always end up tracing too much (big warmup costs + literally you are doing unnecessary work) or not enough (the generated code is less optimal, sometimes up to 5-10x).

With trace projection you decide which loop to optimize "in retrospect" so you don't have that specific problem. However, you have OTHER problems (in particular that you don't know the actual values used in the trace) which makes it harder to optimize, so CPython JIT plans to switch to trace recording.


Interesting. If PyPy is this capable, wonder whether an effort to make non-CPython implementations of Python compatible with C extensions would have been preferred compared to taking time and effort into implementing JIT into CPython.


pypy IS compatible with C extensions, via what we call "cpyext": https://doc.pypy.org/en/latest/faq.html#do-c-extension-modul...

The problem of cpyext is that it's super slow, for good reasons: https://pypy.org/posts/2018/09/inside-cpyext-why-emulating-c...

There are efforts to create a new C API which is more friendly to alternative implementations (including CPython itself, when they want to change how they do things internally): https://hpyproject.org/ https://github.com/py-ni


(author of the blog post here) "just compile when you know the types" is not a good strategy for Python. My EuroPython talk "Myths and fairy tales about Python performance" explains many reasons why Python is VERY hard to optimize: https://lwn.net/Articles/1031707/

One big advantage of tracing JITs is that they are generally easier to write an to maintain. For the specific case of PyPy, it's actually a "meta tracing JIT": you trace the interpreter, not the underlying program, which TL;DR means that you can write the interpreter (which is "easy") and you get a JIT compiler for free. The basic assumption of a tracing JIT is that you have one or more "hot loops" in which you have one (or few) fast paths which are taken most of the time.

If the assumption holds, tracing has big advantages because you eliminate most of dynamism and you automatically inline across multiple layer of function calls, which in turns make it possible to eliminate allocation of most temporary objects. The problem is that the assumption not always holds, and that's where you start to get problems.

But methods JITs are not THE solution either. Meta has a whole team developing Cinder, which is a method JIT for Python, but they had to introduce what they call "static python", which is an opt-in sets of constraints to remove some Python dynamism to make the JIT job easier.

Finally, as soon as you call any C extension, any JIT is out of luck and must deoptimize to present a "state of the world" which is compatible with that the C extension finds.


this is done by the installation process, not by AI.


(SPy author here) function calls in SPy are as cheap as in C.

You can check by yourself seeing of the spy compiler translates the code to C in the (super-experimental) spy playground: https://antocuni.pyscriptapps.com/spy-playground/latest/


PyPy's difficulty with invoking native code is not because of its tracing JIT but because the CPython C API makes it very hard to deviate from _any_ CPython implementation details, including e.g. choice of memory management and precise layout of objects in memory. I wrote extensively about it here: https://pypy.org/posts/2018/09/inside-cpyext-why-emulating-c...

HPy proves that it is indeed possible to have high-performance C extensions with PyPy: https://pypy.org/posts/2019/12/hpy-kick-off-sprint-report-18...


Thank you! I didn't mean to imply that it was because of the tracing JIT; rather, I meant to say explicitly that it was not because of the tracing JIT.


what is the python implementation you are involved with?

I agree with your concerns, HPy tries to address them since the beginning. Basically, there are two distinct compilation modes: - CPython ABI: in this mode, things like HPy_Dup and HPy_Close are translated directly into Py_INCREF and Py_DECREF. The overhead is 0 both in theory and in practice, since all the benchmark that we ran so far confirmed this.

- HPy Universal ABI: in this mode, you introduce the indirections which makes it possible e.g. the debug mode. Our benchmarks indicate a 5-10% overhead, which is in line with what you (and we :)) expected.

So, if you are an extension writer, you will be able to distribute both CPython-opimized and universal binaries


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: