 Hey guys, how's everybody doing? I'm Racheer, I'm going to talk about Intervalation Search. So let's do it. About me, typical self-obsessed programmer starting off with himself, this slide sums it up. I want to go fast, more specifically, I want to write fast code. I want to take code that is just an idea and make it as fast as possible. That's what I love about computers. That's why I do this. And that's really what this is about, sort of less so than the specific search algorithm. This is about how we, and to be really clear, it's not just me who did this. I stand on the shoulders of giants. No person is an island, blah, blah, blah. I'm just the guy they put on the stage. Right? We took a research paper and we tweaked it until it became something that was actually fast and useful and prod. And the paper's name is Intervalation Search for Not Independent Data by some amazing folks at MIT. So check it out, I'll have a link later. So let's dive in. What's the problem? It's a problem that I think many people or many companies have. Right? You have a large static set of items that's huge and it's sorted and you want to do many searches on it. And obviously, like I said before, you want to do it fast. So what do you got? What was our old solution? Pretty standard thing, a sorted array with binary search. This is this algorithm that many people know and understand and love. But can we do better? Right? That's the question that we ask ourselves. And what does better look like? What do we want? Right? Ideally, we want something better than the theoretical guarantees of binary search. So maybe better than like of log n. That would be dope. Right? Like low space usage, cash efficient. That would be awesome. And I don't know about you guys, but in the battle between intuitive and unintuitive, I always prefer the intuitive algorithm. So that would be amazing as well. So, okay. How can we use sort of those things? What do we know about the data that we have? We know it's range. We know it's kind of random-ish. And then beyond that, we don't want to be too clever. We don't want to like try to fit to certain properties of the data that it might have today, but not tomorrow or the day after that. Right? Like, you don't want to be over smart. Okay. So what's the main, what's the first idea? And this is from the paper, right? Bucket the data. And there's a pretty intuitive sort of human real-world analog to this show of hands. Who's used a phone book sometime in the recent past? Wow, that's a lot of hands. Wow, I've never used a phone, wow. Anyway, so hypothetically, let's say I wanted to call Stevie Wonder and say that I loved him. Right? Thank you. Right? What I would not do is pop it open and it's like, okay, J is less than W, so cut to the next cut. I'm like, oh, is less than W. And then like T is less than W. And then I'm looking and it's like, oh, Wonder's not in there because Wonder isn't his last name. Right? What I would do instead, I would just hop to the Ws and search and fail there. Right? But what's the point? The bucket tells you where to look. It provides a way to sort of really drastically reduce your search space and it's useful. So how can we use that? What is a bucket though? Like we gotta step back for a second. Right? Phone books and things with words have letters and so you can bucket by like the first letter. So like alpaca, alphabet, Arthur are all in the A bucket and then like cantaloupes and cactuses or I don't know, Charles are all in the C bucket but numbers aren't letters usually. So what are we gonna do? So it's gonna be a different approach. It's gonna be a different kind of bucket. We'll have a range, like a minute and max in our sorted set and we'll define buckets that evenly subdivide the range. And I don't know about you guys but like I kind of glaze over when I hear about math. So now we're gonna go to visuals and I made that. So just appreciate it. Thank you. I got some hate for this, surprisingly. This is a sorted array. The red numbers are what's in the array and then the little numbers. I don't know if you all can see that. Can people see the little numbers on the bottom? Those are the array indices. Sweet, I had no idea if anyone could see that. So that's great. And this has a range of like one to 89. The parentheses says that like that's not part of the range. It's like a math thing. So let's say we want two buckets. Done, right? So the buckets cut the range in half. So the first bucket covers like one to 44 and the second bucket covers like 45 to 89. So the first bucket has all the numbers. It's like really wide and the letters are all spread out. It's the first bucket. And then the second bucket only has sort of two items and it's like kind of stacked and narrow. That's the second bucket. And we're gonna need to store information about where each bucket starts and ends but that's how we would represent this sort of abstractly. So that's great. And around this time, we had our second idea and this one is gonna blow your mind. The end of one bucket is always right next to the start of the next. At the end of the A part of the phone book is like the B part of the phone book. So we don't need to store the start in the end. We can just store the start of each bucket which sort of has our memory usage which sort of doubles our cash efficiency somehow. And that's good. That those are good things, right? So what does that look like? So I've done this now. So this like upper smaller array, this tells you where each bucket starts and ends, right? So the first bucket starts at index zero and ends at index eight. The second bucket starts at index eight ends at index 10 which isn't a real index but sort of it just works. If you don't read past, like if you know that 10 is one more than the length of your array, the idea, this arrow points to nowhere. Don't, don't read it. Great. How would you use this in an example? Let's try to look up 27. So 27 is bucket zero. Why do we know that? So 27 minus the minimum value which is one is 26 divided by the bucket width. So 26 divided by 44 is zero. So okay, that's bucket zero. That's that bucket that I circled which tells you to look at those two numbers that I circled and then you can just binary search. So real quick recap, figure out what bucket you're in by like subtracting from the minimum dividing by the bucket size. The bucket tells you where to start and end in your like thing to look and then binary search. Why is this cool? Why is this cool? It's binary, in the worst case, in the pathological case where all your data is in one bucket, it's just a binary search and a divide and a read. So it's not that much worse than just a binary search. That's not bad. And if the data is uniformly distributed which I put in quotes because I don't know what it means. Then the lookup is actually a lot better than regular binary search and it's O of log log of N with O of N log N buckets. I swear to God, I know how to prove that but I'm not gonna do it. So trust me. So this is where we leave the world of the paper. And we ask, can we make this better? And when someone says something like that, I tentatively say yes, but you know, then I think about what are the bottlenecks here? And it's like computers don't love to divide and I don't blame them, I don't love to divide either. You know? So okay, the divide adds latencies according to processors like 30 to blah, blah, blah. Right, it's slow. So can we maybe not divide? And this brought me back to like fifth grade and I know how to do this. X divided by Y is the same thing as X times one over Y, done. Solved, killed it, except not really because one divided by Y for computers is often gonna be zero if, because computers are not great at dividing. But this approach is on the right track. You're gonna need to think spatially because I couldn't bother with latex. So X divided by Y is the same thing as X times K divided by Y divided by K. So like just imagine there's a K and a K and the K's cancel, right? So you're left with X divided by Y. And if you pre-compute K divided by Y, then it's a multiply and then another divide. But maybe if computers can really mess with K easily, like maybe if K is the power of two, then this will be a good thing. It'll be a multiply and then a bit shift, right? Like what's a million divided by a thousand? It's a thousand. Everybody knows that really simply because we can just get rid of the bottom two digits. Computers are the same thing with powers of two. That's awesome. Thank you computers, right? So two to the 64 will give us a lot. So now let's look at the code. This is my color scheme. It's like black and green and hackery. So appreciate that. Um, thank you. Um, right? So on top of the C code and it does what we want it to do, right? It multiplies the multiplier, which is K over Y. Can you guys see my mouse? Can you guys see my mouse? Cool, dope. Wow, this is awesome. And multiplies it by the offset, which is K over Y and bit shifts by 64. And I remove the inline so that we can have our sanity with the assembly. And what does it do? Blah, blah, blah. It does a mole queue, which is like an unsigned multiply of a quad word. Quad word means 64 bit of register in this scenario. And so what that gives us, right? When you multiply 99 times 99, the result is a lot and it's also a four digit number. So when you multiply a 64 bit number by a 64 bit number, you get a 128 bit number, the results of which are stored in two registers that are 64 bits each. And since we're gonna bit shift down anyway, we don't really need to bit shift of, and then we can just keep RDX, which is where the high registers are stored. So that's great. So we're gonna divide into a multiply, which is like kind of like a huge win. And now it's graph time because you wanna see some proof and you wanna know that I'm not just like full of shit. So on top, on the blue line is binary search. On the bottom is interpolation search. The Y axis is the number of comparisons. And the X axis is the number of elements in your array. Often in graphs, more is better, but in this graph, less is more, which is better. So you'll see that while the binary search graph goes up into the right, the interpolation search graph stays like kind of straight and flat, which is a good thing. This tracks the difference between log, log event and log n, and this is what we expect. So how much time do I have left? Zero, okay, can I have like a 30 second extra? Cool, so this is a tangent and unrelated to the talk. So late last night at like 2.25 a.m., I was trying to like spruce up my slides a little bit because I had some serious sort of soft doubts about these slides. It's 2.30 a.m. I'm grueling gibberish, like what is buckets? And I found the best image ever, like something way more meaningful than the whole entirety of my talk. That's what I wanna leave you guys with. So this is it. Thank you so much. And thank you organizers, thank you very much, Han. And I wanna thank AppNexus for their sponsorship of this event. All right. Thank you.