Jump to content

Sharing high usage objects between sessions


Darghon

Recommended Posts

Hi,

 

I'm creating a webgame in a self made framework.

Right now I'm attempting to make each and every request go as fast as possible, and I've been reading up on caching and have made quite a journey to where I am now.

 

Now my next problem is that during the game, some data gets reloaded every single request, and I want to prevent the server for loading the same data 100's of times / minute during peak moments.

So I googled some, and found memcached, redis, semaphores, sharedmemory blocks, ...

They all look promising, but what should I use...

 

What I want:

I want to be able to get a shared object stack in memory, that every process can access. The objects itself will be saved when changed, but the idea is that the server doesn't need to request the data each time someone refreshes a page, but that it can just retrieve it from a shared memory resource.

 

It would even be fantastic if I were able to provide a wrapper that would react on whatever was available, but that's running ahead of myself.

Anyone have experience in setting up a shared data resource in php? and if so, how can I do this?

 

Thx for any and all responses

Link to comment
Share on other sites

memcached is most likely your best bet.

http://memcached.org/

 

Even if created arrays of text and saved them as xml, you would have bottlenecks in disk i/o, not to mention the size it would grow to.

 

You could look into query cache.

http://dev.mysql.com/doc/refman/5.6/en/query-cache.html

 

Can also do page caching per unique url if the content is the same data, just don't cache user data.

http://devgrow.com/simple-cache-class/

http://files.zend.com/help/Zend-Server/zend_page_cache_-_php_api.htm

http://php.dzone.com/news/php-caching-pages-with-output-

 

Link to comment
Share on other sites

The concept that I had in mind was that I made a block of data, that in case it got full, would kick the least used data.

This way the size would remain very limited, (or within control), and everything that needed to be loaded frequently would be "ready-to-use".

 

The system uses nothing but objects, and the global idea is that in case a rather large portion of memory could be used for this, that the system would only get ID's from the database, and if the object ID wasn't found in the cache, that then, and only then the data would come from the database, and otherwise just retrieve it from global repository. not sure if my explenation is clear though...

Link to comment
Share on other sites

I've been playing around with memcached, installed a localhost memcache server, and implemented my registry to save all objects in memcache.

Now I don't notice any load increases, at all. which is pretty disappointing, so I was wondering if maybe I was doing it wrong...

a test page that loads 24 objects and 7 finders loads in 0.3seconds with the registry (2 objects arrays), and in 0.3seconds with the memcache server (average over 1000 loads)

 

My "MemoryHandler" class handles 2 cases, first case if when you use memcache, 2nd is when you can't.

The class is a singleton, so only 1 instance of it will be available at any time. This class is build and maintained by a static call, so you will never declare it yourself

 

Functions that my objects use are the following:

ObjectCollector::Memory()->retrieve($class,(option)$id);
ObjectCollector::Memory()->register($object);

There are 2 types of objects that can be "cached" this way, a businesslayer object (containing data), and a finder (containing database connection data, and sql statements)

The following is the code for the memory handler, and if anyone sees anything strange, or wrong, do tell... cause this way, it isn't decreasing my load time...

<?php

class MemoryHandler{
/**
 * Mode that specifies that memcached server should be used (if possible)
 */
const MODE_MEMCACHE = 1;
/**
 * Mode that specifies that the systeem needs to keep a collection during load
 */
const MODE_REGISTRY = 0;

protected $timeout = 30;

protected $objectcollection = null;
protected $findercollection = null;
protected $memcache = null;
protected $mode = self::MODE_MEMCACHE;
protected $connected = false;

public function __construct(){}

/**
 * Public function that registers the added connection data to the memcache object 
 */
public function connect($host, $port = 11211){ return $this->addServer($server,$port); }
public function addServers(array $server_array){
	foreach($server_array as $server){
		if(is_array($server)){
			$this->addServer($server["host"],$server["port"]);
		}
		else{
			$this->addServer($server);
		}
	} 
}
public function addServer($host, $port = 11211){
	if($this->mode != self::MODE_MEMCACHE) return false;
	if($this->memcache->addServer($host,$port) === true){
		$this->connected = true;
		return true;
	}
	else{
		return false;
	}
}

public function & register($object){
	if($this->mode == self::MODE_MEMCACHE) return $this->register_memory($object);
	if($this->mode == self::MODE_REGISTRY) return $this->register_registry($object);
}

private function & register_memory($object){
	$class = get_class($object);
	$id = is_subclass_of($object,'Finder') ? null : $object->getID();
	$this->memcache->set($this->generateKey($class,$id),$object,0,$this->timeout);
	$obj = $this->memcache->get($this->generateKey($class,$id));
	return $obj;
}

private function & register_registry($object){
	if(is_subclass_of($object,'Finder') === true){
		if(!array_key_exists($object->tag(),$this->findercollection)){
			$this->findercollection[$object->tag()] = $object;
		}
		return $this->findercollection[$object->tag()];
	}
	else{
		if(array_key_exists($object->tag(),$this->objectcollection)){
			if(!array_key_exists($object->getID(),$this->objectcollection[$object->tag()])){
				$this->objectcollection[$object->tag()][$object->getID()] = $object;
			}
		}
		else{
			//If no previous object of this type is stored, the collection is created, and the object is added
			$this->objectcollection[$object->tag()] = array( $object->getID() => $object );
		}
		return $this->objectcollection[$object->tag()][$object->getID()];
	}
}

public function & retrieve($class, $id = null){
	if($this->mode == self::MODE_MEMCACHE) return $this->retrieve_memory($class,$id);
	if($this->mode == self::MODE_REGISTRY) return $this->retrieve_registry($class,$id);
}

private function & retrieve_registry($class, $id = null){
	if(is_subclass_of($class, 'Finder')){
		if(!array_key_exists($class,$this->findercollection)){
			$finder = new $class;
			$this->findercollection[$class] =& $finder;
		}
		return $this->findercollection[$class];
	}
	else{
		//Set a default variable to be returned if needed (object expected in referenced return)
		$objdef = false;
		//If Business object type is already set in the objectCollection Array
		if(array_key_exists($class,$this->objectcollection)){
			//Check if the collection has the object with the requested id
			if(array_key_exists($id,$this->objectcollection[$class])){
				return $this->objectcollection[$class][$id];
			}
			return $objdef;
		}
		else{
			return $objdef;
		}
	}
}

private function & retrieve_memory($class,$id = null){
	if(is_subclass_of($class, 'Finder')){
		$obj = $this->memcache->get($this->generateKey($class));
		if($obj === false){
			return $this->register(new $class);	
		}
		return $obj;
	}
	else{
		$obj = $this->memcache->get($this->generateKey($class,$id));
		return $obj;
	}
}

public function getStats(){
	if($this->memcache !== null){
		$return = $this->memcache->getStats();
		$this->memcache->flush();
		return $return;
	}
	else{
		return 'memcache not loaded';
	}
}

/**
 * Public function that sets the mode of the memory handler
 * @param Integer $mode
 */
public function setMode($mode = self::MODE_MEMCACHE){
	 $this->mode = $mode;
	 if($this->mode == self::MODE_MEMCACHE){
	 	$this->memcache = new Memcache;
	 }
	 else{
	 	$this->memcache = null;
		$this->objectcollection = array();
		$this->findercollection = array();
	 }
}
/**
 * Public function that retrieves the mode of the memory handler
 * @return Integer $mode;
 */
public function getMode(){ return $this->mode; }

private function generateKey($class, $id = null){
		if($id !== null){
			return Tools::encrypt($class.$id);
		}
		else{
			return Tools::encrypt($class);
		}
}



public function __destroy(){
	foreach($this as $key => $var){
		unset($this->$key);
	}
	unset($this);
}

}

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.