Skip to main content

PHP code for Implementing LRU cache.

<?php
interface LRUCache{

        /**
        •@param string $key
        •@param string $value
        •@return bool $result

        •

        •Stores value against the key in the cache */
        public function insertIntoCache($key,$value);


        /**
        •@param string $key
        •@return string $value
        •Gets the value of a key from the cache */

        public function getFromCache($key);


        /** Purge the entire cache */

        public function purgeCache();


        /**
        •@return int $count
        •Gets the number of successful cache hits so far */

        public function allCacheHits();


        /**
        •@return int $count
        •Gets the number of unsuccessful cache hits so far 
        **/
        
        public function allCacheMissed();

}


class Cache implements LRUCache{

        // int the max number of elements the cache supports
        private $capacity;
        // Array representing a naive hashmap (TODO needs to pass the key through a hash function)
        private $hashmap = array();
        // object Node representing the head of the list
        private $head;
        // object Node representing the tail of the list
        private $tail;
        // Cachehit 
        private $cacheHit;
        //Cache missed
        private $cacheMissed;
        /**
        •@param string $key
        •@param string $value
        •@return bool $result
        **/

    public function __construct($capacity) {
        $this->capacity = $capacity;
        $this->hashmap = array();
        $this->head = new Node(null, null);
        $this->tail = new Node(null, null);
        $this->head->setNext($this->tail);
        $this->tail->setPrevious($this->head);
                $this->cacheHit = 0;
                $this->cacheMissed = 0;
    }


        /*Stores value against the key in the cache */
        public function insertIntoCache($key,$value){
          if ($this->capacity <= 0) { return false; }
                if (isset($this->hashmap[$key]) && !empty($this->hashmap[$key])) {
                        $node = $this->hashmap[$key];
                        // update data
                        $this->detach($node);
                        $this->attach($this->head, $node);
                        $node->setData($value);
                }
                else {
                        $node = new Node($key, $value);
                        $this->hashmap[$key] = $node;
                        $this->attach($this->head, $node);
                        // check if cache is full
                        if (count($this->hashmap) > $this->capacity) {
                                // we're full, remove the tail
                                $nodeToRemove = $this->tail->getPrevious();
                                $this->detach($nodeToRemove);
                                unset($this->hashmap[$nodeToRemove->getKey()]);
                        }
                }
                return true;
        }


        /**
        •@param string $key
        •@return string $value
        •Gets the value of a key from the cache */

        public function getFromCache($key){
                if (!isset($this->hashmap[$key])) { $this->cacheMissed++; return null; }
                
                        $node = $this->hashmap[$key];
                        if($node->getData())
                                $this->cacheHit++;        
                        if (count($this->hashmap) == 1) { return $node->getData(); }
                        // refresh the access
                        
                        $this->detach($node);
                        $this->attach($this->head, $node);
                        return $node->getData();
        }

        /** Purge the entire cache */

        public function purgeCache(){
                $this->hashmap = array();
        }


        /**
        •@return int $count
        •Gets the number of successful cache hits so far */

        public function allCacheHits(){
                return $this->cacheHit;
        }


        /**
        •@return int $count
        •Gets the number of unsuccessful cache hits so far 
        **/
        public function allCacheMissed(){
                return $this->cacheMissed;
        }


        /**
         * Removes a key from the cache
         * @param string $key key to remove
         * @return bool true if removed, false if not found
         */
        public function remove($key) {
           if (!isset($this->hashmap[$key])) { return false; }
           $nodeToRemove = $this->hashmap[$key];
           $this->detach($nodeToRemove);
           unset($this->hashmap[$nodeToRemove->getKey()]);
           return true;
         }
        /**
         * Adds a node to the head of the list
         * @param Node $head the node object that represents the head of the list
         * @param Node $node the node to move to the head of the list
         **/

        private function attach($head, $node) {
                $node->setPrevious($head);
                $node->setNext($head->getNext());
                $node->getNext()->setPrevious($node);
                $node->getPrevious()->setNext($node);
        }
        /**
         * Removes a node from the list
         * @param Node $node the node to remove from the list
         */
        private function detach($node) {
                $node->getPrevious()->setNext($node->getNext());
                $node->getNext()->setPrevious($node->getPrevious());
        }
}

class Node {
    /**
     * the key of the node, this might seem reduntant,
     * but without this duplication, we don't have a fast way
     * to retrieve the key of a node when we wan't to remove it
     * from the hashmap.
     */
    private $key;
    // the content of the node
    private $data;
    // the next node
    private $next;
    // the previous node
    private $previous;
    /**
     * @param string $key the key of the node
     * @param string $data the content of the node
     */
    public function __construct($key, $data) {
        $this->key = $key;
        $this->data = $data;
    }
    /**
     * Sets a new value for the node data
     * @param string the new content of the node
     */
    public function setData($data) {
        $this->data = $data;
    }
    /**
     * Sets a node as the next node
     * @param Node $next the next node
     */
    public function setNext($next) {
        $this->next = $next;
    }
    /**
     * Sets a node as the previous node
     * @param Node $previous the previous node
     */
    public function setPrevious($previous) {
        $this->previous = $previous;
    }
    /**
     * Returns the node key
     * @return string the key of the node
     */
    public function getKey() {
        return $this->key;
    }
    /**
     * Returns the node data
     * @return mixed the content of the node
     */
    public function getData() {
        return $this->data;
    }
    /**
     * Returns the next node
     * @return Node the next node of the node
     */
    public function getNext() {
        return $this->next;
    }
    /**
     * Returns the previous node
     * @return Node the previous node of the node
     */
    public function getPrevious() {
        return $this->previous;
    }
}

$lru = new Cache(5);
$db = array(
        "This is item 0",
        "This is item 1",
        "This is item 2",
        "This is item 3",
        "This is item 4",
        "This is item 5"
);
$testPattern = "0,2,4,1,0,5,3,1,5,3,0,1,5,2,5,1,4";

// Implement test pattern.
foreach (explode(",", $testPattern) as $index) {
        $item = $lru->getFromCache($index);
        
        if ($item){
                printf ("Cache hit. - %s\n", $index);
                echo ('</br>');
        } else {
                printf("Cache miss for key %s.", $index);
                echo ('</br>');
                $lru->insertIntoCache($index, $db[$index]);
        }
}

        echo '<br>';

        $item2 = $lru->allCacheHits();
        printf("Total Cache Hit : ".$item2);
        
        echo '<br>';
        
        $item3 = $lru->allCacheMissed();
        printf("Total Cache Missed : ".$item3);

Comments

Popular posts from this blog

Magic Function in PHP (__sleep() and __wakeup() )

There are many magic methods in PHP like  __construct(), __destruct(), __callback(), __get(), __set(), __sleep(), __wake() and many more. But we will be takingon  on  __sleep() and  __wake(). __sleep() : serialize() checks if your class has a function with the magic name __sleep(). If so, that function is executed prior to any serialization. It can clean up the object and is supposed to return an array with the names of all variables of that object that should be serialized. If the method doesn't return anything then NULL is serialized and E_NOTICE is issued. serialize() is used for the representation of the storage class for storing the value. Serializing   an object means converting it to a byte stream representation that can be stored in a file. The use of __sleep()  to commit the pending task. If a bulk data is being inserted then at that time __sleep can be used. it will not release the object unless the work is not completed....

PHP function for checking IMEI

Luhn algorithm for IMEI Check public function __checkIMEI($imei){ if(strlen($imei)==15){ $imeia=($imei[1]*2); if(strlen($imeia)==2){$imeia=str_split($imeia,1); $imeia=$imeia[0]+$imeia[1]; } $imeib=($imei[3]*2); if(strlen($imeib)==2){$imeib=str_split($imeib,1); $imeib=$imeib[0]+$imeib[1]; } $imeic=($imei[5]*2); if(strlen($imeic)==2){$imeic=str_split($imeic,1); $imeic=$imeic[0]+$imeic[1]; } $imeid=($imei[7]*2); if(strlen($imeid)==2){$imeid=str_split($imeid,1); $imeid=$imeid[0]+$imeid[1];} $imeie=($imei[9]*2); if(strlen($imeie)==2){$imeie=str_split($imeie,1); $imeie=$imeie[0]+$imeie[1]; } $imeif=($imei[11]*2); if(strlen($imeif)==2){$imeif=str_split($imeif,1); $imeif=$imeif[0]+$imeif[1]; } $imeig=($imei[13]*2); if(strlen($imeig)==2){$imeig=str_split($imeig,1); $imeig=$imeig[0]+$imeig[1]; } $IMEI= ($ime...

What are the effects of indexing on database tables?

The working of Index in database tables is the same as index work in a Text Book . It will help to browse the desired content faster in a book. we use to see the index on the first page then we check the page where it is in the book and then we directly come to that page, instead of going through all pages. Now databases , same happen with tables, if you are applying select query on the table, it will also check for the index and then return you the required field. It will return the field faster on which index is applied. Or in language, we can say that the index one query will execute faster instead of the non-indexed one. Join will execute faster on indexed one. eg- Consider a Table Product with `id` as Primary Key  id name price category_id  location_id                Table Info- Now  Applying Index on category_id  SELECT category_id FROM product WHERE category_id='5'; SELECT ca...