 All right, good morning. So quiz two being graded today, so Hopefully you'll be able to get it back today. The grading session is tentatively 11 to 1 So hopefully it'll be done by one might be slightly after that. Hopefully you can see them Oh, no, it's not great Yeah, the the question what the average is in and they're not graded yet. How do I know what the average is? No, we're grading it. So the TAs are grading it at from like 11 to 1. So they might be done by one So I'm not holding back the average or anything. I don't know what it is Hopefully you get it back today. And then if anything are messed up you can just Email me I guess if you're in this section Okay, so today we'll be talking about the more page replacement and the clock algorithm for this And we'll essentially be doing this all lecture and just drilling in page replacement So that is Is a nice and easy topic for the next quiz or the final or whatever it shows up in so We left off last lecture talking about least recently used and how Well, we could argue about it. We could do all the page faulting But if you actually went to implement it, it would be terribly terribly slow so One of the approximations of least recently used is called the clock algorithm and it looks something like this So The data structures it has it just has a circular list of pages in memory. So just a circular list Uh or a buffer of all the pages that are currently in memory And then each page that is currently active has a reference bit associated with it And when we argue about it in the slides the value of the reference bit is going to be in the light gray box And because it is a bit its value is either going to be zero or one So it's going to be one bit and then the final data structure we have is we have a hand That's why it's called like a clock because we can draw it so it kind of looks like a clock But it's basically just an iterator or a pointer that points to the last element Examined or what I should probably choose to swap out so Given those data structures. This is the entire algorithm So to insert a new page So if it's not into memory and I need to swap it in I need to pick a page to swap out This is how I do it So I check the hand's reference bit So whatever page the hand is currently pointing to it will have a reference bit associated with it If it's zero that means it hasn't been referenced in a while that means I'm going to replace it So if it's zero I swap out that page put in the new page and then I advanced the hand So the iterator is pointing to the next element and the intuition behind that is I don't want to try and replace The element I just put in because it is the most recent access So I would just swap or I would just go over it and advance it to the next hand and then The other case is the hand is pointing at something with a reference bit as currently one So if the reference bit is currently one, I just Change the one to a zero And then I advance the hand and then I repeat this process until I find somewhere to place it So it essentially gives things a chance to survive and whenever You access a page to keep track of whatever is least recently used or an approximation of it For each page access all it's going to do is set the reference bit from a zero to a one And that's okay. So generally having operations that happen on every single page access is Bad because it's going to be like pretty slow, but in this case We're doing the least amount of work Pretty much humanly possible on each page reference all we're doing is flipping one bit So it's actually not that much work So we do most of the work whenever we need to pick something to swap out And for each individual page access we just change the reference bit to a one. Yep So yeah, the question is if the hand goes to the end what happens to it essentially So it's a circular buffer. So it's just going to go back to the first element So it's going to try and insert something if you need to insert it And it's probably going to monkey with the hand and go around because at minimum Like if we're pointing at something with a reference bit of zero We'll change it to we'll insert it and then advance the hand one spot and we'll see it So we'll go through an example and we'll We'll make this Imprint into your mind. So here's our example. So I even drew off a pretty little clock So this would be like a circular buffer. So it would be an all in memory But I'll just draw it as a nice little circle So we'll assume our memory can only hold four pages So initially what's in memory? It's page zero or some invalid page with no reference bit So the top of the box is the number associated with the page and the bottom in the light gray Is the reference bit which would be either zero or one So again, we're going to assume memory can only hold four pages And then we have the following accesses one two three four five two three one two three So if we do that and we just follow the algorithm First access we have We have an access to page one It is not in memory. So we need to swap it in. So we just follow the algorithm So the hand's initially pointing at the first element in the array or whatever it is And then we would look look at it. Hey, its reference bit is zero So we can evict whatever there is there initially. It's just empty anyways So I would insert page one set its reference bit to one and then advance the hand one position So this is what the clock looks like right after we insert page one So next is going to be the same thing. We have page two So the iterator of the hand's pointing at something that is empty. So we would go ahead insert it So we now inserted page two its reference bit is one and we advance the hand And now this is what the clock looks like at the end of our Whenever we resolve the access to page two Similarly, we get page three. It's going to do the same thing the hands at a zero We insert page three advance the iterator one spot and now it looks like this Now we have an access to page four It's going to be real boring because it's going to do the same thing. So we insert four its reference bit is zero or sorry its reference bit is one and we advance the hand So now things are going to be a bit different. So now we have an access to page five Which is not in memory. So we need to pick something to swap out So we're just going to follow the algorithm So the current pointer of the clock is pointing to page one its reference bit is a one So I can't swap it out yet. I give it another chance So reference bit is one. I change it from a one to a zero and advance the iterator So it just advances one spot and then now it's pointing at something reference bit is one So now the reference bit I'm going to change from a one to a zero advance the hand Now I'm stuck same thing again. I'm going to change the reference bit from a one to a zero advance the hand This particular scenario the first time you're just going to go around the entire clock once so it's going to be real boring so Pointing at four its reference bit is one. I change it to zero Now I pointing at page one Its reference bit is now a zero. So I pick to swap that page out so All I would do is insert page five set its reference bit as one and then advance the hand one position So now after I insert page five The clock looks like this Any questions about that So What's going to happen when I access page two? Yeah, so it's already there I don't have to swap anything in or out I don't have to move the iterator or monkey around with the iterator All I do is set the reference bit from a zero to a one because I just used it So after the access to page two We would set the reference bit to a one again We want if you are just doing accesses you want to be as fast as possible because that is a much more common operation So we're just flipping one bit. We're never touching the iterator Then when we access page three, what's going to happen? Set the reference bit from a zero to a one Okay, now the clock looks like this So now when we access page one, we need to pick something to swap out and we just follow the algorithm again And note if we did like first in first out, we would have just booted out page two at this point But in this case because we referenced it and we're kind of keeping track of it We're not going to push it out because it has a reference bit set So it's kind of like least recently used so If we try and put in page one The the hand of the clock is pointing at page two its reference bit is a one So we just set it to a zero and advance the iterator one position Now we're pointing at page three Reference bit is one So we change it from a one to a zero and advance the hand one position Now we are pointing at page four its reference bit is a zero So we choose to swap out page four So we would swap out page four with page one its reference bit would be set as a one and we would advance the iterator of the hand So this is what the clock looks like At the time when we right after we insert page one So any questions about that? Okay, all good. So now we access page two It thankfully is still there. We didn't get rid of it So we just set the reference bit from a one or a zero to a one And then our final access is to page three. So we would go ahead and set the reference bit from a zero to a one Then this is it. So If we go through usually you would draw out your page faults and everything while you have this but it takes up too much room on this So here was our page faults for the exact same question. So for the first access We swapped it into memory second third fourth That's what happened And then for the fifth access we choose to swap out page one Then we access page Two and three and they were hits and we changed the reference bit to one Now when we came to swap in page one we replaced page four So it looked like this and then we had an access to page Two and three. So if we count our number of page faults for this scenario, there was six So Just for a bit of practice We can do the same Accesses and try and remember from one lecture What would happen if we did the optimal strategy? So we can kind of compare to what the clock did to what optimal would do So If I did the optimal strategy here, so remember you're going to do the smart thing and look all the way into the future So Initially memory is empty. So it would look like this. So on the first access to page one. What do I have to do? I Yeah, I just swap it into memory So initially everything is on disk. I would swap it into memory. So First access I swap into memory and I'll put blue as kind of the page I swap in So then we have accesses to two three and four. It's going to be boring So I'm just going to do a little bit of a shortcut here Skip some steps So my first four page access I'm going to fill up memory. They're just going to be swapped in So after this for optimal If I try and access page five, what page do I remove Page one I hear what there's a one and there's a four so Remember optimal. So we're currently here at this access to page five Yeah, so it's not going to remove Or it's going to remove the page that's used furthest in the future. So Between one two three and four. I'm definitely not going to remove page two because I use it right after Yeah, I'm not going to remove page three And I'm not going to remove page one So that leaves me with I have to remove page four so When I so I would swap in page five for page four And it would look like that Now when I access page two Well, that's a hit because I was doing the optimal thing. So I predicted the future And then when I access page three again, it's going to also be a hit because I was smart Page one also going to be a hit Page two also going to be a hit And finally page three also going to be a hit So at the end of this I had five page faults so I'd Optimal case I had five page faults in the clock. I had six so It was close enough. It was better than most So for some more bit of practice. Yeah, yeah all the question is essentially for this hey You know, we can't realistically predict the future but machine learning is pretty good. So why don't we plug that in and see how it does And yeah, it's kind of slow for this but there is work of Putting AI stuff into systems and seeing was that there was one interesting paper that Essentially tried to use machine learning You know, whenever you have like a b-tree or a big tree and you need to search in it Instead of like actually resolving the search just use machine learning to guess what the index was And it actually worked pretty well So there is work to throw AI stuff into offering system stuff, but I'll talk about at the end because this Nowadays this doesn't even really matter that much Yep, okay So for the purposes of more practice, we can just hammer this to death. So let's do the clock again With this sequence of accesses So if we have these accesses, I'll go ahead and draw a very nice clock Actually, let's make it a bit bigger So I'll just assume that there's four pages again And this is what my clock is going to look like initially whoops so These are all my memory accesses So if I have an access to page one, well We just follow the algorithm. There's currently nothing in memory. So we would have to swap it in The clock is pointing to some Whoops some invalid page with a reference bit as zero So we would just go ahead and insert one there set its reference bit as one And then advance the iterator So at the end of the first access it is going to look like this So we just swapped in page one and we'd We set its reference bit to one and we'd advance the iterator right in the hand And then Also, just like as a side if you went to actually implement this The reference bit would not live on the page itself because the users are using the page You can't just randomly take a bit and use it for whatever you want So you would essentially just have a big bitmap that just keeps track of all the reference bits So if you only have one bit per page, that is one bit every like 4096 bytes So it actually is not that big And we'll see kind of that idea once we get to file systems because file systems use the same idea that thing's called a bitmap and Spoiler alert file systems basically just deal with blocks as well. They call them blocks, but they're the size of a page So file systems pretty much everything follows the same thing so When we go to access page two, whoops Page two whoops different color If we go to access page two the iterator is currently pointing at something the reference bit is a zero So we would just insert it here Advance the iterator one position and then it would be swapped in so then Again when we access element three, we do the same thing It is pointing at an invalid page. So we insert three one advance the iterator and it looks like this So now when we access page four We do the same thing again the hands pointing at something the reference bits is zero We change it from a zero to a one and insert page four advance the iterator of the hand And we swap in page four Okay, so now what's going to happen when we access page one again Sorry Yeah, it's already in memory. We're good. It's reference bits. It's already one as well So we don't even have to change anything So We just ride the wave we didn't change anything the clock doesn't change at all its reference bit was already a one Now We access page two same thing is going to happen. It's already in memory It's reference bit is a one and we don't have to do anything Now We access page five Oh, no, it's not in memory. We have to pick something to swap out Well, it's the first time So it's essentially going to do the first in first out thing but go around the stupid clock But We'll go around and just do it anyway. So we're pointing at an element where the reference bit is a one So we can't replace it. We change the one to zero Advance the iterator Again, same thing change the one to zero advance the iterator Again change a one to zero advance the iterator Then we're at four change the one to a zero advance the iterator Now we can we're pointing at something the reference bit is a zero So we choose to swap that out and we swap in page five So we replace one with five set its reference bit as one and then we advance the hand one position So we replaced five with one And then this is what is currently in memory So now we have an access to page two So what do we do? Yeah, so it's already in memory. We're not swapping anything But we're changing its reference bit from a zero to a one because we just used it Now we have are going to access page three and it's going to be the same thing So its reference bit is currently a zero. We change it to a one And it was essentially a hit So now we access page five again And its reference bit is already a one so we don't have to do anything Now our next access is to page two We don't have to do anything as well. It's already in memory its reference bit is a one So we have five Two three four still in memory Now when we try to swap Uh, when we try to access page one, it's not in memory. So we have to do something So we have to swap out something for page one. So we're just going to follow the algorithm So the element we're currently pointing to its reference bits of one So we're not going to replace it. We're just going to change the one to a zero and advance the iterator Now we are going to do the same thing the reference bit is a one We change it from a one to a zero And then we advanced the iterator Now we're pointing at four and its reference bit is a zero. So we get to replace that So we replace four with a one And set its reference bit as one and then advance the iterator So now luckily we replaced four with one And now in memory we have pages five two and three still now now we go to Access page four and oops, we just kind of kicked it out. So we have to swap something back in Or we have to swap something out for it So I'm just going to follow the algorithm again. So it's currently pointing at five reference bit is one So we just change the one to a zero And we advance the iterator. So we're not going to get rid of five Now we're pointing at page two its reference bit is zero. So it is gone So we replace two with four And then set its reference bit as one and then advance the iterator So now in this case we replace two with four Five three one So if we count our page folds, we have one Two three four five six seven Okay, any questions about that? Yep So the like the iterator itself So the iterator itself only changes once when you're picking something to swap in So on any access that's a hit The most you're going to do is change the reference bit of one of a page from a zero to a one So you only move the iterator when you have an access that you have to swap into memory Because remember the idea here is on normal accesses We want to do the least amount of work as possible and our least amount of work is just flipping one bit So if the access is a hit and it's already in memory, we just flip a bit. We don't touch the hand at all Because if we had to do a bunch of pointer operations for every single memory access on your machine That would be really really slow Yep Yep So when you move the hand so it would just be some data structure in the os that knows In the kernel that knows what pages are currently in memory Yeah, yeah, I'd be just like be a link list or something like that and just follow pointers Okay, any questions about that or want me to do the same sequence of accesses and beat your heads over it with like optimal or FIFO or something like that So I I guess I'll leave that and We can wrap up a bit bit early and then Has anyone started lab four yet? No You about lab four Okay, uh Sure, so I'll wrap this up quick and then I guess I'll keep the recording on and take lab four questions or anything else So this is a nice break though, right a lot straightforward easy questions Yeah Yeah, this would probably be this is fair game for the next quiz or the file or whatever So these are the questions. I actually remember from the os course All right, so Whoops, I need to swap back to my slides Okay, so all this too is kind of More relevant before So for performance reasons if you have to cash to your disc or whatever that can be slow, it's kind of Coming back around where hard drives are really really slow, but they're getting much much faster But if you really care about performance in your google or something like that rams cheap now So in your kernel you may choose to disable this entirely and you would rather prefer instead of your applications go slow They just crash without of memory and then you go to the store and you buy more ram because rams fairly cheap so In linux what we saw too when we had those examples Whatever I ran out of memory. It just said, oh no, I'm out of pages to give It essentially looked for looked at all the processes looked at the one that was consuming the most amount of pages and just sag killed it so it Was it is now dead. So it invalidated all those pages. They were free to be used for anything else and it freed up memory so another thing you can do too as a different trade-off since those Page sizes are fairly small Is for most hardware Especially now you can choose to use larger page sizes Sometimes they call them huge tables or huge pages And they can either be two megabytes or one gigabyte and those sizes might seem a bit odd But they're chosen if we go back to our multi-level page table question well Those boundaries essentially just eliminate one extra level of page tables So if I had remember there was like nine bits for each individual level For like sv was sv 48 whatever it was called Um So we had nine bits for each one. So this is just nine bits different. So Instead of a four kilobyte page that had three levels I could have a two megabyte page that has two levels Or I could have a one gigabyte page that only has one level and we're back to single level page tables And they become relevant again But the drawback is you're going to have more fragmentation Which we'll talk about more when we get to memory allocation too Because hey if your application only uses, you know, like four kilobytes and the operating system only deals with pages Well, if you use a one gigabyte page suddenly your application is using a whole gigabyte of memory And it's not going to use nearly all of it So you would only use like one gigabyte pages if you know your application is really really really memory intensive Otherwise two megabytes probably better nowadays And you also get the additional benefit of your TLB If with the same number of entries it covers more space So if I only have to so instead of having you know To the nine entries that cover two megabytes in spaces That's just a single entry that covers two megabytes And I can fit more in my cache and then more things are cached and I have a better TLB hit rate So I'll have faster memory accesses So any questions about that? Okay, yeah Yeah, so if you run ls or Any program you've probably written like a hello world something like that That basically uses nothing for the one we wrote all the way back in lecture two It didn't even use a kilobyte. It was like 168 bytes So Doesn't use that much memory at all So a lot of it would be wasted and wasted memory is essentially called fragmentation and we'll see it later Okay, uh lab four question So the question was in lab four when I create 10 children You are asking how you wait on them So yeah, you would probably want to use weight pid because in the lab spec You have to actually if one of them returns an error code in the spec You have to pick the first one in the sequence and return that as the error code So because you create all the processes you should know the process IDs of all them And you should be able to wait specifically on those processes And the order you wait in them doesn't really matter But the return code matters Yeah, your your main process in lab four is not going to finish until all the child processes finish So also in the lab spec, you are not allowed to create orphans So you wait on all of them you wait for them to finish all of the test cases will finish Yeah, easiest thing to do is you just have a loop and you Wait over everything What's slow about that What's slow about that? Yeah, but the parent has to wait for all the processes to end before they to get their exit code because they have to end Yeah, sorry, what so if you call weight on Yeah, the so the question is what happens when I call weight and the process isn't dead yet Yeah So in that case what will happen is your process calls weight and the child is not dead yet So the kernel will just block it So it'll just be blocked and it won't run again until that child's Yeah, so the process will be blocked. So the scheduler will essentially just let the child run So you're so yeah, the main program is not going to return until the child's done Okay, any other questions? Yeah The big example tablet, yeah One Sorry The first entry instead of the first one So Okay, so I'm going to delete this and go back So essentially you're asking The first access to five so like what happened there. So All right, let's rewind then So when we add the page access to five are This clock two one So right before the access to five. This is what the clock looked like So since this is what the clock looked like we have to swap in page five. We just follow the algorithm So in this case the iterator is pointing to page one reference bit is one So we can't replace it. So it goes from one to a zero and then advances the hand And then it's just going to do the same thing again. So This reference bit is a one we change it to a zero advance the hand Now it's pointing at page three reference bit is one we change it to zero advance the hand Same thing for four we change it from a one to a zero advance the hand And now our iterator is pointing at the first page where the reference bit is a zero and just following the algorithm That means that one's gone So you you start Like whatever the iterator is pointing to is where you start No, you just wherever the iterator is pointing to is where you start So that's why we draw it out and we don't redraw it every time we don't reset the iterator It just stays there until we need to make a decision So at this point why we picked one is because currently the iterator is pointing to one its reference bit is a zero So we swap that out page five Its reference bit is one and then our final thing we do before we go the next access is we advance the hand one position So we swapped out page one with page five and then So for instance now if we access page one again instead of page five Well now we don't reset the iterator or do anything with it We just follow the algorithm with what it is currently pointing at so currently it's pointing at page two Its reference bit is a zero so we get rid of it immediately So we would insert page one for page two And then advance the iterator And then we're done. So we would have swapped out page two with page one No, so I said instead Yeah, instead if you access page one after this is what will happen Not what's on the side because we did that Okay, so Let's wrap up then and then I'll stick around. Whoops. That's So again, this is the whole clock algorithm data structure circular list of pages in memory, whatever your however many pages you can fit into memory And there was a reference bit for each page And that would be stored somewhere else in the kernel that keeps track of the pages Because the kernel is going to know what's actually in memory then the other thing the Clock algorithm has is an iterator or a hand that you only update whenever you're swapping things in and out of memory So that was the algorithm to insert a new page you check Whatever the hand is currently pointing to you check its reference bit If it is a zero then that page is swapped out So you would swap in that page said its reference bit to a one and then advance the iterator of the hand one position Intuition behind that is you just inserted the page You don't want to try and remove it because next time you have to swap something out It's going to start by looking at whatever the hand is currently pointing to and it probably shouldn't point to The thing you just put in so that's why The intuition why we advance the iterator after we insert a element And then the other case is the reference bit is one so I can't replace it So I change the one to a zero and just advance the iterator one position And just keep going on this until I find a page to evict. So worst case I'm going to go through every single page once and hopefully average case. It's better than that So and then also the other part of this for page accesses to keep track of least recently used I'm instead of like doing a timestamp or anything. I'm just approximating it So I just set a reference bit to a one if it is currently a zero So that's it. I'll turn off recording stay around here lab four lots of fun. Hopefully again quiz three Hopefully back soon. So just remember pulling for you. We're all in this together