Posts Tagged ‘what works’

Memcache Feature-Bug Gotchas

Thursday, July 17th, 2008

Recently I’ve been doing a lot of work with memcached using PHP and have been bitten a few times by different things with how things worked. I’m calling those items out here so anyone getting started with Memcache can learn from my mistakes. Memcached is an amazingly powerful caching layer with lots and lots of online documentation. It’s easy to get running on Linux and hooking PHP into it - I’ll save yet another post about how to do it since there are so many excellent resources already. The hard part is determining where you’ll implement it and in what way. For this post, I’ll leave the implementation strategy aside and walk you through a couple of examples of where I’ve been bit. I’ve created a layer to further abstract the memcache() object in PHP so I can ignore dealing with the add() vs. replace() vs. set() switches and allowing me to have one stop shopping for all of my configuration settings. The source for that basic class is included at the bottom of this post, feel free to use/distribute as you see fit.

One last item before we delve into the examples. Memcached and memcache are not quite the same thing. When I reference Memcached - I’m actually referring to the server instance of Memcache which you are running on the server, which is accessible using a variety of methods, on a variety of platforms including but not limited to PHP. When I use memcache in this post, I’m referring to the API hooks that have been created for PHP to interact with your Memcached server instance. Some (or possibly all) of these items ONLY APPLY TO PHP and shouldn’t be construed as feature-bugs with the Memcached server itself.

Compression and Object Sizes

It took me a while to track down this bug - but I finally read up on memcache a bit more and learned that memcache behaves oddly with small chunks of information if compression is turned on. I’m pretty sure this is memcache not memcached that’s causing the issue because the compression layer happens in PHP. The output for the following code is The value is not the same. However, if $compression is set to false, it will work as expected. Integers and character strings seem to be okay with compression on - as do complex objects. The setCompressThreshold method allows adjustment of this size but I’ve gotten in the habit of not caching simple values like true and false - instead opting to cache objects, classes, arrays and alternately JSON.

// create the cache
$cache = new Memcache();
$cache->addServer("localhost","11211");
$compression = true;
 
// create the value in the cache
$x = true;
$cache->add("x", $x, $compression, 10);
 
// access the value
$y = $cache->get("x", $compression);
 
// check what happened
if($x == $y){
   print "The value is the same";
} else {
   print "The value is not the same";
}

Caching of Class Objects

When caching complex objects like classes, memcache serializes the entire object and then caches it was as it was instantiated. So be warned if your class definition changes, you’ll need to flush your cache entirely of those objects or you might find it behaves a little differently than your expecting. Let’s say you have a class with a few properties that update multiple properties when certain methods are called and you wish to change one of those properties slightly. Any objects that are in the cache already will continue to work with the old values until they are flushed from the cache. It’s not sufficient to read it out and put it back in - the object really is your OLD class definition.

class Foo{
   protected $property = array();
   public function __construct($arr){
      if(count($arr) > 0){
         $this->properties = $arr;
      }
   }
   public function __get($key){
      return $this->property[$key];
   }
   public function __set($key, $value){
      $this->property[$key] = $value;
   }
}

So now you can create Foo objects all day and stuff all sorts of information into them and cache them. You can also get them back out willy nilly later (I’ll use my cache class to save time on the code below).

$foo1 = new Foo(array("apples"=>11,"orange"=>20));
$cache->set("foo1",$foo1, 60);
$foo2 = $cache->get("foo1");
echo $foo2->apples; // should be 11

So we see that all works but, what if we change the way the class works? For example adding a layer of math to calculate a tax or something along those lines.

class Foo{
   protected $property = array();
   public function __construct($arr){
      if(count($arr) > 0){
         $this->properties = $arr;
      }
   }
   public function __get($key){
      return round($this->property[$key] * .9); // calculate storage/depreciation loss
   }
   public function __set($key, $value){
      $this->property[$key] = $value;
      $this->property['num_items'] = count($this->properties) - 1;
   }
}

Our existing cached object doesn’t behave as expected. One of two things seems to happen, and I haven’t fully flushed it out what happens when. First, the object just comes back as it was initially instantiated or second, it silently dies without returning an error. This might be a good reason to create a version value for your cached objects so you can switch on the version to determine if the cached value is valid.

// let's access our existing cache object from before again...
$foo2 = $cache->get("foo1");
echo $foo2->apples; // we might hope for 10 but...

Database Results

Caching of resources doesn’t work. The data being cached needs to be able to be serialized by memcache so it can be inserted into memcached. Database handles are much like your memcached connection - they’re a socket you talk to and unfortunately, so are MySQL results. There are good reasons for this so don’t gripe about it. You’ll need to write a simple wrapper that does all of the result parsing for you prior to caching. Then you can easily create a cacheable MySQL object that can be inserted into memcached. It only takes a few minutes to do this and I may even post later describing the wrappers I’m now using to do just this. Until then - know that you can quickly create an array of your data using the following code and cache that result instead.

// create a cache object (using class from below)
$cache = new Cache();
 
// create an array to populate the data with
$data_array = array();
 
// run the query 
$mysqli_result = $mysqli->query("select * from table where condition=true");
 
// stuff all the data into the array
while($row = $mysqli_result->fetch_assoc()){
   $data_array[] = $row;
}
 
// cache the array
$cache->set("query_data",$data_array,90);

Cache Time to Live

Nothing too big here, but if you provide 0 (zero) or false for a time to live/expiration value, the item never expires, it just gets pushed out if needed later. This all happens on a LRU basis and is well documented.

Protect your Namespaces

This may seem trivial, but I’ve been bit here too. Often it’s sufficient to use one server for multiple tasks. Since Memcached is easy to run in one large pool and share it among multiple resources (much like you would with MySQL) it’s easy to share across multiple applications. There are some nice economies of scale this will afford you. But consider the following bug you could create for yourself in your logic.

Application 1 accessing it’s DB table.

 
// Application 1 fetching content about a user
$memcache = new Cache();
$query = "select * from users where userid = 12";
$result = $memcache->get(hash(md5,$query));
 
// The data wasn't in cache, so we run the query below and store the data
if(!$result){
     $result = $mysql->query($query);
     $memcache->set(hash(md5,$query), $result, 600);
}

Application 2 accessing it’s DB table.

// Application 2 fetching content about a user
 
$memcache = new Cache();
$query = "select * from users where userid = 12";
$result = $memcache->get(hash(md5,$query));
 
// the value existed in cache - so it skips the query and uses the cached value
if(!$result){
     $result = $mysql->query($query);
     $memcache->set(hash(md5,$query), $result, 600);
}

Application 2 and Application 1 are using the EXACT same key to reference their data. Unless this is intentional (because they share a common database) it can be a real pain to debug. The easiest way to correct this is to create a namespace for the cache layer and append it to any keys you may use. The example class provided below does just that with minimal fuss. The code above would be changed to reflect the correct namespace for each application and they could co-exist using the memcached server together.

// in app 1 - use that namespace
$cache = new Cache("app1");
 
// in app 2 - use that namespace
$cache = new Cache("app2");

Memcache Abstraction Class

This is the abstraction class I use to handle all memcache interaction. It’s little more than a thin veneer over the existing PHP object. You can see where it’s easy to expand this basic cache layer within the constructor and you can tune for your data, servers and other bits relevant to your implementation as needed.

class Cache{
 
   protected $cache = false;
   protected $namespace = "";
 
   public function __construct($namespace = ""){
      $this->cache = new Memcache();
      $this->cache->addServer("localhost","11211");
      $this->cache->setCompressThreshold(127,0.2);
      $this->namespace = $namespace;
   }
 
   public function __destruct(){
      $this->cache->close();
   }
 
   public function set($key, $value, $ttl = 600){
      $this->cache->set($key . $this->namespace, $value, true, $ttl);
   }
 
   public function get($key){
      return $this->cache->get($key . $this->namespace, true);
   }
 
}

AT&T LaptopConnect First Impression

Thursday, June 5th, 2008

AT&T Logo Despite my initial reaction to the contract, I decided to bite the bullet and purchase a laptop connect card from AT&T. The modem arrived early this morning via DHL express thanks to the complementary 2 day shipping that came with this modem. I opted for the Option GT Ultra Express 3G device which of course comes with limited Apple OS X support. I read the reviews on AT&T’s site about how the card stuck out 2 inches from the side of the computer. I found it to be slightly less, but it’s flush with the top surface of the 15″ MacBook Pro, so I was happy. With the antenna all the way out it extends just over 2 1/2″ but your milage may vary for the most accurate placement of the antenna. There’s also a port for an external antenna should you happen to have one. The other negative I had read about the modem was the blinking light was so bright they needed to put tape over it. While it is slightly distracting, it’s hardly blinding and I find it reassuring to know I’m connected - again YMMV.

LaptopConnect PackagingFor folks using a Mac, you’ll need to download the correct version of your software from Option. It’s a small file (1.1Mb) and downloads quickly - but don’t forget to do it before you head off into the land of non-access. You’ll get little help from the paper that comes in the box with the modem. Download the installation manual from Option as well. It’s not linked from the 10.4.11 and 10.5.x download page. Apple has the device listed in it’s configuration files so I’ll be spending some time looking for connection scripts to see if I can bypass the GlobeTrotter Connect software all together.

LaptopConnect Card Installed I was unsatisfied with the SIM card insertion - there’s nothing but friction holding it in. I have a feeling over time it will fall out. The other connection that felt weak is the actual slot in the Mac. I’m not sure if this is a issue with the card or the laptop’s ExpressCard/34 slot. The old style PC Cards seemed to have a more solid connection and the handy eject button that popped out let you know if it was in all the way or not.

I found it frustrating to have to create a new Network location instead of having it inserted in with my Airport/Ethernet etc settings. This also means I’m going to have to create all of my Parallels configuration again so I can use the network with Windows and WiFi and Ethernet so I can share the connection on vacation. I followed the instructions and set the APN value to isp.cingular as instructed in the 3G/EDGE/GPRS tab in settings. It never did connect although it may have been my lack of patience with the device’s initial network registration process. After removing that value it connected just fine - so it may be ignored anyway.

GlobeTrotter Connect Screenshot

From my home office I had pretty dismal download numbers for the portion of the test that was able to complete. I tested via Speedtest using their recommended connection in Kansas City, MO. With the default configuration set to prefer 3G but use what was available. I was able to achieve a peak of 17kbps and then it slowed to 6kbps and then stopped 17% of the way into the test. The ping test yeilded 349ms which I feel was reasonable. I’d read that setting the device to only use 3G and not switch to EDGE as needed can improve this performance. I reconnected and sure enough I was able to hit 700kbps but averaged 650kbps download before the test failed at 76% completed. I ran one last test to my closest physical location, the Twin Cities and hit 900kbps before the test failed at 56% I’m unclear why the tests continue to fail before completion - but that’s for another day.

Twin Cities Speedtest Screenshot

Option GT Ultra Express My last test was to upload a few photos (in fact the ones I took for this post) just to see how that all performed. My expectations were pretty low given the issues with the download test. I was able to upload all of these photos (~204Kb) in about 10 seconds which I actually found reasonable. The larger screenshot above (~188Kb) uploaded in about 4 seconds which was even faster. My conclusion is that this certainly won’t be replacing my broadband cable modem for daily internet access (not to mention there’s a data cap on the service) but it’s a viable alternative to going without and for those who travel sufficiently, it’s a cheaper alternative to pay as you go WiFi in airports and hotels.

90 Twitter Related Tools and Applications

Tuesday, May 27th, 2008

Curious how big the extended twitter universe (twitterverse) is, I decided I’d do my own investigation and provide results I found as a list of tools. Basically, it’s BIG. Google returns ~69.3 million hits for “Twitter.” Below is what I found relevant in the cream. You’ll notice I skipped Mac/PC clients. There are lots of great clients that people use for platform specific updates (perhaps a future blog post worth).

Websites:

Spotting Trends (Techcrunch tweeted an even better one than these but I can’t for the life of me find it):

Tracking, Leaderboard, Ranking and Visualization:

Voice Tools:

iPhone Specific:

Web Browser Plugins (a very short list):

Social Networking Sites:

Mobile Applications:

Desktop Apps (Adobe AIR):

Search:

Photos & Images:

Mashups/Geolocation:

Blogging Tools (a very short list):

News & Politics:

Survey Tools:

Special thanks to franticindustries, Mashable and all of the assorted the commenters for the initial inspiration for this list. Also see Twitter Fan Wiki for a comprehensive list of apps. There are some big ones missing I’m sure, so YMMV with that list as with this one over time. All links/sites were active as of May 27, 2008.

Learnings from a Terms of Service Violation

Tuesday, April 22nd, 2008

MySpace Developer Site Last Friday afternoon I wrote a MySpace application called Visitor Track. This is not a wholly original idea - nor was I the first to try it on MySpace. As of this writing there is even another application still listed in the application directory.

Before I explain how I went about going from 0 to 12,000+ users in a matter of 48 hours, I want to mention a few things.

1. It’s critical to understand that the MySpace audience clearly demonstrated a desire for more information about who’s looking (or not looking) at them.
2. Having a fantastic marketing plan will not make an application succeed no matter how cool YOU think it is, it needs to find an audience.
3. There is AMAZING growth potential in the MySpace application domain, even without notifications, invites and the viral components developers desire and users loath.

What I did was leverage the users profile well, provided a clean canvas with only what the user was expecting and was straightforward and honest in the application description. While I certainly could have leveraged advertising to promote the application, I chose not to so I could watch the growth of the application as it progressed organically.

The following chart is from Zynganomics who’ve been tracking MySpace applications since the initial launch of the platform.

Installed users over time provided by Zynganomics

As you can see, prior to the suspension of the application, growth was extremely strong.

Leverage the profile:

This is the single most important thing developers on the platform can do right now. With a general lack of viral push channels, developers need to hope that users find them. MySpace has recently started adding friend feed notifications about application installs and that has helped fuel growth through awareness within social circles.

The Profile for Visitor Track was a plain white box with two lines of text. I made the box as small as I could so it didn’t clutter the users profile with useless information. You can see what it looked like here:

Visitor Track - Profile Screenshot

The language, placement, size, color - everything - about the profile should be considered over and over and over and over again.

Name of the application:

The name of the application is very important. The largest viral channel available to applications today is the Friend Subscriptions. Basically a copy of the Facebook Newsfeed feature, this is the one place that the application will be seen by users you won’t otherwise touch.

MySpace Friend Subscription

Graphic design is over-rated:

My application about page had a poorly created icon and just a few lines of text to describe the application. I spent no time creating a fancy graphic interface - no time altering the colors of the page or install buttons with CSS and kept everything about as plain as it could be.

Visitor Track Application About Profile Page

Compare that to the highly designed canvas pages of larger applications from widget giants like Slide and Rock You below:

Slide and Rock You Application About Screenshots

Note: that the arrows facing the install buttons are animated in both cases and that neither app has more installs than Visit Tracker did.

Speed is everything:

If you aren’t tied to OAuth authentication and tight OpenSocial integration use an IFRAME - it’s less secure for you as a developer, but you ultimately control the communication between your application and your users. You’ll rely on REST requests to gather information about your users which means you’ll leverage the backend hardware more. However, what you lose in signed ajax requests and opensocial.postTo(), you make up for in speed and reliability. I’ve observed continual performance bottlenecks accessing AJAX content during peak times. While it’s reasonable to assume that this will continue to become more stable, now is the time to begin capturing audience before it’s too late.

Deliver:

Because it’s so easy to get started as an app and because the market of available users is so large, even knockoff applications can be quiet successful in terms of capturing users and market share. Consider the number of applications attempting to build on the success that applications experienced on Facebook like Honesty Box (of which I am a developer) on MySpace today (there are no less than 5 copycat applications).

It’s critical to deliver on what you told the users you would do! Below is a screenshot of the canvas (I omitted the right hand column which was advertising - a naive attempt to make money in this endeavor).

Visitor Track - Canvas Screenshot

As you can see I kept it really simple. I leveraged the amazing Google Charts API for the graphs and the rest is just text. There’s gold in them hills, and a diligent miner with the appropriate tools will find it. Even this relatively little application had nearly 20K page views, which monetized effectively could yield ~$120/month or more.

I want to apologize to any MySpace users and employees who might have been offended by my application. I sincerely hope you’ll forgive my transgression against the TOS and that we can make beautiful applications together in the future (that don’t violate the TOS).

Promoting Businesses on Facebook (and other social networks)

Wednesday, March 5th, 2008

Facebook Logo™ Yesterday I posted about how bleak the social networking landscape was becoming on Facebook and by extension, other social networks as well. Today I want to explore what a traditional media and existing business can do to promote themselves on Facebook without assuming that a widget is the panacea to save their business. This is another excerpt from a proposal I developed and felt was worth sharing with the community at large.

Gone are the days of instant success large scale applications. Users have a plethora of options when selecting their applications. For example, Twitter has their own application - but there are more than 20 others that seek to compete against it, each leveraging the utility of Twitter in it’s own way. Success in this overly saturated market will come from the niche audiences and remixing successful sites that are not already on Facebook.

National Wildlife Federation Facebook Page

Businesses need to leverage the “page” feature more extensively on Facebook to build up their brand as well as a buzz. The “fans” of this page have indirectly offered you their email address through Facebook. While you can’t export them into your current email marketing campaign system, you can still target these folks directly using updates. You can promote products, actions and even feature partnerships. Very few companies are effectively leveraging this right now. (Red) and Presidential Candidate Barack Obama being two I’ve seen, although there are likely others.

Companies that have existing media outlets such as newsletters, brochures and websites can leverage their existing media to build the fan base within Facebook. Creating an online persona for their product or service is the first step. When users take action within the Facebook “page” they’re actions are recorded and eligible for promotion on their friends and larger network news feeds. This viral component is critical for success because their friends likely have similar interests. This indirect endorsement of your product reaches a like minded audience that is between 1 and 5,000 people each time one person becomes a fan, rates your application and so on. The implications are huge; it gets your brand in front of many many more people. MySpace is slowly copying this feature, under the name Friend Updates, from Facebook. This is a powerful tool that companies need to leverage effectively in their social networking strategy. How access to this feed of information is gated by MySpace will be interesting to watch as their platform goes live.

Blackberry Pearl Page Metrics from Facebook

To show an example of this, I recently created a Blackberry Pearl “page”. With out advertisement, corporate sponsorship or endorsement by the parent company - without having any real content - it continues to attract “fans” whom I can now send messages to as I see fit! Not unlike traditional media, it’s important to respect your users, but you can see the power here. If RIM were to provide incentives on this page, they could grow this into a powerful advocating tool. Incidentally, if someone from RIM would like to take over this page, please just let me know. I’ve also noticed someone else followed suit and has created one for the Curve.

Depending on your core business, there may be an existing Facebook application that you can leverage to build your brand more completely. For example, if your business involves publishing of content, a RSS feed on your Facebook page is a no-brainer for driving traffic back to your website. In the event that building out your own widget is something you’ll likely follow through on, you’ll be able to leverage the fan base once you have an application. Spreading the word through direct communication with each and every fan of your application.

Last, but no least (truly most important) social networks are about making connections. If pursuing a widget is the correct strategy for your business, be warned that it must somehow allow self expression while allowing the user to feel they are connected and part of some larger community. You might be better served purchasing an existing widget that has some traction within the network, then building one from the ground up.

Social Network Application Space Looking Bleak?

Tuesday, March 4th, 2008

Graphing Social Patterns West This week O’Reilly Media is sponsoring the Graphing Social Patterns West (GSP West) conference in sunny San Diego, CA. Many leading application developers and minds are present discussing the future of social media as we know it. What follows is an excerpt from a proposal I developed for a potential client recently. I fell it brings value to the social networking community. It serves as an introductory piece in a series of posts for traditional media who have not yet grasped social networking for lead generation.

Leveraging the users social graph has grown increasingly more difficult in the last few months as providers such as Facebook lock down their social graph. Days of early growth fueled by numerous friend invites, notifications, newsfeed and messaging components has been replaced with systems of quotas and restrictions on use. Additionally, users are now more sensitive to the behavior of applications and quickly discard the apps they deem annoying or spammy. Not yet launched platforms from MySpace and Orkut have yet to implement these types of restrictions, but they have already received a bit of blogger attention for a platform thatʼs still in development. Given a little more time, more and more folks will be complaining and something will be done.

What this means for a content provider, seeking new audience through social media, is that growth must be fueled by highly engaging content and/or functionality. That’s right, just like traditional media - you can’t provide lip service. Applications now destined for failure include vanilla RSS feeds of site content, newsletter signups, subscription ploys and 1 time survey style quizzes that put a warm fuzzy icon on your profile. The limited engagement of one to many fails. Instead, engagement of new audience must include something for the user that makes them feel good about themselves and allows them to express themselves digitally, with their friends, in a way that no other application is already doing.

Free Gifts Users of social networking applications have a very low attention span and applications are competing in a more and more hostile environment each day. Applications are having to diversify their offering beyond the core application to retain users and increase traffic. Applications like Free Gifts have begun virtual economies leveraging game play, ultimately designed to increase time spent within the application, and rewarding users with special virtual gift incentives.

Revenue models that seem to have some success include pay per click ads and sponsored partnerships. Realistically, very few apps are able to sustain the technology costs, let alone development costs, with Google ads alone. There’s still a huge untapped market here for those who are willing to brave it. A few specific advertising networks have grown up to fill this space and offer CPM rates roughly double Googleʼs, but they are fueled primarily by other applications and not external advertisers seeking new audience. Likely due to poor performance of advertisements on social networks at large. Applications for existing media should be considered marketing expenses and not thought of as revenue streams (at least not initially).

Competition between friends (or even beyond immediate contacts to the network in Facebook or entire user-base elsewhere) definitely does very well with the Facebook / MySpace audiences. Applications such as Likeness show this daily. Additionally, leveraging user established in a recommendation style format is also highly effective. If your considering this type of application, be aware that there is a lot of competition in this area and micro-niche audiences on Facebook or MySpace are still too small to be sustaining.

Rewards based behavior works - however - there is a very short life span for actions that force virility based on user actions - that’s called SPAM. Meeting new people based on shared interests within a network will really enhance a users adoption and ultimately interaction with the application rewarding this behavior will enhance a products utility. Rewarding the users for daily and weekly interaction with desirable rewards will push the application much further along.

So the ultimate question then, how to promote a business on Facebook and other social networks? I’ll follow up with a post on that in the near future.

© 1998-2008 AF-Design, All rights reserved.