Quick, name some ways to make your Python code faster.
Did you think of PyPy, the JIT compiled version of Python?
Maybe some async and await parallelism?
How about Cython, where you write in a Python-esque language that compiles to machine instructions?
Well, I'm here to add a new one to your vocabulary, Nutka.
Nutka is like Cython in that your Python code is compiled into true machine instructions rather than interpreted.
But, unlike Cython, you can take standard Python 3 that runs just in regular old Python, CPython,
without changing the syntax at all, and still compile that to machine instructions.
And Kai Haien is here to take us on the journey of Nutka, a project he's created and has been overseeing for some time.
This is Talk Python to Me, episode 172, recorded July 16, 2018.
Welcome to Talk Python to Me, a weekly podcast on Python, the language, the libraries, the ecosystem, and the personalities.
This is your host, Michael Kennedy. Follow me on Twitter, where I'm @mkennedy.
Keep up with the show and listen to past episodes at talkpython.fm, and follow the show on Twitter via at Talk Python.
This episode is brought to you by Cox Automotive and Rollbar.
Please check out what they're offering during their segments. It really helps support the show.
Hey, everyone. Thanks for tuning in, like always.
I have two things I want to share with you real quick before we get to the interview.
First, I owe you an apology.
You don't realize it yet, but you will pretty soon.
When I recorded this, the microphone cable that connects my good microphone, the one I'm talking on now, to my computer, got bumped or something.
And then the computer just dropped the microphone and fell back to something terrible, like my iPhone headphones or something like that.
Anyway, the audio is not up to where I would like it.
It's not terrible. It's somewhat like a lot of my guests, I guess.
But it could be better, and I really work hard on that, as some of you know.
And this one, it's not up to my standards.
So hopefully you enjoy the conversation.
You can still hear it just fine.
It's just not as smooth and nice as this microphone.
So please bear with me.
It's still a great conversation and absolutely one worth listening to.
Secondly, I just released a new course, and I'm really excited about it.
This is one that's been in the works for a really long time.
It's called Building Data-Driven Web Apps with Pyramid and SQLAlchemy.
And we cover all sorts of cool stuff around building web apps, but also things like Alembic for migrations and unit testing web apps and deploying to Linux,
and a whole bunch of things that I think you'll find useful.
If that course sounds interesting to you, please check it out at talkpython.fm/pyramid.
Have a look through the course page, watch the course intro video, and see what it's all about.
Hopefully you love it.
I really am glad that I got it out there for everyone who's been waiting for it.
All right.
Now, with that stuff out of the way, it's time to chat with Kai.
Kai, welcome to Talk Python.
Yes, hello, Michael.
I'm glad to be here.
Yeah, it's good to have you here.
We've been trying for a while to set this up.
We've both been on and off traveling and things like that.
But it's great to have you here.
And I'm really looking forward to speaking to you about your project and your efforts to make Python faster.
Yeah, as you can imagine, I'm very excited.
Yeah, it looks like you're having some really great success.
So I'm excited to share that with everyone.
Let's start, though, with your story.
How did you get into programming in Python?
Yeah, I started as a kid.
I think that was a long time before the Internet.
So when I was 11, the first thing I ever saw was C64, Commodore 64, my brother, we brought it home.
And I had like one or two days of learning basic on it.
And then you went away with it.
And I didn't have a computer anymore.
So what I did, I was programming on paper.
Wow.
That's a dedication.
Programs in my mind.
Yeah.
That was bizarre.
It was hard.
But I suspect that that's actually really good training.
Because a lot of people, especially with...
The editors weren't that good, but paper is actually a lot more flexible.
Yeah, that's probably true, actually.
But, you know, just a lot of people, I feel like, kind of just poke at the program when they're new.
You know, they'll write something that doesn't work.
They're like, well, let me just change it and see if it works now.
I'll change it a different way.
Like, you don't actually, you know, so deeply, like, think through the work.
And if you do it on paper, like, you've got to think it through.
Yeah, and I didn't learn everything from my brother.
So I wanted to write something, I think, Hangman, something like this.
And I came up with that there should be something like a loop.
But I didn't know what it is.
And so on the schoolyard, I pestered all the kids who I knew were also programming.
There were, like, maybe three other guys that I knew of.
And I pestered them and asked them questions.
And I learned about the Goto statement.
These are, like, the early loops.
The early unstructured wild days of programming before functions and things like that.
It was, like, you were on an island.
So the cursor was blinking.
And you would figure out everything on your own.
And there were barely people to talk to.
I also, I grew up in a small village.
Went to school in a small city, very small city, 6,000 people maybe.
And, yeah, there was, I think in my village there was no other kid who had a computer that could
actually do some programming.
And I was, at least I wasn't aware.
So I was very isolated.
Yeah, I think that's one of the bigger differences now that you're connected, right?
It also made me self.
I don't know.
I was autodidactic all my life.
That's probably stemming from there.
Because later I learned, like, stack overflow programming.
You type what you want.
You copy, paste your code.
You're done.
But initially it wasn't like that.
So I also recall learning a sampler.
So coming from basic, it had these line numbers.
And I thought addresses were like line numbers.
And I wrote down my program.
And when I wanted to insert a statement, I just took a number between two addresses.
And, yeah, if you know a sampler, you know that corrupts the program.
I didn't get it for a long time, what this was all about.
So, yeah.
So learning a sampler.
But eventually I learned the 68K series of processors.
It was almost like a high-level language.
The C64, it had no registers.
You couldn't learn that.
That was too crazy.
I couldn't get anything done.
I think it couldn't multiply.
It was crazy.
But this one was actually pretty good.
And I learned a sampler in C.
Later I did C++ for some real programs.
Actually had a day job.
And met again with my brother, who was studying mathematics and computer science.
And he's pretty much older.
He's 13 years older.
He learned computers from these, what's it called, with the punch cards.
And he told me, learn Pearl.
If you know Pearl, you will always be the only guy who can do stuff.
And he was right.
So Pearl was really my absolutely first love.
I had learned a lot of languages until then.
But Pearl was, like, yeah, amazing.
And I read the book of Larry Wall, who was a linguist, designing a language.
And he wrote, or he designed the language in a way that it fits your mind.
So you would write what you think, however unstructured that is.
So unlike Python, where you are forced in a certain, yeah, outline of a code, you could write unless at the end of statements.
You could basically write down as you think, and you would never have to go back.
You could always just continue writing.
That was, like, a really productive way of programming.
Yeah, it's interesting.
I haven't done much with Pearl, but that sounds quite interesting.
Yeah, and Python was upcoming.
But it was very weak in terms of, this is 2002 we're talking.
It was very weak in terms of supported stuff.
So with Pearl, you had modules for everything, much like with Python today.
Nothing can compete with Python anymore.
But back then, CPAN was like, if you want to do stuff, it's already there.
So why bother with Python, which cannot even send an email?
You couldn't get stuff done.
But it was much more readable.
And, yeah, 16 years ago, when I switched jobs, we were working on a product which had a lot of share scripts.
And it was pretty ugly, and we wanted to improve on it.
And Pearl was, of course, an idea.
But a better idea was to use Python.
So I switched to Pearl from that.
I've since fallen a bit in love with Python, actually, a lot.
But it's not my first love.
It's never the same.
Yeah, yeah.
So Pearl was the first to enable me to do what people, I think, a lot of people perceive Python to be.
Right, yeah, that's really cool.
And for teamwork, it's absolutely much better.
Yeah, for sure.
And I think what's really interesting, you brought it up here, often people debate languages on the syntax.
You know, like, this syntax is better than that syntax.
And what most of the time rules the day is, yeah, but I have all these libraries that actually let me do stuff when I put the syntax in place.
Right?
And that's so important and often sort of forgotten in these language debates.
Yeah, this is, I think Java also has this rich ecosystem.
C++ sort of, but not as productive, I think.
Yeah.
Yeah, getting things done and being quick.
That's, for many tasks, it was, with Pearl, I've done things for my J job that were just, yeah, beginning.
Yeah, great.
It was like, and Python too.
And I think now everybody knows this.
Oh, everybody that's using Python, that's pretty much.
That is a lot of people today.
It's pretty amazing, the growth.
So, speaking of your day job, what are you doing these days?
Currently, I'm on parrots to leave.
So, I have a one and a half years kid now.
And there's this regulation in Germany which forces your employer to give you time off when you have kids.
And you get paid by the state even for 14 months total, both of us.
So, my wife took 12 of them.
I took two of them.
You get a reduced payment for that.
And on top of that, I added four months of unpaid parent to leave so I could focus on newt car.
That's what I currently do.
I have three times two months to spend on newt car.
And I'm at the start of a third chunk of that right now.
In reality, that parent to leave, I mean, you're a parent.
And, yeah, it's a lot of work to care for a small kid.
And especially with my wife, she's a doctor.
And I'm very emancipated because for roughly 10 days per month, she's not here for 24 hours.
So, actually, I get a fair share of her work there.
But when I will return, I will be what I've been for 16 years now.
I will be an engineer for air traffic management software.
Also did a bit of project management.
But mostly, I've been an engineer on this time.
That sounds like software that you have to be really careful with.
Yes.
That's actually, we review everything.
And it's the requirements, the code, tests.
Everything gets looked with at least four eyes and goes through several phases.
And it's amazing.
And I was very lucky that the project that I'm working on, it's very old.
Now, is it 30 years now?
I think it's getting 30 years old or is already 30 years old.
And I was blessed with the opportunity to lead the project to replace the middleware because
it was closed source software.
And the idea was to be able to distribute it to parts of the world where we didn't or the
owner didn't have a license for.
And so I got to replace the middleware.
And I got to introduce Python in the safety critical software.
That was also an amazing experience and a huge success.
And it's also a reason why a lot of my day job now is Python.
So that's, I'm very proud of that because obviously that's not easy.
Java can't go there.
Yeah, that's cool.
Because of the virtual machine doing its cleanups whenever it wants to.
But for Python, we managed.
Wow, that's really interesting.
I definitely have heard that about the GC languages.
The unpredictability of the pauses is just too much sometimes.
Yeah.
Interesting.
Yeah.
Python is much more predictable with its garbage collection.
And budgeting is actually, can become a problem.
Yeah.
Threading is also something we're not allowed to do.
And so we are using multiple processes.
And that fits Python's weaknesses pretty well.
That's right.
So you have to do it the way that Python has to do it.
Perfect.
We'll use Python.
Yeah.
Because that's actually, threading is terrible.
I recall writing an editor.
And this editor was also a file system.
So I would type in my editor and launch the compiler.
There was no save.
It wasn't necessary.
I was just using the file system that was the editor and had a scripting language as well.
And these are all working on the same data.
And I learned an important lesson from there.
You don't do threading.
It's terrible.
We're locking.
And it's such a time killer.
And yeah, I'm not a fan of threading.
It sounds like it.
You know, sometimes, I mean, with modern processors, sometimes it's necessary.
But it's, yeah, it's maybe not the first thing to jump to.
Yeah.
Depending on your problem, you don't have a choice.
But when it's about safety, I think a process and a thread is not much of a difference, depending
on how you work with it.
It's roughly the same.
It's just more difficult.
Because with threads, you get access easier, but also careless.
Yeah, exactly.
This portion of Talk Python to Me is brought to you by Cox Automotive.
They're leading the way in cutting-edge, industry-changing technology that is transforming the way
the world buys, sells, and owns cars.
And they're looking for software engineers and technical leaders to help them do just that.
Do you hate being stuck in one tech stack?
Well, that's not a problem at Cox Automotive.
Their developers work across multiple tech stacks and platforms.
They give you the room you need to grow your career.
Bring your technical skills and coding know-how to Cox Automotive.
You'll create real-world solutions to today's business problems alongside some of the best
and brightest minds.
Are you ready to challenge today and transform tomorrow with Cox Automotive?
Go to talkpython.fm/cox, C-O-X.
And check out all the exciting positions they have open right now.
Speaking of performance, let's talk about your project, Nutka.
Yeah, so maybe let's just start with a really quick overview of what it is and then how you got started on it.
The first thing is it's a fully compatible Python compiler.
So it does everything and it's compatible.
So the idea is if you run a program with the standard CPython interpreter or you run it with Nutka, it does the same thing.
So that's basically only a clone of CPython that is capable of producing binaries just faster.
Yeah, that's really neat.
And one of the things that I thought was cool about it is you don't have a separate language, right?
It's not like, say, Cython where you write a slight variation of Python that then can do this, right?
It's like I could take something I wrote yesterday and just run it through you.
That's exactly my point is like you have no lock-in.
You can anytime something is behaving strange, you have these other implementations or the other Python implementations and you can switch to them.
And it's a drop-in replacement for as long as it works.
And when it doesn't, you can use something else.
That's the point.
And you can, and this is very important, you can drop a million lines of code on it and have it accelerated.
That's the important point because for small programs, which you fully write on your own, you can accelerate them manually.
But for libraries from third parties that you have no clue about, you cannot just live with any kind of limitations.
So a big part of the problem was to get everything working.
Yeah, to give people a sense.
Like during your EuroPython talk, you showed compiling Mercurial, which is, is it over a million lines of Python?
I don't know.
It's large though.
It's not a million line, I think, but it's a substantial project.
I think a million lines and all this.
Yeah.
Python is not that bad.
That's true.
It's true.
It should be less.
But it's a seriously large project.
It's not just like, oh, look, I can take this and I can write a calculator, a calculator app.
To make no changes, no changes to Mercurial.
And actually I was capable of doing this in 2012.
This was my first demo when Nutka was more like a feasibility study.
Back then I had, it was more like a templating from Python to C++.
It was just going to demonstrate that this is achievable.
And since then it has evolved into an actual real compiler under the hood, still capable of doing the same things and becoming more compatible.
So yes, people are using this in real life for real programs.
Obviously, some of the things are not working.
But I get a lot of positive feedback on a level of compatibility.
Yeah.
I was always thinking that for such a compiler to be acceptable, it needs to run foreign code and guaranteed to behave the same.
And otherwise, you just cannot trust it.
So how do you do, I'm probably getting things a little out of order here, but just a moment.
How do you ensure compatibility?
Like you run the tests that they run against CPython itself or things like that?
Mm-hmm.
I am taking the CPython test suite and, for example, also the Mercurial test suite and run it with compiled and uncompiled.
And it must pass or fail the same way.
Actually, the CPython test suite, for me, never really passes all the things.
And then I run the CPython 3.6 test suite with 3.5.
And then I get a lot of exceptions.
So I get extra coverage for error cases and these things.
So that's one way of doing it.
Obviously, then users report me back with incompatible behaviors that they still encountered.
Yeah.
Maybe something that wasn't covered in the test, right?
Yeah.
Sometimes that happens.
And often they describe the behavior of things in the test pretty well.
And sometimes I just add another test to see what it is.
But there's many times there are instances where, for example, running Mercurial tests would misbehave
and I would trace it down to an incompatible behavior of NewtGuard.
Yeah.
This has happened in the past.
Yeah.
It's cool that you have these large programs that are open source.
You can go and you just try them.
Actually, I would like to go further because right now running the Mercurial test suite is something I do.
And this is all a lot of CPU cycles.
And I want to integrate with TOX or these kind of projects and get people to just switch on running their own tests with NewtGuard.
And see if I pass as well.
That's something I need to work on to get out and get even more coverage.
Right.
If you could get all these other projects with all of their continuous integration automatically running their tests through your stuff,
that would be great.
Maybe not automatically, but they have to enable that, I suppose.
But they shouldn't just say much more.
If you want to run your tests with PyPy, I think it's as simple as saying do it.
I'll list PyPy in an enumeration and NewtGuard should also be there.
But that's just the plan.
Right now I rely on people doing things manually and reporting back.
And some people run their test suits with compiled stuff.
And I'm still pretty early with integration of pytests, running your tests, the compiled code, and then uncompiled tests with pytests.
That's working with some tricks, but it's not documented yet.
And it's not complete.
There's another field where I want to get more exposure.
There is Distoutils integration is something that people have started through pull requests on GitHub.
And that's pretty awesome because you don't even have to know how NewtGuard works.
You just install NewtGuard, enable a flag, and it outputs a wheel, which is a binary for a given platform instead of a no arch wheel.
And that's ridiculously easy to use then for existing projects.
Right now it's a manual rerun of what setuppy does that you have to specify on the command line.
And that's another field of integration.
So it should also be that simple to use.
That's also my goal.
Yeah, that's really great.
The more you can just make it just another command you give things and you don't have to really understand it.
That's super cool.
So maybe we can start looking at what you built by comparing it against other things people might know.
So people might know Cython.
Let me see if I can summarize it.
I think Cython is a lot more successful in terms of adoption because there are people willing to write this hybrid language code
and get the optimization benefits of manual work.
And it's useful a lot.
And I know Stefan Benel.
Actually, I worked with Cython for a while.
I was listed as a contributor.
But I asked them to remove it since initially I wanted to turn Cython into a compatible Python as well.
But this didn't work out.
I think it's a pretty good solution for what it does.
But I think it's bad for the ecosystem for all the reasons that we said.
The IDE integration, the lock-in, you cannot switch.
So Cython has a bug.
There's no way of comparing to anything else.
Right.
You're stuck with it.
You've got to just work around it somehow.
Yes.
So I have a lot of respect for Cython.
I have.
I'm an even bigger fan of PyPy, which I also contributed a patch to.
PyPy was our Python specifically.
We reduced Python for something which I tried out to accelerate actual code of mine long, long time ago.
And it's such an amazing project.
And obviously there's very little commonality.
It's a totally different approach.
And it's a thought.
So it's a very active project.
I think they've been a lot more successful at getting funding.
So I'm not getting that.
But I think they got money from the European Union initially.
And they also got fundraisers and PSF endorsement and all these things.
And very huge benefit is many of the benefits that Newtka also has.
It's a drop-in replacement.
You don't do anything.
It works when it works.
I mean, sometimes it doesn't.
It requires too much memory or can happen.
I'm not so much using it.
But I think it's a great alternative or maybe even, I don't know if Newtka does succeed.
I think it's a great thing.
But PyPy is here today.
That's really cool.
Yes, Cython to me feels a little bit like inline assembler used to be for C, C++.
It's like I've got most of my code the way I like it.
But this little part, we've got to make this a lot faster.
Let's rewrite it sort of here to be a little bit faster.
And so that's Cython.
And then PyPy is P-Y-P-Y.
The JIT compiled sort of CPython runtime.
Mostly compatible alternative to Python.
Which sometimes is faster.
Sometimes it's not.
Pretty interesting project.
I think they've made progress with the extension modules.
But this was a large holding back factor.
I think they might maybe do now PyQt.
I'm not so sure.
Yeah, I think that's right.
They did, yeah.
Yeah.
But with Newtka, I could do all the extension modules.
I think we can do some or all now.
I'm not so sure what's the current state there.
I don't follow it, actually.
I've had mixed results with it as well.
You know, like, I really think the project is awesome.
I'm glad it exists.
And I know in some places it makes things a lot faster.
But I switched out one of my larger websites to run on top of it.
And it did.
But it was like two and a half times slower.
And I thought, well, that's not helping me.
So I guess I'll just switch back to CPython.
And I think it was probably the C extensions and the data layer or something.
I'm not entirely sure.
But there was something compatibility.
Yeah.
If you're on Django or something, that's really something where I need to go is to get Newtka to work out of a box for Django projects, which have their own mess.
It's for manage.py is doing all sorts of nasty things that you cannot know about at compile time.
But I think the Django, accelerating Django, even by a bit, will be very welcome to many people.
And that's also something somebody should go eventually.
But I'm not focusing on that right now.
I'm focusing on other optimization.
So, I mean, for Newtka, I was like, I was observing the landscape for many years.
And all this time, I was thinking, a compiler for Python, that's totally possible.
And why is nobody doing it?
And that was just, I think, a couple of years that I was observing it and wondering.
And I think around the 2.5 timeframe, I thought, I'm going to make a prototype, make a proof of concept and show that it's possible.
And that turned out to be pretty much the case because a Python design is very welcoming to be compiled, actually.
I mean, it's a trivial, it's a non-trivial task.
It's very hard.
But you can do it for Python, if anything.
So, I have this compiled function type.
And there's the uncompiled function type in Python.
And all I have to do is for them to behave the same.
And then you're in.
So, you can have a compiled function.
That's basically a lot of how you get to work.
And then you don't have bytecode, but you have C code behind it.
Yeah.
And when the C code compiles to machine instructions, and then you're off to the races.
Yes.
And the Python engine really doesn't care all that much.
Because extension modules are first-class citizens.
Right.
So, let's talk about the architecture just a little bit.
So, the way it works is we take regular straight Python code.
We feed it to Nutka.
Nutka translates that into, like, a reduced Python.
The reduced Python is then translated into C.
The C is compiled, basically, to a C extension.
And that runs on top of CPython.
So, Nutka is not its own special runtime, like, say, PyPy is.
It's a thing that...
No.
No, no.
It's a thing that...
No.
No, no.
It's a thing that...
Do you have to install the runtime for it?
Or does it just create...
Like, do you have to install CPython, like, 3.5 in order to run it?
How...
Has it put together?
There's two modes.
There's a standalone mode, where you create something which will be self-contained, and then contains Python runtime.
And there's also this accelerated mode, and then it just links against a Python installation and loads libPython, like every program that embeds Python needs to do.
And that's how it goes.
And I try to avoid the C runtime, the Python runtime as much as possible.
And that's how I curlerate things.
So, not having bytecode, and then having knowledge or static optimizations, trying to avoid to go as much into the Python runtime as possible.
It's basically the acceleration.
Yeah, but you are still...
Like, that C code I talked about being generated in the architecture, that still uses, like, the Py object types and stuff like that, right?
It's as if you're basically...
Your compiler is writing a C extension from our Python code.
Yes.
That's true, except for...
Did you say our Python?
The PyPy...
It's not...
No, no.
Our Python.
Like, the Python that I write, I give to Nuka.
You write...
Yes.
Yeah, yeah, yeah.
Exactly.
Yeah, sorry.
Sounds the same, of course.
No, our Python would be reduced.
Yes, exactly.
It takes your Python and turns it into an extension module, and then a very hacky one.
It's really nasty.
I'm really big friend with the dictionary implementation.
I take advantage of all the internal knowledges that I'm not supposed to use.
Nice.
But that's what a compiler is supposed to do, right?
Yes.
It's responsibility to do all these nasty things, and yeah.
And if you order the Python version, the safer it is.
So 2.7 is not going to change a lot.
Yeah.
So we can...
You can be shorter on that, yeah.
This portion of Talk Python to Me has been brought to you by Rollbar.
One of the frustrating things about being a developer is dealing with errors.
Ugh.
Relying on users to report errors, digging through log files, trying to debug issues, or getting
millions of alerts just flooding your inbox and ruining your day.
With Rollbar's full-stack error monitoring, you get the context, insight, and control you
need to find and fix bugs faster.
Adding Rollbar to your Python app is as easy as pip install Rollbar.
You can start tracking production errors and deployments in eight minutes or less.
Are you considering self-hosting tools for security or compliance reasons?
Then you should really check out Rollbar's compliant SaaS option.
Get advanced security features and meet compliance without the hassle of self-hosting, including
HIPAA, ISO 27001, Privacy Shield, and more.
They'd love to give you a demo.
Give Rollbar a try today.
Go to talkpython.fm/rollbar and check them out.
This is Vitar Askin.
So let's talk about compatibility a little bit.
So it works on Windows, Linux, and macOS.
It works on not just that.
It's because it's creating C code.
I think it will work on anything that you can work with Python on.
That's the idea.
I obviously can only test Windows and Linux.
It works on Windows and MacOS is working because other people are using it.
And sometimes I fix something, but I don't have a macOS machine.
And yeah, you made an interesting point around that as well.
Like, well, I think iOS and Android probably are also candidates here.
Yes, Android.
I think people have done Android.
Obviously, it has been done.
And I think I have even done myself.
There's a cross-platform toolkit for...
I've done some Android compilations myself.
It's an ARM-based Linux.
It has a Python and you can...
Obviously, the compiling machine might be too slow.
That's the limitation there.
But in principle, there's nothing which prevents it from working.
And I think it has been done occasionally on and off.
The practicality is currently just not there.
But I think once the speed-ups are increasing, I would expect that people...
There's a lot of people currently doing games in Python.
I met a couple of those.
It's very interesting to have something like NewtGov for these use cases.
Right.
You mentioned the PyPy folks getting the 2D stuff accelerated and working faster.
And that was pretty cool.
So...
But your project is really right in there as well for making these things go faster.
Yes.
But it's not happening this year.
Yeah.
So lots of OSs.
Python 2 and Python 3 both?
Yes.
3.7 actually.
At the time you're releasing this, it will be working.
And 3.2, I just discontinued support for that, mostly because it's impossible to get it running.
And 3.3.2, 3.7, and 2.6, 2.7, they all work.
In my design, I have what I call these reformulations.
I think you can put up a link to these language conversions to make things simpler from my developer menu,
which is very instructive, and it explains a lot of things.
Actually, to me, this is a baby Python or this commonality Python internal that I'm using.
And the with statement, for instance, it's translated into many statements, actually.
Or a third statement is just if not condition, race, assertion error with my arguments, these kind of things.
And that means that most of the time, the Python versions do not make as much difference as you would think they do.
Right.
You've got some step that goes, oh, I look at a with statement, I'm going to translate that to something else, regardless of which level.
So there's a huge chunk of code dedicated to reformulating the with statement into a series of try-accept-finally stuff,
doing lookups of enter and exit, implementing the Python mechanics in explicit terms with temporary variables and so on,
which then can be optimized at compile time.
Maybe sometimes we know that it's not going to raise an exception and then we can drop this.
That's basically the reason why the language versions are not that much of a problem.
Yeah.
I suspect that the async stuff was more interesting.
Oh, this was terrible.
And especially imagine our coroutines and async jams.
Like, I've seen this being used.
I personally never knew why I would use it.
Well, so I don't use it.
And because it's like you get a lot of disadvantages of reading without the advantages.
I'm not so sure why it is good.
Well, I was just thinking of you, how difficult that must be to implement in this scenario and your comments in the beginning, how you don't really like them.
I had no idea what it is about.
It's like I'm trying to find out what it does and use it and the semantics and especially the coroutines, for example,
in a minor release, 3.5.2, they changed their mind how they work.
And they introduced a compatibility layer.
And then in 3.5.2, yeah, it was like a totally new implementation compatible with another one, which is a total mess.
And the async generators are taking it to the extreme.
And like, you know, when I started Nutka, there was a yield statement.
So a generator could yield the execution.
There was no return value.
And then this got added.
Actually, it was through Nutka that I learned that this changed at all.
So you can imagine that what happened there is it's amazing.
And they have a full team of people implementing this stuff and throwing out a new release.
And I get to replicate that.
That's basically what happens.
And that's one guy against the whole team.
And then you try to be faster with your implementation.
That's actually ridiculous.
But the last release wasn't so bad.
It's actually I didn't encounter anything crazy.
That's cool.
I'm pretty impressed that you got 3.7 going already because that just came out a couple weeks ago.
Yeah, yeah.
Actually, with 3.6, I was reporting bugs.
So I did with the 3.7.0 some bug report now about dictionaries.
I was using release candidates and reporting my findings.
So I have a couple of tests which demonstrate that Nutka is not misoptimizing certain things badly.
And I found out CPython was so Nutka wasn't, but CPython was.
And I could turn this into reports.
And 3.6 was already pretty good at the time it was released.
Therefore, but for 3.7, they made a huge change to exception handling.
Exception handling is also absolutely terrible.
I think in Python 2, it had pretty crazy semantics where a frame had an exception and restored it.
And it was terrible in Python 3, they changed it again.
And now in 3.7, they changed it yet again, but mostly on the implementation side.
So the structures internally, where you store it and so on.
This changed.
And this prevented me from, without a lot of changes, to compile with Nutka in 3.7.
So I'm a bit late, actually.
But I normally try to be quick with this because the early adopters will pester me about lack of support for the latest, greatest Python release.
Yeah, it sounds like you're pretty much on top of it.
That's really good.
So one thing that I was thinking about as I was looking at this is what basically can be the output of Nutka is it's like a C extension, right?
A compiled C extension.
That's one of them.
Yeah.
So if I have regular Python code that I just want to run, not compiled or anything, just standard, but there's part of my program that I would like to make faster and optimize with what you're doing, I can put those two things together, right?
Yes, you can.
That's absolutely true.
And actually, one of the things I'm aiming at is making bindings an easy task.
So my vision of bindings is for you to use C types or something.
For the middleware, we use C types to make bindings.
So it's implemented in ADA, but you can think of C code.
And that's a pretty neat way of doing the bindings.
And my idea of this for Nutka to optimize that way and not use C types, but to directly C codes and do bindings like this in a comparable fashion.
And what I also want to achieve is that Nutka makes available the original code.
So if I use that binding extension then and try to compile a program, I would like for the compilation process to be able to go and inline code from there.
So I'm not so sure if I was clear or not.
But the idea was right now there's a barrier.
So if it's an extension module, it's an extension module.
I can't look into PyQt at all if it's created with zip.
And I want to replace this with the ability to make a call into a bound C function in my main program.
And normally I would use this compiled extension module, compiled with Nutka.
And if I compile the program, it would be able to inline that extension module's call.
Right.
So not just optimizing the Python code you feed it, but actually optimizing the underlying C code that's being used.
Because ultimately it gets down to like C on C.
Yeah, generate C code for the compile program again.
And I think the ecosystem would benefit from having these dual mode codes.
Like you have this original Python binding and you have the compiled extension.
You can use the compiled extensions where you want.
And you can also use the original code if you compile.
So that's my vision.
And I think that would be healthy for the ecosystem.
And that's something that Cython doesn't do.
And then it would, I think, be much more attractive to do bindings in pure Python.
Yeah, I think that sounds really great.
That's awesome.
That's my vision.
And I think I will be getting there.
Yeah, I think you will as well.
You definitely got some impressive stuff already working.
Let's talk about some of the optimizations.
It sounds to me like one of the most important things that you could do in Python is to inline functions.
Because functions in Python are almost, I want to say, unreasonably slow.
They're like quite, it's actually quite a high penalty to call a function in Python.
Just that mechanics of setting up that stack and call and whatever compared to, say, other languages where it's slow.
It has an effect, but it's not like, you know, super significant.
Yeah, it did a lot of hacks to accelerate functional method codes, actually.
And a lot of the acceleration in Utica is coming from being willing to do all kinds of nasty tricks to call functions in a faster way.
That's a huge overhead and this inlining that will, of course, make all the difference.
But it requires whole program optimization.
That's a rather difficult task.
So as you know, with Python code, it can change everything behind my back without me noticing.
Right.
I will always have to do both the things.
So I will have to check that it's actually what I'm thinking it is.
Much like the PyPy JIT is having guards, like, is it really the same as last time?
And is it really what I expect it to be?
And then I can be super fast or I need to fall back because something crazy happened behind my back.
Right.
Like a unit test patch, for example.
Yes.
That kind of thing will have to work.
And then, but that's this duality.
It's my vision of how things will then eventually work.
But inlining code will definitely do a lot of things.
I'm currently working on classes and optimizing the classes and the dictionaries and tracing the values in there.
And NUTCA and I hope the next release will be capable of statically optimizing most classes into a simple call to type with a static dictionary.
Of stuff.
That's the first step, obviously, to understanding types fully, because I will be able to precisely know the dictionaries.
Then I have to see through the meta class mechanics and see that they are actually mostly harmless most of the times.
And from there, I take it from there.
This is a, I think it's a huge undertaking.
It's one of the directions that I want to go.
So these global program optimizations are one thing.
And then locally, for cases where I do know that something is an integer, I want to get to using alternative integers and Python integers or just the C type where possible.
That's the direction I intend to work on the next two months.
Basically, that is the magic sauce that makes Cython fast is that you explicitly type your stuff and it lets, you know, it just be four bytes on the stack in C rather than all the indirect stuff.
Like, well, it could be this reference type.
Like, we don't really know what it is.
You know, treat it as a full on pie object.
Yes.
You're working on this as well.
Yes.
That's crazy.
And this is where I think C level performance is possible.
And then I have the idea that unlike Cython, I want to make type annotations to that are actually behaving in Python at runtime too.
So I would like you to declare that the function takes integer arguments and will raise an exception if it isn't integers.
And then I want to have Newt Cassie through that, take these assertions and generate specialized code from there, much like Cython does, but in a lot more complex way and with the benefit of actually enforcing these things at runtime.
That's the vision there, which is also a lot of work.
You would have to write some decorators, but I think other people can do this.
Just today I asked somebody who offered to volunteer if he could do it.
That would be great if people joined such efforts because that's all only about CPython, right?
You can write this without any knowledge of Newt Cassie.
It's just, I want to have a decorator which says, I have to clear this class and now it's frozen.
You will not be able to change anything after the fact about this or else you get an exception.
And that's a hint to the compiler to take advantage of that for static optimization.
Yeah.
A little like slots, right?
Yeah, exactly.
Like slots.
But in a more general fashion and enforcing these things.
And these kinds of decorators, I think, make all sense.
And yeah, this is another avenue where I think Newtcar will also be beneficial to the ecosystem of making it viable.
Because what it will do is you slow down your program terribly because it will do all these checks that typically are not useful at runtime if you do with the Python decorators.
But then when you accelerate some, it's actually better.
And that's the idea.
Well, that'll let you claim a much higher performance boost.
Look, I ran it on her Newtcar.
It was 20 times faster.
Just kidding, because it would be slower, right?
Yeah.
So I don't know if you're getting this, but Newtcar is a crazy compromise-free project.
And if it fails, which it probably will, that's why.
It's all about trying to do the best thing possible.
Yeah, the compromise-free part is what makes it so challenging, right?
Yes, it's so challenging, but it's also, yeah, it's rewarding.
And everything I've achieved challenge-free from when in 2003 to I made these public releases of Newtcar, it was usable.
It was usable from day one.
And it has remained usable all this time.
And it only became ever usable, more usable.
What it didn't become in, I think, like at least two years, it didn't become faster.
Because I'm doing these big transformations of internals where, for example, the local dictionary work that I'm doing on classes, class declarations aren't performance critical at all.
You run that code once.
It's not in a loop.
But for scalability, it's hugely important to get this, because if you compile this million line of code and you optimize it better, it's much less code.
And for these plans, we really need to understand the global picture there.
So I'm spending a lot of time on stuff that doesn't actually improve performance at all most of the time.
And I really look forward to finally having fun running benchmarks again, because I really don't enjoy running benchmarks if the numbers are all stacked.
Yes.
It's sad.
It's crazy.
And it's totally anti what everybody else has done in the field so far.
So there has been compilers from Google.
I forgot the name now.
But they had their own project.
And the first thing they had is incredibly well-numbered benchmarks.
And, yeah, but it wasn't doing what it should be doing.
I think the unladen swallow.
Yeah, yeah, I think you're right.
Unladen swallow, I think.
It just went away.
And it's not sustainable because you can't use it for anything but benchmarks.
Right.
That's basically the idea.
And I'm doing something which can be used outside of benchmarks.
But there will always be code which is currently slower and new to curve because I didn't look at it.
Or actually CPython has a lot of tricks.
I recall that it took me a long time until I was at the point to emulate their in-place assignment tricks.
So if you do an in-place assignment to a string, they did some things to avoid allocating a new object unless a reference was held on the outside.
Which in many instances makes it incredibly, like infinitely faster than Newtco was.
And so I'm behind in some optimizations even.
And that's pretty tough.
And obviously I would like to have also cool benchmarks.
But what I would like to have is also the ability to say, and you can have it too in your program.
That's obviously, I don't know.
And forever it has felt like it's right around the corner that I can do this now.
And then I discover something else that I need to do first.
Yeah, that's why I brought up Mercurial.
Because that's a pretty serious application to process.
Yeah, and just carrying the full weight.
So doing all these refactorings.
And I'm always doing these refactorings in a non-breaking way.
So I try to not strive too far away from a working state in all the changes that I made.
So I made gradual changes.
Like I said, initially it was more like a templating language.
And I turned it into a single state assignment form compiler gradually.
One by one, bit by bit.
And trusted more here and there.
Right now this value tracing is very reliable.
But still not used for everything.
I think right now the major fact that I'm using it is do I need to check if the value is assigned or not.
And that's mostly what it's being used for.
And for static optimization.
And that's working bug free.
But I'm always expanding this.
And then I find something which is not yet working.
That's the crux of it.
Yeah.
Well, it sounds like it's getting better and better.
And there's a lot of things that you could unlock with it.
So speaking of stuff that's faster, stuff that's slower.
When should I use this?
And maybe when shouldn't I use it?
Oh, you shouldn't use it if you don't care about performance.
Yeah.
Compatibility is just like mostly what you care about.
Yeah.
Actually, I have this secret pipe dream of being better than PyLint.
But that's not.
That's a whole other issue.
Because my static analysis may uncover things that PyLint wouldn't.
The program analysis.
And if you don't care about performance.
And I think that's roughly 99% of all the people.
And you should use it if you are into NumPy and these things.
Although I wasn't having discussions with a university.
It would take somebody to work on specializing code generation for NumPy.
So NumPy is a hugely great scientific library where you would just provide very little Python code on your own.
And for you to do something for each cell, for example, that would be bytecode.
And it would be massively cool if we could have this little bit compiled.
Yeah.
And still run it.
And I think NumPy would be then practically not entering the Python runtime a lot.
And that would be something.
But I didn't quite manage to get some university or something involved.
So scientific applications and financial applications are also like where you want to do financial stocks, something.
You want to buy as fast as possible, make your decisions as fast as possible, real-time applications in Python.
All the algorithmic trading stuff, yeah.
Some people are crazy enough to do this in Python because of the development turnaround.
And then they want to throw something easy on it to get it accelerated.
And on another day, they want to change the algorithm simply.
And that's the kind of uses.
I think to most people that do not care that much about acceleration, some people care about deployment.
And there's a standalone mode, especially on Windows.
where you do not normally have any Python on an arbitrary user machine and definitely not the version you want to have and definitely not the modules.
You can run a newtker and use it to create this distribution folder and send that to people's way and have things work.
That's, I think, what a lot of people use it for.
I think that it's really excellent.
And so basically you compile it down to an exe that does not depend on CPython.
It bundles it up to contain that within itself, right?
Not on an installation.
Yeah.
Yes.
And yeah, although you could use anaconda python for that too.
It's, I think, a convenient package.
I think that also a lot of people are using it to hide their source code from people.
And that's actually something which I'm, well, that's what compilers allow for.
It's not my, it's not my daily joy of being part of depriving people of the ability to change source code.
But yeah, that's people's people own their source code.
So we can do, they can give it to you or they can't in favor of that.
But yeah, that's one other mode of operation, which I think is unfortunately the majority of users, I guess.
And it's also causing a lot of trouble because extension modules often do imports of stuff which they don't tell me about.
And then they crash when it's not present.
And it's sometimes very nice.
Yeah, I can imagine.
It's tricky.
So if I'm using external packages off of PyPI, that's no problem, right?
You can deal with that.
So if I work with requests, SQLAlchemy, whatever, I can run that through Nuka?
That's awesome.
Yes, yes.
Actually, yeah.
It's the out-of-the-box experience.
You just arbitrary code.
It's supposed to work.
I think Django is, if it's some of the really dynamic, crazy stuff, would need a plugin to be created to pass it.
Because I think Django does some dynamic imports of stuff.
Some people are getting it to work.
I don't know.
But that takes some modifications.
Yeah, sure, sure.
Interesting.
So this, yeah, the standalone mode is pretty interesting as well.
So I think we're getting kind of near the end of our time.
So one thing I did want to highlight, I think, it sounds like you're looking for contributors.
And there's a lot of places that people can contribute.
You talked about writing some standard Python code that then Nuka could use.
I'm sure if there was a long list of these are all the optimizations we're looking for.
Could anybody who's good at this kind of stuff and see?
Could you help here?
Things like that.
Are you looking for contributors along those lines?
Yes, of course I am.
I actually have to think if I did, I should have a list of issues on GitHub that are marked as help wanted.
And there's a lot of these things.
And obviously I could and should create a couple more from these ideas that I just told you about.
And that's totally something I should do.
I have relatively bad experience with people joining the project because it's tough to get progress.
It's also a complex design, not easy to get into.
It takes a lot of skill and privacy.
And occasionally I get contributors.
But I think it's not rewarding enough, I think, for many people, unfortunately.
Yeah, it takes a lot of effort to see the rewards through, right?
I'm just thinking that there must be many people who are working on compilers and stuff who just left university and are looking for some kind of project.
You know, maybe they could jump in, right?
Yes, I welcome everybody.
But I have to be honest with you.
I also don't have time to actually mentor much.
I can't guide people through doing things and then they lose interest.
That's happened a couple of times.
So there's a lot of people who want to find out if this is something they would be willing to do.
And yeah, I have a family, I have a day job, and this is my spare time.
Right, absolutely.
It needs a lot of work.
Communication often takes second place after coding myself.
Yeah, that's the challenge of doing this as a part-time project, right?
Yeah, it's totally impossible to keep up with.
So suppose somebody really wants to get into this and yeah, I cannot respond quick enough sometimes.
And that's already frustrating.
Sure.
I guess people could probably start by watching your EuroPython presentations and then go from there.
Yeah, yeah.
Yeah, but also I think what I really would need is somebody with community skills who would be capable of doing a fundraiser for me.
It's a long-term project and a lot of people have short-term needs.
I need to get Newtka to a point where people with short-term needs will feel that investing their time into Newtka is worthwhile.
And then it will be a different story.
Yeah, but coming back to what I would like to have.
I would like to have somebody who organizes some fundraiser and does this so I could get time off my day job.
I work on Newtka and I've invested my own money right now.
Four months unpaid is a lot of effort.
I'm buying hardware and so on.
I'm getting some donations, but it's not enough to buy the hardware that I buy for Newtka.
And that's also something people could do is to send donations my way.
But I think a concerted effort that would gain visibility and with a raising goal and me being able to put a couple of months again into Newtka and pushing really forward, that would be great.
Probably that's something more than I need than actual contributors.
Because I think I need to reach a breaking point where I have something that is attractive enough for people who have actual problems to just add the bits that they are missing.
Like at the point where they have a lot of optimization and then they run into some construct which is not properly optimized and then they can hack it.
And then it is.
That's a thing for them then.
Right now, that's not the case.
Right now, you would have to be somebody with a long term vision and no concrete other problems that require your attention.
So that's it.
I think the couple of months sprint really would make a big difference.
I've seen that make a difference in other projects more than donations or other things as well.
So certainly that sounds like a good thing.
All right.
Kai, before we get out of here, let me ask you the final two questions.
If you're going to write some Python code, what editor do you use?
I'm using Eclipse and PyDef specifically.
I occasionally use VI on the command line just for quickness, but Eclipse and PyDef it is.
Right on.
And then just some notable PyPI packages.
Maybe people haven't heard of them or aren't using them yet.
Obviously, I have a lot of machines running and I'm using Ansible, which somebody introduced me on a Debian conference.
I'm forever grateful for the tutorial I got there.
It's very useful tools like salt, if you know that, Ansible written in Python.
And you just can easily deploy all your machines in a similar fashion.
And that's great.
Nicola is something I'm actually, I forgot my contributor number.
I might be contributor number five or something or static website generation.
That's what people are using a lot these days.
And I really liked the idea and I joined that and I'm using it for my website.
And it's great.
And obviously, BuildBot is also a tool I heavily rely on.
I absolutely despise Jenkins, which I have to use at work.
The BuildBot is great because you get to write your configuration as Python code.
Actually, there's no web interface needed to configure stuff.
You just do your for loops and stuff and everything is consistent, which is great.
And I think something which should get more exposure is pip-env, which combines the virtues of virtual environments and pip install, making it easy to run stuff.
I'm not using that myself a lot, but I think it's very notable.
Yeah, absolutely.
Absolutely.
All right, Kai, thank you for being on the show.
This was a really interesting project that you've been working on a long time.
And it's definitely a cool exploration of this compiled space.
And it's its own take.
And I would like to thank you for hosting me and giving me your opportunity.
And I hope it wasn't rambling too much.
It was some interesting stories.
Thank you.
And yeah, take care.
Okay, bye-bye.
This has been another episode of Talk Python to Me.
Our guest for this episode is Kai Haian, and it's been brought to you by Cox Automotive and Rollbar.
Join Cox Automotive and use your technical skills to transform the way the world buys, sells, and owns cars.
Find an exciting technical position that's right for you at talkpython.fm/cox, C-O-X.
Rollbar takes the pain out of errors.
They give you the context and insight you need to quickly locate and fix errors that might have gone unnoticed until your users complain, of course.
As Talk Python to Me listeners, track a ridiculous number of errors for free at rollbar.com slash Talk Python to Me.
Want to level up your Python?
If you're just getting started, try my Python jumpstart by building 10 apps or our brand new 100 days of code in Python.
And if you're interested in more than one course, be sure to check out the Everything Bundle.
It's like a subscription that never expires.
Be sure to subscribe to the show.
Open your favorite podcatcher and search for Python.
We should be right at the top.
You can also find the iTunes feed at /itunes, Google Play feed at /play, and direct RSS feed at /rss on talkpython.fm.
This is your host, Michael Kennedy.
Thanks so much for listening.
I really appreciate it.
Now get out there and write some Python code.
I really appreciate it.