This episode, we have an optimization twofer.
We begin by looking at optimizing a subset of Python code for machine learning
using the LLVM compiler with a project called PyLLVM.
It takes plain Python code, compiles it to optimize machine instructions,
and distributes it across a cluster to do machine learning.
In the second half, we'll look at a fabulous new way to work with MongoDB
for Python writing data scientists.
The project is called Bison NumPy and provides direct connections
between MongoDB and NumPy.
It's 10 times faster than working with PyMongo directly
if you plan to end up in NumPy anyway.
You're about to meet the woman behind both of these projects, Anna Herlihy.
This is Talk Python to Me, episode 103, recorded February 6, 2017.
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 Talk Python Training and Hired.
Be sure to check out what we both have to offer during our segments.
It helps support the show.
Anna, welcome to Talk Python.
Thank you.
Thank you for having me.
Yeah, it's great to have you here.
We got a couple of really cool things to talk about.
We're going to talk about PyLLVM, which is a really cool project that you worked on.
And we're also going to talk about a super high-performance sort of data science-y thing
with MongoDB that you're also working on right now.
So I'm looking forward to talking about both of those.
But before we get into those, what's your story?
How did you get into programming in Python?
I had my first real experience with programming.
I mean, I had done some basic when I was pretty small, but I thought it was not very fun.
So I kind of put that off for another five or six years.
But in university, I was kind of all over the place.
I didn't know if I wanted to be a writer or an engineer.
But I figured that computers are probably going to be relevant.
So I took a CS class because I didn't know the difference between computer science and computer
literacy.
But it ended up actually working out in my favor because I really, really enjoyed it.
And I ended up prioritizing my CS classes over all my other classes.
And then I kind of figured, maybe I should just do this full time.
That's really cool.
What was that first CS class?
That was Andy Van Dam's intro to computer science, which for anybody who went to Brown will recognize
that it's quite a popular course.
I mean, when I took it, it was maybe 150 people.
But I think just last year, they had 250 or something.
It's really, really blowing up.
Oh, that's excellent.
What language did you study?
Do you remember?
Yeah, it was a Java course.
We did a lot of swings.
Okay, excellent.
Yeah.
And so you decided, hey, I kind of like this programming stuff.
Let's just do that as a job, right?
And how did you go from learning Java and CS 101 to working in Python?
So I really liked programming languages in general.
So I wrote some compilers, some interpreters.
My area in computer science was mostly looking at different programming languages.
And I found that Python was kind of the most elegant, in my opinion.
And I didn't feel bogged down by really complicated syntax.
But I also felt very powerful.
So I kind of felt that as opposed to being pure Python, I wanted to do more like Python and C stuff,
sort of more from the very beginning to how it gets down to the computer code at the end.
I see.
So you really were interested in like the internals and stuff and whatnot, huh?
Yes.
Okay.
Cool.
And so the first project we're going to talk about, which I want to ask you a question quick before then,
but PyLLVM, that was part of your university work, right?
Yes, exactly.
The project that it was based on Tupleware is a research project with some of the database professors at Brown.
And my project was a senior thesis that was built sort of on top of that.
Okay.
Wow.
Very cool.
Okay.
So today you work at MongoDB, right?
Yes.
Yeah.
What do you do there?
So I actually recently switched over from spending the majority of my time on Python work.
So like PyMongo, Mongo Connector, other sort of Python related projects to MongoDB Compass,
which is basically a user interface for MongoDB.
It's actually written in JavaScript, which was something new for me since I had done a pretty
excellent job of avoiding JavaScript until now.
It finally got you, huh?
Yeah, I know.
It was inevitable.
But now I really like it.
I can't say that I am converted and I still think that Python is the community and the language
that I like best.
I'm probably preaching to the choir here.
But I now split my time between working on Compass and working on this BSON NumPy package,
which I hope we'll get to talk about later.
Yeah, we'll definitely talk about it because it's very cool.
Okay.
Excellent.
So it sounds like you have a lot of cool projects going on.
Let's talk about the project that you did first with this LLVM thing.
So I suspect a number of people out there know what LLVM is, but the audience is diverse.
There's people from all sorts of places.
Let's start with just talking about what is LLVM?
Cool.
So despite the name, it doesn't really have too much to do with virtual machines.
It's basically just a collection of compiler technologies.
So the LLVM project itself is huge.
But what I worked with is LLVM IR, which stands for intermediate representation.
And LLVM IR is basically a way of representing code that's about halfway between a top level
language.
So for example, Python and some machine code.
So something that you wouldn't really want to read.
You could probably look at the assembler and know what was going on, but it's not something
you would ever really want to write.
But runs much, much faster than something that a human would be able to write.
Sure.
So does...
I don't know all that much about it, actually, that myself.
So do you compile the source language into this LLVM IR and then do a further compilation
towards some final target?
Yes, exactly.
And that's actually what makes it so powerful, is that a lot of the time you have compilers
that have to be very specialized.
So they take a language and they take a platform.
And that is what the compiler does, is it compiles Python for a particular architecture.
What LLVM IR does, which is not unique to LLVM, it's true for all intermediate representations
or most of them, is that it's a way of making things both language and platform agnostic.
So you can take any popular language you want from Java, R, Python, and you can compile it
down to LLVM IR.
Then you can take that LLVM IR and you can ship it anywhere and it can be compiled down to most
platforms.
So it doesn't even matter what the original language was and it doesn't matter what platform
you're eventually going to run it on.
It makes the code really...
It makes it very cross-platform and it makes it fast.
Yeah, sure.
So basically, if you can get something to compile down to LLVM IR, you can get it to
run quickly on many, many places, right?
Because there's existing infrastructure to turn LLVM IR into executable code on all sorts
of platforms, right?
Exactly.
And it's super powerful.
The optimizations that the LLVM IR compilers do make it so that it doesn't matter if you wrote
your code in C or if you wrote your code in Python.
I'm of the opinion that it's much easier to write your code in Python than it is to write
it in C.
And so it's pretty nice because you get the benefits of maybe a more difficult syntax with
pretty much whatever you're comfortable in.
Yeah, that's really cool.
What's the weirdest thing that you can execute this stuff on?
What's the weirdest platform?
That's a good question.
Actually, I don't know.
But I think it's pretty easy to if you just look up the LLVM IR or the LLVM compiler project,
I think it's a really good way to get to know compilers in general.
So there are a lot of proof of concept compilers that use LLVM because the infrastructure is so
good.
So I'm sure somebody has written something for an extremely obscure platform just to show
that they could do it.
Yeah, I'm sure.
Do you think that it makes a lot of sense for people to create from scratch compilers these
days?
Or should most people just be building on LLVM?
I think it depends on what the goal of your project is.
So because this was a project that was done in the world of academia, I pretty much just
picked whatever seemed like would be the most fun.
And I know that's not necessarily true for a lot of people who have needs and users and they
have to work quickly.
And so I think it just depends on if you want something to work faster or if you want to learn
a lot while you're doing it.
Sure.
Yeah.
And I guess also like you only had, it was like a senior project sort of thing, right?
So you couldn't start from scratch and do a ton of work.
You had a time frame and a little amount of time and energy, right?
So I guess that's a-
Exactly.
I had to graduate.
Exactly.
So that's a pretty good testament to LLVM.
Cool.
And I know it's like used for Swift and some other things on the Apple platform and it's
pretty cool.
Okay.
So you also talked about a project to do with machine learning called Tupleware.
And this is a project at Brown, right?
Yes, it is.
So Tupleware's tagline is that it is a distributed analytical platform that leverages LLVM IR to
be totally platform agnostic and totally language agnostic.
So the way that PY LLVM fits into Tupleware, it was basically a proof of concept that you
could take Python code and you could compile it down to LLVM IR and then you could ship
it to your clusters and then have them be automatic and have your code be automatically run on a
very large dataset.
Okay, cool.
So this is like a distributed machine learning type of system and your project PY LLVM basically
made it possible to feed Python instead of say C++ code or something like that to it, right?
Exactly.
And I chose Python because I didn't really want to write an R compiler, but also because at
the time I was working on this, which is about three, three and a half years ago now, the language
that most scientists were using for programming was still MATLAB.
I actually had a summer job where I converted MATLAB code to scientific Python code and it was
becoming more and more common that people who were not programmers would be programming in Python
instead of just inheriting these old MATLAB scripts that they would reuse.
So that's why I've picked Python.
Yeah, that's cool.
I've definitely seen that as well.
When I was in school, MATLAB was definitely the thing and people would have all these scripts
and one of my first programming jobs was to take a bunch of MATLAB code and turn it into like
graphical visualizations on Silicon Graphics supercomputers and I had to convert the MATLAB code to C++
but if it was today, I very well might have done that in Python instead, right?
Yeah, that's funny.
Sounds like the same job.
Yeah, exactly.
Exactly.
Awesome.
And so you said PY LLVM started from an abandoned open source project.
What's the story there?
Basically, once I had pinned down what exactly I wanted to do for my thesis,
I went on a search spree where I tried to figure out if somebody else had done it for me,
which would have been very convenient.
But at the time, I couldn't find any Python 2 LLVM IR compilers that were already up and running or already published.
So what I did is I found this GitHub.
Actually, it wasn't even GitHub.
It was a Google code, right?
Yeah, it was a Google code project, which had been documented almost zero.
There were some slides in Japanese that I found, which I tried to feed through Google Translate, which did not work.
So it was basically just some code.
And it ended up being almost exactly what I needed because it was a pretty simple compiler outline without any of it really implemented.
But the structural stuff was there.
So a lot of the scoping and a lot of the variable tracking had been started but not finished.
So it was kind of the perfect project to pick up because a lot of the design decisions that would have resulted in a lot of cost versus value arguments.
So, you know, we could implement it this way, but it would take a lot of time and we might not actually get that much out of it was sort of already decided for me.
So I had a pretty clear path in terms of getting the subset of Python it supported to be something that I thought a user could actually make use of.
Yeah, that seems really great that, you know, that's out there and you can pick it up.
And it's funny it was on Google Code because not only was the project kind of abandoned, like Google Code itself is kind of in archive mode, right?
I guess it's a real testament to GitHub.
I think it was in archive mode when I found it even.
It's definitely in archive mode now.
It's several layers.
Yeah, but that's helpful that it's like, well, we already kind of put the thinking into place, but hey, I need to – they just didn't take it to completion, right?
And so, like, okay, these are the final to-dos on this project or whatever until I can actually use it on Tupleware.
Yeah, I mean, when I found it, it wouldn't even compile.
So I have really a lot of respect for the person that wrote it because it really had everything – it was clear that this person didn't actually run it, but they had thought about it a lot.
And the skeleton was there, but it hadn't actually gone through the process of becoming a tool that could be run.
And that, to me, is very incredible.
I mean, I run my code every 10 seconds just to make sure that it's working.
Exactly.
Yeah, I'm with you on that.
Like, run it often.
So, yeah, I guess some people – you know, probably more in the early days when compiling took longer and stuff, but some people really sit there and work through it, and then they run it.
You know, hours after hours of work, that's just how I work.
I run it often.
Yeah, it's very impressive.
Yes, indeed.
It takes a subset of Python.
I can't feed it like Django and have it spit that out, right?
Because what happens is it takes the Python language and it turns it to LLVMIR, which then finally compiles down to machine instructions.
But there's no interpreter.
There's no standard library underneath there for it to run, right?
So, you've got to be pretty focused on what you give it.
Yes.
What it does have is sort of the C standard library.
So, for example, if you want to call, like, Printline, you can do some somewhat complicated gymnastics in order to get LLVM to make that external call.
So, that's really nice because getting Printline to work when you're writing a compiler is so important.
And when it does work, it's, like, really one of the best feelings ever.
But generally, no, if you wouldn't be able to import a Python package, for example, since the goal of the project was really just to provide people an alternative to using MATLAB.
So, instead of writing your machine learning algorithms in MATLAB, you can write them in Python.
Or, you know, in this case specifically, it'd be instead of writing in C++, you're writing it in Python.
But the nature of those algorithms is that they're quite simple.
So, we didn't – I didn't spend a lot of time trying to get objects or more complicated data structures working because I didn't anticipate it would be that common.
Right.
So, you're working with, like, loops and join and map and stuff like that.
And then you feed it basic algorithms, huh?
So, like, Bayesian stuff or linear regression.
Yeah, exactly.
You feed those off, huh?
Okay.
And I'm not a machine learning – I had not really done much machine learning at that time.
So, I basically just went to my ML professor and was like, give me, like, your top five most common machine learning algorithms that you would expect to want to run on large data sets.
I'll make these run in Python through this thing, right?
Nice.
And so, yeah.
So, you basically – you write the algorithms.
They compile down and then finally get transformed to run basically on the C, C++ runtime, like you said.
And that goes through something called Boost Python, right?
What is Boost Python?
So, Boost Python – Boost is a bunch of packages for C++ that provide a lot of really, really powerful capabilities.
And so, Boost Python is actually just an easier way of calling the Python C API.
If I had done this now, I probably just would have skipped using Boost entirely because I'm pretty comfortable with the Python C API.
But at the time, it was sort of the first Python plus another language interfacing I had done before.
And this was pretty simple because it was already being used by Tupperware itself.
So, I didn't have to do a lot of – I didn't actually have to incorporate it into the ecosystem.
It was already there.
Yeah.
That's cool.
Yeah.
And by now, you've done so much with PyMongo and all the stuff in MongoDB.
Yeah.
Cool.
Okay.
So, give us, like, a short example of what this algorithm might look like.
I mean, code over audio is really hard.
But just, like, what kind of stuff would you feed off to this system?
So, I would expect there to be – so, you've got to assign to your variables.
You most likely have an array that you are assigning values to.
You need to iterate through the array or you need to iterate through the data that you've been given.
And you need to do a lot of – or at least a decent amount of error checking.
So, what that means in terms of syntax is you would want to have reassignable variables.
You would need to have conditionals, loops, and arithmetic.
Those are basically the most important things.
This portion of Talk Pythonry is brought to you by us.
As many of you know, I have a growing set of courses to help you go from Python beginner to novice to Python expert.
And there are many more courses in the works.
So, please consider Talk Python training for you and your team's training needs.
If you're just getting started, I've built a course to teach you Python the way professional developers learn, by building applications.
Check out my Python Jumpstart by building 10 apps at talkpython.fm/course.
Are you looking to start adding services to your app?
Try my brand new Consuming HTTP Services in Python.
You'll learn to work with RESTful HTTP services as well as SOAP, JSON, and XML data formats.
Do you want to launch an online business?
Well, Matt McKay and I built an Entrepreneur's Playbook with Python for Entrepreneurs.
This 16-hour course will teach you everything you need to launch your web-based business with Python.
And finally, there's a couple of new course announcements coming really soon.
So, if you don't already have an account, be sure to create one at training.talkpython.fm to get notified.
And for all of you who have bought my courses, thank you so much.
It really, really helps support the show.
One of the things that seems a little challenging to me is like you're building something in Python
and it's being more or less just compiled into the results of C++, which is a typed system, right?
So, it expects, you know, here's a four-byte integer.
Here's a Boolean.
Here's a string pointer, right?
Whereas in Python, you don't really have that, right?
So, what do you have to do to make the type system sort of fit together there?
That is a problem that comes up sort of time and time again because no matter how many layers of abstraction you're talking about,
ultimately, machine code is pretty strictly typed.
And we don't really like working in strictly typed languages.
So, there's a lot of cost-benefit analysis going on there where you could say I demand that I can reassign my variable from an array to an integer
or between different types of numbers, for example.
Or you could say that's going to save me a ton of work if I just tell my user who I anticipate is probably used to MATLAB.
Don't do that.
This is Python, but it's not that Pythonic.
Like, you know, maybe down the line when this is no longer a proof of concept.
Ultimately, what we ended up doing was just sticking to pretty static types because whenever you write a compiler,
it's kind of a debate between how much do I want to reinvent the wheel and how much are my users going to be willing to sort of have a more limited experience
for the sake of, like, my sanity or how much time I'm willing to put in on this project.
Sure, that makes a lot of sense.
I feel like because it's such a limited set of types, really, that you can write your algorithm in,
it's not so bad to sort of restrict it and talk about the types, right?
You've got, like, the fundamental numerical types, strings, lists, and a few other things that they can really work with, right?
Yeah, and I definitely, that's what we're trying to sell here.
But I remember having this argument where I came up with what I thought was, like, a super clever solution for how we're going to do dynamic types.
And it was, like, twice as much code as the entire compiler was before that point.
And I brought it to my advisor.
I was like, this is such a good idea.
Like, I can't wait to implement this.
And he kind of looked at me and he was like, this is not what we need right now.
What we need is something that is working, which is, I guess, was my first experience with, you know, writing code that actually needs to do something.
And it needs to do something as soon as possible.
As opposed to code that's, like, beautiful and elegant.
And I've, like, prototyped it three times.
And I have all the time in the world.
So.
Yeah.
You know, shipping is a feature, right?
Yeah.
No one's going to use your code if you don't actually get it out there and get it working, I guess.
Yeah.
I mean, I still struggle with that now.
I definitely like to write code that is fully baked as opposed to just, like, getting stuff out of the door.
But I'm definitely getting used to that now that I'm working in JavaScript more.
Yeah, it's one benefit.
That's awesome.
Yeah.
Yeah, I guess I really appreciate getting something out there so that people can use it and give me feedback.
Like, this is working.
This is not working.
But, yeah, you just have to have some flexibility.
You can't get locked into, like, some early prototype API or something, right?
Yeah, exactly.
Yeah.
So you said that some of the LLVM IR features made your life easier and some made it harder.
How'd that work out?
So probably the most involved issue that comes up between converting from Python to a intermediate representation is like what you mentioned with types and reassigning.
LLVM IR is written in SSA, which means static single assignment.
And what that basically means is that you have your registers, which are your smallest unit of storage, and you can only assign to them once.
So if you assign a number to your register, even if you want to assign something of the same type, it is frozen for that function call.
So what I needed to do to get around that was basically move everything onto the stack.
And once everything is on the stack, then you need to keep track of stuff using what people call a symbol table, which is basically just a dictionary where you can look up.
I have a variable named X, and it lives at this memory address, and it's been around for this long and all sorts of other metadata like that.
Okay.
So, yeah.
Does that make sense?
Yeah, yeah.
That's pretty interesting.
You can only assign to them once.
Okay.
Pretty interesting.
And then memory management, how did that work, actually?
Because everything was on the stack, for the most part, things basically just took care of themselves.
I didn't have to write a garbage collector, thankfully.
But there was one particular instance that was really awkward.
So if you are making a function call and you want to return something that can't fit into a register.
So say, for example, you have an array, or you have a function call that populates an array, and then you want it to return the array to the original caller.
The problem there is that you can no longer save that on the stack.
Because as anyone who's ever programmed in C or C++ knows, it'll go out of scope.
So the solution there is either, oh, do I have to keep track of scopes now?
Do I actually have to write a garbage collector?
Do I have to reinvent memory management in Python myself in two months?
And the answer to that was, okay, no, that doesn't make sense either.
So what ended up happening is I would just move the data that you put in your array onto the heap temporarily and then pass back a pointer to it.
And then either copy it into the stack again and free it, or just chalk that up to a memory leak and let the stuff that you return from a function just call it a memory leak.
So that's sort of a lose-lose situation.
It was definitely one of those things that if I had had more time, I would have liked to dig into that.
And dynamically reassigning variables to two parts of the compiler, I feel like, are unfinished.
Sure.
Okay.
Yeah, that's a big challenge in adding your own garbage collector.
That sounds like a lot of work.
Sounds like it could be really fun, but it sounds like a different thesis.
Exactly.
It's not my problem right now.
Okay.
Interesting.
So how was the performance?
Say, like, one of the options was I could write my code in C++ and I could give it to Tupleware, or I could write it in Python and give it to Tupleware.
What was the trade-off there in terms of performance?
Was it huge or pretty close?
So in terms of performance, I actually do have the numbers that I ran that I can dig up.
But the bottom line was that the LLVM compiler itself was much faster.
If you take C++ and you compile it down to LLVM IR using a compiler that I think is written in LLVM IR itself, or at least in C or C++, compared to a compiler that is written in pure Python that takes in Python code, does all the, builds the syntax tree, does the parsing, all the semantic error analysis, that kind of thing.
It takes longer, but it doesn't take an order of magnitude longer.
So if you're running ML algorithms on huge data sets, having the compilation of your algorithm, which only happens once, if it takes one second or if it takes five seconds, it doesn't really matter because we're talking about hours and hours of work.
So it's definitely slower, but for what the project needed, it wasn't inhibitively slower.
Yeah, yeah, sure.
And for the execution speed, like would the algorithms run about the same or was it really different?
So the algorithms itself, once they got down to LLVM IR, pretty much ran the same.
There were a couple interesting cases there.
So what actually happens when the code gets put into LLVM IR and is then shipped to the other half of the distributed system where it gets actually compiled, analyzed, and run, is that is all handled by LLVM and C++.
There's no Python involved in that.
And so the optimization passes that the LLVM IR compilers actually do are incredibly powerful.
So the reason that there's not a lot of optimization happening in the compiler itself, I mean the compiler from Python to LLVM IR, is that it's pretty much going to get squashed no matter what with the LLVM passes themselves.
So that was a huge benefit because I didn't really have to sweat optimizations, which is another huge part of compiler writing.
Yeah, that's awesome.
Just let LLVM do its analysis on the intermediate representation, yeah?
Yeah, I mean it's a huge selling point of LLVM IR.
But there is some interesting stuff about optimizing function calls.
And basically if you have a recursive call, it becomes a lot more difficult.
I basically discovered that the LLVM IR compiler is not as good at unrolling these recursive calls as it is when you give it Python code because there's sort of, if you're doing...
It just basically doesn't like the recursion so much, huh?
Yeah, there's some things that you have to do in Python that you don't have to do in C++ because it's closer to the end result that ends up tripping up the optimizer.
And so for an algorithm that involves recursion, it will actually perform slower.
Okay, interesting.
Yeah, so this sounds like a really cool project if you have something super focused like Tupleware where you can take a really small subset of Python and execute it against that system, right?
There's a bunch of different implementations or runtimes out there.
So we've got things like IronPython and Jython that try to take a different take on Python.
There's PyPy, there's Pigeon, there's Cython, and Numba.
It sounds like you're much closer to something like Numba with this project than you would be, say, with Cython.
Yeah, I think that a lot of the sort of the line in the sand that gets drawn between projects is everybody is trying to get Python code to run really, really fast.
But the way that LLVM IR actually factors into it can vary a lot between projects.
So the goal of Numba is to run your Python code super fast.
LLVM IR is just one step in what is, I think, a six-step process.
And there's not actually, there wasn't actually a way to extract the LLVM IR directly from Numba, which has changed now.
But when I initially wrote it, they didn't have that ability.
So I would have had to basically go in and pick and choose bits from their code and then move it into a separate project because there was no elegant way to really pull it out.
Another huge difference is that a lot of these compilers are JITs, which work great for what they're trying to do and generally work faster.
But the thing about JITs is that they're lazy.
And if you have a lazy compiler, it won't actually compile anything unless it's run.
But for Tupleware, we're completely unconcerned with running the code.
We just want to compile it and then we want to take that compiled code and pass it off to somebody else.
I see.
So that's basically part of the mechanism for deploying to this distributed cluster, right?
Because you've got to give it the executable code.
I see.
So sort of ahead of the time JIT compilation would be as close as you could get or something.
I did some performance comparisons between Numba and PyLVM.
But the problem there is that there's no way to actually run code using my compiler.
But you have to run the code in order to compile stuff with Numba.
So if you're doing benchmarking, the actual cost of the algorithm itself, it doesn't negate the data, but it makes it a pretty big asterisk.
Like, by the way, we also had to run the algorithm.
Yeah, sure.
So it's hard to compare apples to apples.
Yeah.
Okay.
So I guess maybe we should kind of wrap it up on PyLVM and talk about your MongoDB stuff.
But what's the two quick questions?
Is this a Python 2 or Python 3 project or both?
This is Python 2.7 is what I wrote it in.
Yeah, sure.
Okay, cool.
And what's the future for this project?
Do you know if anyone's picking it up or, you know, people out there listening, if it sounds interesting, you can pick it up.
It's on GitHub, right?
Yes, it is on GitHub.
I would really recommend people to look at the project and to contribute.
But that is also from like a curiosity slash selfish interest.
I think that if you're going to do it, there are a lot of design decisions that were made in the interest of this specific project.
And so if it matches your use case, that's excellent.
And so if it matches your use case, because there are so many variables, I recommend just writing one because it's probably one of my favorite projects I've ever worked on.
Just because it's such a neat, like a very well defined and very satisfying problem to solve.
Nice.
Do you feel like you understand how a lot of these compilers and execution fits together better now?
Yeah, I think it's probably the best learning project anyone could have is to actually understand what goes on under the hood of the language they use.
It also made me much, much better at writing optimizations work.
Okay.
Yeah, very cool.
All right.
So let's talk about this, what you're up to these days at MongoDB.
And you said you'd worked on PyMongo.
And just for everyone listening, like that's the primary driver.
The primary way to speak to MongoDB is to, you know, pip install PyMongo and import it.
And then you just start talking.
And basically the data exchange is dictionaries, right?
You write a prototypical query sort of thing as a dictionary and you get back rows, which are documents in the forms of dictionaries, right?
Yes, that's correct.
So you don't actually have to get dictionaries anymore.
For a long time, PyMongo would just automatically read your data into dictionaries.
But now you can actually get raw BSON out of the driver.
And that opens up a lot of doors for what you can do with it.
Right.
So BSON is binary JSON, which is the actual in-memory on-the-wire representation that you get talking to MongoDB.
You had a cool talk about something called Monary, which is kind of getting superseded by the project that you're working on now.
But you had some interesting performance numbers about getting dictionaries back or just in terms of analysis in general.
Forget the database for a minute.
Like working with dictionaries versus working with lists versus something like NumPy, right?
Yes.
So that was pretty enlightening for me as a relatively new Python programmer to realize that Python dictionaries, which I considered was kind of the most basic way of storing data in Python, was actually pretty slow.
And compared to like ND arrays, which are C-style arrays that come with the NumPy package versus just something like a list, they are significantly slower.
Yeah.
You had some cool numbers.
You said something like for a certain algorithm, working with a bunch of Python dictionaries, you could do like 12 million a second.
Yes.
And with lists, it was close to 10 times as much, 110 million a second.
And with NumPy, you could do 500 million a second.
Yes.
And that's just a really simple like take a bunch of data that's in this form and just add them all together or like make pairs or something like that.
Right, right.
Like basically read through it or something to that effect.
Exactly.
Okay.
And so you said, look, the way with the BSON capability notwithstanding, like basically the way that PyMongo works is you do a query, you get a bunch of dictionaries back in Python.
But if you're doing data science or something computational, you probably want to work in, say, NumPy, right?
But the workflow would be I make a query in my Python layer.
It goes to Mongo.
That comes back across the wire.
It gets turned into Python dictionaries and then serialized back in down in the C layer into NumPy.
And that was a problem, right?
Yes, that's a huge problem because you're taking something that is pretty fast, namely MongoDB, and you have something on the other end of your line, which is also really fast, NumPy.
And then you have this bottleneck, which is Python dictionaries.
And it's kind of a shame that there hasn't been more stuff related to this until recently because MongoDB is an incredibly powerful database and it's very easy to use.
And NumPy also has a selling point that it's extremely powerful and pretty easy to use.
So you'd think that for a lot of data scientists or for people who don't love coding in MATLAB, they would want to put these two tools together.
But MongoDB hasn't been used in this context super often because of the limitation that in order to get the data out, you have to put it through this kind of clunky data structure before getting it back into your super fast arrays.
Right.
So you said basically with some tests you did, like going through PyMongo, you could read about from MongoDB through Python into NumPy about 150,000 documents a second.
And there's this other project called Monary that you were talking about when I saw this presentation where it basically says, let's stay down in the C layer the entire time.
And even though we're calling it from a Python app, it sort of connects it directly to NumPy, right?
Exactly. So now we are taking this raw BSON format and basically moving it directly into C style arrays.
So you have two things that are in sort of natural machine order and you no longer have to take it out of that.
Nice. And that's something like 10 times faster, right? At least it was.
Yeah, it was 1.7 million reads per second compared to 150,000.
That's a big difference. You might.
That's like a difference between going and getting a cup of coffee while your algorithm runs on your data versus going to lunch or something.
Yes, exactly. And so it's really exciting to me that we can leverage these two really awesome technologies.
And Monary itself is actually not under active development anymore.
Monary is a project that actually was community based.
It was started by somebody who did not work at MongoDB, David Beach, who basically wrote it because he was sick of having to lose so much time to Python dictionaries.
And so now we are writing a codec that is 100% in C that takes this raw BSON, which before, I think maybe a year or two ago, you couldn't actually get raw BSON from PyMongo, but now you can.
So now you can take this raw BSON and you can have this super lightweight package that just converts it directly into NumPy and you are good to go.
That's really cool. So what's this thing called now?
So this is called BSON NumPy, which is a deeply uncreative name.
And I am definitely open to alternatives, but it is descriptive.
Basically, it is in beta.
So maybe closer to alpha because we stopped working on it about two weeks ago and we released, we actually released about two weeks ago.
So it's the project of both me and a Jesse Giryu Davis, who is my coworker who you spoke to twice, I think.
Yeah, yeah. Jesse's a friend of the show.
So hello, Jesse.
And nice work on this project as well.
We are both really eager to hear people's feedback.
We really want MongoDB to become more useful for data scientists.
And we think that this is really the tool that is going to make it happen.
Yeah, it seems like a really great idea.
Just we'll skip the serialization where it's slow and just flow the data straight into NumPy.
This portion of Talk Python is brought to you by Hired.
Hired is the platform for top Python developer jobs.
Create your profile and instantly get access to 3,500 companies who will work to compete with you.
Take it from one of Hired's users who recently got a job and said,
I had my first offer on Thursday after going live on Monday and I ended up getting eight offers in total.
I've worked with recruiters in the past, but they've always been pretty hit and miss.
I tried LinkedIn, but I found Hired to be the best.
I really like knowing the salary up front.
Privacy was also a huge seller for me.
Sounds awesome, doesn't it?
Well, wait until you hear about the sign-in bonus.
Everyone who accepts a job from Hired gets $1,000 sign-in bonus.
And as Talk Python listeners, it gets way sweeter.
Use the link Hired.com slash Talk Python to me and Hired will double the signing bonus to $2,000.
Opportunities knocking.
Visit Hired.com slash Talk Python to me and answer the door.
I guess people can just go to MongoDB and find it.
How do they learn more about this project?
Because it's in its very, very first iteration.
It's not...
We released it on bsunnumpy.readthedocs.io.
And you can find it on Read the Docs.
Basically, we...
Neither myself nor Jesse are data scientists, but we're both super familiar with Python and
we're super familiar with MongoDB.
But that does leave a lot of open questions that I wouldn't necessarily know how to answer.
So I'm not sure what the most common data type for NumPy would be.
I mean, there are all these really cool, complex data types, but for all I know, nobody ever
uses them.
So what I really want is to be able to reach out to the community and have people tell me
what they need.
Because a lot of the great features at MongoDB pretty much came out because somebody had a
need and they asked for it.
So we wrote them and then it became a huge selling point.
So what I want is just to hear from what people who would use these technologies really want.
Yeah, absolutely.
So people can check it out.
It's bsun-numpy on PyPI.
And also I'll put the link in the show notes.
So check it out and give both of you guys feedback on like, hey, this looks really cool, but it
doesn't do whatever, right?
Exactly.
Nice.
You also had in your presentation about Monary, it's still kind of the same type of question
and answer type thing that you get the same kind of analysis you can do.
with Bison-numpy, you had an interesting analysis you did of taxi cabs and Times Square, right?
Do you want to tell people that story?
Sure.
So when I first joined MongoDB, I was working out of the headquarters, which is in Times Square
in New York City.
As a side note, right now I work out of Stockholm, Sweden, which I prefer quite a bit more to
fighting my way through the crowds.
But I was struck one morning when I was trying to think of sort of a nice data set to
sort of show examples of how much faster Monary would be than Pymongo.
I just was so sick of fighting through the crowds and fighting to get to the train station.
And I kind of figured like, wow, what is...
Why is there a Batman in my way?
What's going on in this place?
Exactly.
It's like, how can I get out of here as fast as possible?
Like, where can I go?
How can I do it?
So I also had access to the taxi data for all of New York City, which is freely available
online.
And it's a really interesting data set.
And so I basically just took that data set and I looked at all the rides that both started
and ended in Times Square.
Because I kind of just wanted to know, like, where are people going?
Like, what's the rush?
Where are you coming from?
Why are you coming here?
Of all the places in New York City to be, why Times Square?
Okay.
Yeah.
That's really cool.
And you found, you had a really great bunch of visualizations that came out of MATLAB.
And I'll put the link to that video up there because you have, you know, some really great
maps and like bars living on flat maps and all kinds of stuff.
I thought that was great.
Yeah.
It's like, it's MATPLOTLIB.
Oh, yeah, yeah.
Sorry.
I keep, I don't know why I said MATLAB.
MATLAB because we were talking about, yeah, yeah.
MATPLOTLIB is what I had in mind.
Yeah.
But yeah, no, I mean, the point of those diagrams were just basically to show off how
cool NumPy can be and how powerful MATPLOTLIB can be for creating really beautiful visualizations.
And I know that there are a lot of different visualization tools out there.
But in terms of selling Python and providing a way for data scientists to use both MongoDB
and NumPy, I felt like it was a pretty good sell.
Yeah, that's cool.
And you also were able to leverage, I think the interesting linkage there is you were able
to put a huge amount of data in Mongo and apply a geospatial index to it and then use that
in your queries, but then also do the analysis with NumPy, right?
Mm-hmm.
Exactly.
So you are taking advantage of these geo queries, which are really simple, really easy to use,
but also very fast.
And you are taking advantage of Python, NumPy specifically, where you have really, really
fast analysis, but a lot of these algorithms are actually written for you.
So you can use a lot of these scientific Python packages that have done what I consider the hard
work for you completely.
Yeah.
It seems like just take the tools, click them together, and you get some really great
analysis.
That's awesome.
Yeah.
So I'm looking forward to your presentation where you talk about your Bison NumPy version.
Yeah.
Well, I'll have to find something better, some better visualizations and some, you know, I
don't have as many things to complain about now that I live in Stockholm.
So I have to...
Yeah.
You can do something with snow or winter or something.
Who knows?
Yeah.
The darkness.
Yes, exactly.
Here's the light analysis.
All right.
Cool.
So I guess let's go ahead and leave it there.
That sounds like a great project.
And so if you're out there working with MongoDB and ultimately your data ends up in NumPy,
you know, maybe skip the dictionaries is the message, right?
If you can.
Yeah, exactly.
And especially for people who use scientific Python and have never considered MongoDB a viable
option, I think that is going to change.
And I think that we are going to be able to write programs that take advantage of all this
cool work that has already been done.
Yeah.
And I think having it officially part of the product, the library, gives it a little more,
probably gives people more confidence to build upon it.
Yeah, exactly.
And I am personally just so excited because this is the first project that I've really had
ownership over.
I contributed a lot to PyMongo, but it wasn't my project.
Well, I feel very proud of what I've done for this particular project.
It sounds really, really cool.
So, so nice work.
Let me ask you a couple of questions before we get out of here, as I always do.
First one, if you're going to write some Python code, maybe not C code, if you write some Python
code, what editor do you open up?
So I use PyCharm.
And it's funny that you mentioned C code because I got a perpetual license for JetBrains.
And I love that I can write, I can write Node, I can write Ruby, I can write Python, I can write C.
And all my shortcuts are the same.
I was a Vim user before Jesse convinced me to switch over to PyCharm.
And now I'm like completely converted.
I can have all my Vim shortcuts and I can also have all the power of a really great IDE.
So I really recommend the JetBrains libraries because it's really nice to not have to switch
between IDEs, between like SeaLion, PyCharm, Ruby9, WebStorm.
You know, it's the same environment.
So I feel like I don't have to lose any time to relearning stuff.
Yeah, that's really cool.
Jesse's a big fan of PyCharm and so am I.
Just so people who are not familiar, basically there's this IntelliJ platform, which is kind
of the IDE and then they plug in the language specific stuff.
So like when you say it's all the same, it's like all kind of the same base.
And like you said, like it behaves the same.
It's pretty sweet.
Yeah.
Okay, cool.
And we just this week passed 100,000 packages on PyPI.
So that's a big milestone.
Hooray.
Wow.
Yeah, no kidding.
And so there's a ton of them out there.
Do you have one that maybe like you think people don't necessarily know about?
You're like, hey, you should check this out.
BSON NumPy maybe?
Yes.
Is it too shamelessly self-promoting to say that you should download BSON NumPy and that's
the best package on PyPI?
It's one of the newer ones.
That's a really good question.
I guess I'll just go with that because I'm very utilitarian with my packages.
I pretty much just keep them to a minimum.
Okay.
Yeah.
Very cool.
All right.
Yeah.
It's a great package.
And you know, you guys need some people to try it out and actually do real data science
with it.
So that's great.
Exactly.
All right.
So final call to action.
What do you want people to check out or do?
I would like people to check out BSON NumPy because I think it's a really cool project.
I think that if anyone is interested in a really neat piece of code, they should look through
the LLVM Py work, especially if you're either new to compilers, maybe new to Python, new to
LLVM IR.
It's a very nice sort of pet project and it's very self-contained and it is, in my opinion,
pretty well documented.
There's an entire 20-page thesis I wrote about it.
So if you have questions, they're probably answered.
I'm also always happy to answer by like email, Twitter, anything.
So those are my two things I would love to see people do.
All right.
That sounds great.
Ana, thank you so much for being on the show.
It's been really interesting to talk to you.
Yeah, of course.
Thank you so much again for having me.
Yeah.
Thanks so much.
Bye.
This has been another episode of Talk Python to Me.
Today's guest has been Ana Herlihy and this episode has been sponsored by Hired and Talk
Python Training.
Are you or a colleague trying to learn Python?
Have you tried books and videos that just left you bored by covering topics point by point?
Well, check out my online course, Python Jumpstart by Building 10 Apps at talkpython.fm
slash course to experience a more engaging way to learn Python.
And if you're looking for something a little more advanced, try my Write Pythonic code course
at talkpython.fm/pythonic.
Hired wants to help you find your next big thing.
Visit Hired.com slash Talk Python to me to get five or more offers with salary and equity
presented right up front and a special listener signing bonus of $2,000.
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.
Our theme music is Developers, Developers, Developers by Corey Smith, who goes by Smix.
Corey just recently started selling his tracks on iTunes, so I recommend you check it out at
talkpython.fm/music.
You can browse his tracks he has for sale on iTunes and listen to the full length version of the theme
song.
This is your host, Michael Kennedy.
Thanks so much for listening.
I really appreciate it.
Smix, let's get out of here.
I'll see you next time.
I'll put it in.
Thank you.