<?php
class Pamiec {
protected $iFizyczna = 0;
protected $aFizyczna = array();
protected $iWirtualna = 0;
protected $aWirtualna = array();
protected $aKolejka = array();
protected $aOdwolania = array();
protected $sTyp = 'FIFO';
public function __construct($iFizyczna, $iWirtualna, $sTyp = 'FIFO') {
$this->iFizyczna = $iFizyczna;
$this->iWirtualna = $iWirtualna;
$this->sTyp = $sTyp;
$this->aOdwolania = array_fill(0, $iFizyczna+$iWirtualna, 0);
}
public function kolejka($iAdres) {
$this->aKolejka[ ] = $iAdres;
}
public function execute() {
$iBledyStrony = 0;
foreach($this->aKolejka as $iKey => $iAdres) {
$iBledyStrony += $this->get($iAdres);
unset($this->aKolejka[ $iKey ]);
}
return $iBledyStrony;
}
public function get($iAdres) {
// na potrzeby LRU
$this->aOdwolania[ $iAdres ] = 0;
if(in_array($iAdres, $this->aFizyczna)) {
return 0;
}
if(count($this->aFizyczna) >= $this->iFizyczna) {
// echo '<hr />! '.$iAdres;
// $this->drukuj();
// usuwam z pamieci wirtualnej
$iKey = array_search($iAdres, $this->aWirtualna);
unset($this->aWirtualna[ $iKey ]);
//odpowiednie sortowanie
$this->sort();
// przepisywanie pierwszego elementu fizycznej do wirtualnej
$iTymczasowy = array_shift($this->aFizyczna);
$this->aWirtualna[ ] = $iTymczasowy;
}
$this->aFizyczna[ ] = $iAdres;
// na potrzeby LRU
foreach($this->aOdwolania as $i => $v) {
$this->aOdwolania[ $i ]++;
}
return 1;
}
protected function sort() {
switch($this->sTyp) {
case 'FIFO': // usuwamy stronę najdłużej przebywającą w pamięci fizycznej
break;
case 'OPT': // optymalny - usuwamy stronę, która nie będzie najdłużej używana
$aOpcje = $this->aFizyczna;
// szukamy w kolejce ostatniego elementu w liscie opcji
foreach($this->aKolejka as $elem) {
// jezeli znajdziemy w kolejce usuwamy z opcji wyszukiwanych
$iKey = array_search($elem, $aOpcje);
unset($aOpcje[ $iKey ]);
// jezeli zostanie tylko jeden element to przesuwamy go
// w kolejce fizycznej na pierwsze miejsce
if(count($aOpcje) == 1) {
$iKey = array_search(current($aOpcje), $this->aFizyczna);
$tmp = $this->aFizyczna[ $iKey ];
unset($this->aFizyczna[ $iKey ]);
array_unshift($this->aFizyczna, $tmp);
return;
}
}
break;
case 'LRU': // usuwamy stronę, do której najdłużej nie nastąpiło odwołanie
arsort($this->aOdwolania);
// echo '<pre>';
// var_dump($this->aOdwolania);
// echo '</pre>';
// sortujemy odwolania a nastepnie szukamy najwiekszego odstepu w fizycznej
foreach($this->aOdwolania as $iAdres => $iCount) {
// echo "szukam $iAdres<br />";
if(($iKey = array_search($iAdres, $this->aFizyczna)) !== false) {
// echo $iAdres.'<br />';
// znaleziony adres w pamieci fizycznej przesuwamy na pierwsza pozycje
$tmp = $this->aFizyczna[ $iKey ];
// echo implode(',',$this->aFizyczna).'<br />';
unset($this->aFizyczna[ $iKey ]);
array_unshift($this->aFizyczna, $tmp);
// echo implode(',',$this->aFizyczna);
return;
}
}
break;
case 'aLRU':
break;
case 'RAND': // usuwamy losowo wybraną stronę
shuffle($this->aFizyczna);
break;
}
}
protected function drukuj() {
echo '<table border="1"><tr><td>Fizyczna</td>';
foreach($this->aFizyczna as $elem) {
echo '<td>'.$elem.'</td>';
}
echo '</tr><tr><td>Wirtualna</td>';
foreach($this->aWirtualna as $elem) {
echo '<td>'.$elem.'</td>';
}
echo '</tr></table>';
}
}
$iIloscStron = 10; //wirtualna
$iIloscRamek = 10; //fizyczna
$iMaxAdresy = $iIloscStron+$iIloscRamek;
foreach(array('FIFO', 'LRU', 'OPT', 'aLRU', 'RAND') as $sTyp) {
$Pamiec = new Pamiec($iIloscRamek, $iIloscStron, $sTyp);
srand(5);
for($i = 0; $i < 1000; $i++) {
$Pamiec->kolejka(rand(0, $iMaxAdresy-1));
}
srand(microtime(true)*100);
echo $sTyp.' = '.$Pamiec->execute().'<br />';
}
preferences:
34.91 ms | 402 KiB | 5 Q