 Welcome back to 353! So today get to continue our journey on page replacement algorithms. So before where we left off we were like oh we can't implement least recently used because it would be too expensive so we can implement some type of approximation of that and that is what we get into today and it is called the clock algorithm. And why? So for reasons that will become apparent in the next slide you can visualize it as a clock. So the data structures we need are we're going to keep a circular list of pages that are currently in memory and this instead of having like a time stamp that keeps track of when a page was last accessed we're going to use a single bit of information called the reference bit that will indicate whether or not a page has been used somewhat recently yes or no that's it just one bit of information and that's going to be updated by hardware so we're going to essentially get it for free whenever we access memory so that will be handled by the MMU. So the other thing this algorithm needs is the hand the hand of the clock which is basically just an iterator that points to the last element examined and then the algorithm only really has two steps so to insert a new page to figure out something we have to kick out we're going to check the element the hand is currently pointing to whatever page that is if its reference bit is zero that means we haven't used it in a while we're going to kick it out of memory and then go ahead and put the new page into memory set its reference bit to one and advance the hand otherwise if what we're currently pointing at has a reference bit of one that means it was used somewhat recently we just change that bit from a one to a zero we do not kick it out of memory we give it a second chance we advance the hand and we keep on going around to find another victim and then whenever you access a page remember that was the thing that happens most often that we need to be really really fast if the reference bit of a page is currently at a zero it will go ahead and set it to a one so easiest way to do this is with a diagram so this lecture can be short depends how much practice we want to do so here is the the diagram the question would be set up like any other question we have so our physical memory can hold four pages and then we have the following accesses assuming all the pages are initially on disk so how I draw it is for each page so we have four the box on the top is the number of the page that is currently in memory right now the page is zero because well it's not loaded and at the bottom in the shaded box is the reference bit so it should either be zero or one and then to make it look like a clock it's a circular linked list of pages so this page points to this one which points to this one which points to this one which points to this one so it just goes around in a big circle and you can draw it like a circle so it looks like a clock the final thing is the hand so this is the arrow that is pointing to a single element and that's when we would start our algorithm so if we are currently accessing page one and we follow the algorithm well page one is not in memory so we have to load it into memory and then we figure out what to evict oh well we take the current hand it's pointing at an entry where the reference bit is zero doesn't actually represent a page so we're going to throw that out we're going to replace it so page one is going to come in we're going to set the reference bit to one and then we are going to advance the hand so everyone okay with that so far so this is going to happen for element two same thing is going to happen we're pointing at a page reference bit is zero so we're going to replace it we're going to put in page two in the memory reference bit is going to be one going to advance the hand then we access page three same thing happens access page four same thing happens now the fun begins when we access page five so now if we follow the algorithm we have to go around the entire clock and this will kind of seem like a pain in the butt to begin with so currently we need we're accessing page five so we need to kick something out of memory and if we follow the algorithm well our hand is pointing to page one its reference bit is one so we are not allowed to kick it out of memory we would set its reference bit to zero so it gets essentially one strike against it sometimes this algorithm is called the second chance algorithm so set its reference bit to zero advance the hand and then we try to replace page two its reference bit is one we cannot kick it out of memory so we would set its reference bit to zero advance the hand then same thing with page three can't kick it out of memory we're going to go around and look at every single element it's kind of annoying so we're going to look at element three its reference bit is one okay we set it to zero advance the hand and then we do it for page four reference bit is one so we have to set it to zero advance the hand so if you want to do a shortcut of that you could just set everything to zero because it's just going to go around in a circle and we're going to start off right where you're going to end up right where you started off at just with everything as zero instead of one so now if we follow the algorithm well now we are pointing at page one its reference bit is zero so that one gets evicted so we swap out page one put in page five and then we would set its reference bit to one and then advance the hand and then our clock looks like this after we access page five so everyone okay with that sweet so now this is where the magic comes in so now if we access page two normally for anything else we didn't really update everything but now since we access page two well what's going to happen is we used it so its reference bit would just get set to one so we would not change the hand we would not do anything we only move the hand when we're doing the replacement because well that's going to be slow anyways because we're loading something in from disk in the memory for normal accesses we want to be as fast as possible so if you want to justify it you don't update the hand you don't update anything with normal accesses all you do is set a bit so now if we access page two well we have now used it we should note that we have used it somewhat recently and give it a second chance if we try and get it out so on accessing page two we set the reference bit from a zero to a one and that's all that happens so zero to one that's it that's it and it would be a page hit like it's already in memory but internally for this algorithm we update the reference bit to be a one all right okay with that if we we are pretty much survive today's lecture isn't this a lot easier than locking and synchronization and virtual memory and everything like that it's kind of a nice relief right so yeah it gets easier towards the end we got past the hard part so now when we access page three what's going to happen yeah we just used it so we said it's referenced from a zero to a one yay that's as hard as it gets today so now whatever we access page one now well this is where again it's called second shot so because we just reference them well if we use like first in first out we'd kick out page two but now when we want to bring something in to replace or kick something out to bring in page one well if we follow the algorithm now we can't kick out page two because its reference bit is one so all we would do is set its reference bit to zero advance the hand try and find another victim then we're pointing at page three its reference bit is one can't kick it out so we have to find another victim so we'd set its reference bit to zero advance the hand and now we're pointing at a page the reference bit is zero so we can kick it out of memory and we can go ahead and replace page four with page one set its reference bit to one advance the hand and now our clock looks like this after the access and then now we're accessing page two well it gets another strike that it can use so we would set its reference bit to one or zero to one and then we access page three we would set its reference bit from zero to one and then our final state would look like this so if we have another access to like page four or something we could shortcut this and just set all the reference bits to zero because we know it's just going to go around the clock because all the reference bits are one so it's going to do that thing where it tries them all again but we're okay with this all right so if we wrote it out with our normal way of just putting a box of everything that's in memory so typically for these questions you have the clock as you work through it and you just fill in this chart as you go through wasn't enough room on the slide but this is what would look like at the end of the day we had four four faults initially we had to load them in the memory we moved the clock around and all that fun stuff and then for page five we went around and we replaced page one with page five then when we access page two we set its reference bit to one access page three sets reference bit to one and then when we went around it and access page two page one we kicked out page four so we would write it like that and then when we access page two and three they were both hits so we can figure out the number of page faults we got how many page faults we got four or not four wow okay not awake six hopefully number of red things so if we want to compare that to optimal well we could have fun everyone loves optimal right so if we speedrun optimal it would look something one one one two two three so if we access page five and we have the optimal algorithm what page in memory do i kick out four right so i look forward i can't kick out two can't kick out three can't kick out one so i would just kick out four turns out well in this case i don't really have to do anything else pass that so i kick out four for five it looks like this and then everything else is a hit so the optimal thing to do is i get five page faults which hey clock got six optimal got five so it turns out to be pretty decent all right you want me to do this with the clock for fun sure all right let's do it we should should still have time at the end for whatever you want to so whatever we do the clock this is let's say we have four pages or four frames we can fit in memory so draw four boxes top is the page bottom is the reference bit and then initially it's zero so i can draw arrows like this and then i don't know i usually just point the first iterator up because i don't know why not so if we access page one well all these accesses are going the first four accesses are going to be pretty boring right so they're just going to be like one one go ahead advance the hand access two it's going to be two one advance the hand then we're going to have three one advance the hand then four one advance the hand and after our fourth access it's going to look like this right so i will draw that out so one two three four i'll kind of squish them together so everything fits one one two three we're okay with that so far all right so now i access page one what happens yeah so page one its reference bit is already one if it makes you feel better you can erase one and then put a one if you want or you could just leave it alone uh up to you so whatever makes you feel better so that's a page hit nothing changes so we can just write out all the pages again access page two what happens same thing i could either erase a one and replace it with a one or i could leave it alone so that would be another hit all right access page five do you want to do this a slow way or the fast way fast way what's the fast way yeah just change them all to zeros so one one one get all changed to zeros and then we can just start from there so now we're pointing at something where its reference bit is one or sorry zero so that one gets kicked out so we would kick out page one so we could draw that over here to the side and replace it with page five and then advance the hand after we inserted it and you can kind of see why we need to advance the hand after we insert it because if we didn't then it would just be pointing at whatever we just inserted and we would immediately have a strike against it so we would change the reference bit from a one to zero and that doesn't make sense because we shouldn't it shouldn't be the first one we put a strike against since it's the one we most recently put into memory so why would we do that so after accessing page five it looks like that two three four so all good all right so access page two what happens yeah reference bit gets changed from a zero to a one so we can do that otherwise it is a page hit so we can just repeat everything then we access page three again same idea this would be updated by hardware in fact if you like look at the page table entry and most things where this reference bit is stored is in the page table entry so your mmu is going to handle it whenever anyone tries to access that page gets updated for you and it's actually stored in the page table entry so we access page three it's reference bit would change from a zero to a one it would still be a hit we're all great so now we access page five this is hopefully getting somewhat boring that means my job's mostly done so access page five it's reference bits of one again for fun we could erase it and then put a one so that was fun so page hit nothing else changes same thing for page two again we got lucky so everything is still good then we access page one so what happens with this so we just follow the algorithm again so the hand's currently pointing at page two its reference bit is one so we can't replace it we just put a strike against it so we change its reference bit from a one to a zero advance the hand trying to find the next victim next victim is three but we can't get rid of it because it's reference bit is one so it gets another shot at life so we change its reference bit from a one to a zero and then advance the hand and then oh now we're pointing at page four its reference bit is currently zero so it gets kicked out so we would replace page four with page one so I can erase page four oops put in page one set its reference bit to one and then advance the hand so now my memory looks like this so we're all good so far still all right now we access page four we just follow it again so we can't get rid of page five so we set its reference bit from a one to a zero advance the hand oh now we're pointing at page two its reference bit is zero so we can get rid of that so we would replace page two with page four and then if we want to finish it up put in page four reference bit is one advance the hand and now we're done we can count the number of page faults we have hopefully I can count again and hopefully it is seven page faults all right sweet was that ever fun or what so if I put this on an exam it will be no issue right okay cool um do you want to do another example or okay great we're bored that's great so we can I will re wrap up the lecture really quick and then you can work on lab six and I'll be here uh because why not so for performance some of you or at least like some companies might be like I really don't want this so if you start swapping things from memory to disk things get really slow right disk is a lot slower than memory and if you're google or something like that you probably care more about performance and you do about money money like you can just throw money at if you have a problem you can throw money at that's pretty good especially since ram is generally cheap and high capacity like servers can have terabytes of memory like ram in them it's not that expensive so what some people do and what I do generally on my laptops is I'd rather know that I ran out of memory I just need to go buy more than things just being slow so what you can do is you can go ahead and just disable swapping completely so that if for some reason you run out of memory while you just get an error or linux just starts killing something so if you actually physically run out of memory your kernel is going to run something that has a great name it's just called the out of memory killer and basically all it's going to do is seg kill anything that's using a lot of memory and just free up that and then suddenly you're no longer out of memory so it would probably like sig kill something like chrome if it's smart and then boom you have memory again no problem um you could diagnose it and be like okay well my program just crashed because it ran out of memory I'll just go to the store and I'll buy like 32 more gigs of memory which last time I looked as like 100 bucks now or something like that so not even that expensive uh I guess unless you're apple and then it's like probably like 800 bucks yikes um and then some other things with memory four kilobytes pretty small for page sizes so if you have larger page sizes so essentially they is go up by like they pretty much just get rid of the lowest level of page table and then use that last index space to use that for a page instead so instead of four kilobyte pages on some systems especially macOS and I think other operating systems are starting to do it more now instead of four kilobyte pages you can have two megabyte pages or if you go up and eliminate two levels of page table that means each of your pages are one gigabyte in size so if you see in your operating system something called huge pages a huge page is two megabytes and then if they have one gigabyte pages they call them gigapages yeah very creative names and the goal here is that or the tradeoff here is well you have more fragmentation because if your program actually just uses like five kilobytes or eight kilobytes or something like that I could fit on smaller pages without wasting space well if you have a two megabyte page like when we discussed for some memory stuff we'll see more memory in the next lecture the rest of it's just going to be unused so we're going to have more fragmentation but the tradeoff is for the same number of entries in the TLB so if I only have like 10 entries and my pages were four kilobytes that means I can only essentially cache 40 kilobytes worth of memory but if I have two megabyte pages and I have that same those same 10 entries but they now just cover a wider space well now I can cache essentially 20 megabytes of memory and generally things go a lot faster so like your iPhone stuff like that that'll use huge pages so it'll probably be like the two megabyte pages things are kind of moving more in that direction now because four kilobytes is basically nothing all right any questions about that all right so wrap it up then so clock algorithm it is an approximation of least recently used data structures circular list of pages in memory uses a reference bit so make sure you draw them out draw them in a circle draw two boxes one for the page number one for the reference bit and then you have a hand that points to the last element examined which you only use for page replacement and then whenever you want to do some page replacement the algorithm is as follows check the page the hand or check the entry the hand is currently pointing to if its reference bit is zero then that page gets checked out of memory you would insert the new page in set its reference bit to one advance the hand and then keep on going otherwise if its reference bit is one you change it from a one to zero gets another shot and then you advance the hand to try and find another victim and then most importantly four page accesses that's what you want to be really really fast because that happens every time you access even a byte in your program so all you do then is to set the reference bit to zero or sorry set the reference bit to one don't mess with the hand don't do anything you want that to be as fast as possible so with that just remember well for you we're all in this together