FacebookPerformanceCachingLucasNealanDCPHPConferenceNovember7,2007,16:00–17:00FacebookSocialPlatformSharingandcommunicatingefficiently6thmosttraffickedsiteintheU.S.**ComScore2007FacebookStatsOver52millionactiveusers~50pagesperuserdaily250,000newusersdailyOver7,000platformapplicationsFacebookArchitecture!#$%$&'()*+,-**./012,34%#%+!5678ComplexityConnectingtoallDatabaseisimpossibleLargecodebaseScalingaffectsresourcesinmanyways‣Memoryconsumption‣SocketconnectionlimitsCacheretrievalis~10%cpu-userofmostpagesWhataretheBenefitsofCaching?CachingLayers$GLOBALSAPCMemcachedDatabaseBrowserCacheThirdPartyCDNGlobalsCachefunctioncache_get($id,$key,$apc=false){if(isset($GLOBALS['CACHE'][$key:$id])){$cache=$GLOBALS['CACHE'][$key:$id]));$hit=1;}elseif($apc&&(($cache=apc_fetch($key:$id))!==false){$hit=1;}else{...//fetchfrommemcachedif($apc)apc_store($key:$id,$cache);}if($hit)$GLOBALS['CACHE'][$key:$id]=$cache;return$hit?$cache:NULL;}GlobalsCacheAvoidsunnecessaryAPCandMemcachedrequestsAutomaticviaabstractionButstillhasfunctioncallcostoverheadforeach($idsas$id){if(isset($GLOBALS['CACHE'][profile:$id)){$profile=$GLOBALS['CACHE'][profile:$id];}else{$profile=cache_get($id,'profile');}}APCOpcodecaching‣Hundredsofincludedlibraries‣ThousandsoffunctionsVariablecaching‣HundredsofMB’sofdataAPCUserCacheNon-userspecificdata‣Networkinformation‣Databaseinformation‣Useragentstrings‣Hotapplicationdata‣SitevariablesFriendsNormal4050msAPC135msapc.stat=0128msAPCOpcodePriming$path='/path/to/source';$exclude=$path.'/='.*\\.php';$files=split('',exec(find-L$path-regex'$expr'|grep-v'$exclude'|xargs));//primephpfilesforeach($filesas$file){apc_compile_file($file);}APC+SVNClientCacheBustingfunctionget_static_suffix($file){global$ROOT;if($version=cache_get($file,‘sv’,1)===null){$version=trim(shell_exec(“svninfo$ROOT/$file|grep‘ChangedRev’|cut-c19-”));apc_store(“sv:$file”,$version);}return'?'.$version;}APC+UseragentStringsUseragentstringparsingisinefficientinPHPCacheparseduseragentsinAPCforthefirst10minutesHitrateofover50%Pearimplementationavailablesoon:‣PEAR::Net_Useragent_Detect_APCSiteVariablesEnable/DisablesitefeaturesacrossallserversConfigurememcachedclusterIP’sConfigureproductfeaturesVersionmemcachedkeysforinvalidationSiteVariables!#$%&'&()$*+,-+)$-./.$'-+,!#-./01$23-./01$23-./.$'-+,-./.$'-+,4#5$6'5$'7686-.9&98$7#:#9+;$6-87-8-.6;$7686-.(&9167686=2!?!#$.&'@A=$59&98$;*+;$B-8!$'.$'-.(&9167686MemcachedDistributedobjectcacheFacebookcurrentlyutilizes400memcachedhostsWith5TBinmemorycacheFacebookcontributions:‣UDPSupport‣PerformanceEnhancementsManychoicesinopensourceclientsWhattocache?UserSpecificData‣Longprofile‣Shortprofile‣Friends‣ApplicationsKeyversioning‣sp:6:10030226CacheRetreivalCreateWrapperfunctions:‣cache_get($id,key,miss,$apc,$timeout);‣cache_get_multi($ids,key,miss,$apc);Cachekeycallbackfunction:functionprofile_key($id){global$VERSION_SP;//primedsitevariablereturn“sp:$version:$id”;}CacheMultigetSortkeysintobucketsofserversForeachserver‣obtainconnection‣sendrequestsForeachserver‣readresponses‣deserializenon-scalartypesforeach($keysas$key=$kdata){$host=get_host($key);//hash$keys_hosts[$host][$key]=$kdata;}functionget_host($key){global$servers;$prefix=$key[0].$key[1].$key[2];$prefix=isset($servers[$prefix)?$prefix:‘wildcard’;$hash=crc32($key);$host=$servers[$hash%count($servers[$prefix]);}CacheMultigetSortkeysintobucketsofserversForeachserver‣obtainconnection‣sendrequestsForeachserver‣readresponses‣deserializenon-scalartypesif(isset($cache_sock[$host])){return$cache_sock[$host];}list($ip,$port)=explode(‘:’,$host);while($try5&&!$sock){$sock=pfsockopen($ip,$port...);$try++;}stream_set_write_buffer($sock,0);$cmd=“get$keys\r\n”;fwrite($sock,$cmd);ProfileMultigetsProfileinfoProfileinstalledplatformapplicationsViewerinstalledapplicationsPlatformapplicationdataListoffriendsPrivacydataCacheDispatchingcache_get_multi($ids,key,miss,$apc,$pending=false,&$pending_arr);cache_dispatch();Combinerequestsfordatafromthesamememcacheserver‣Upto10%performanceimprovementExecutecodewhilethekernelbuffersthememcacheresponseProfileMultigets?phpinclude_once(...);parse_arguments();check_permissions();check_friends();check_friend_status();•get_profile();render_basic_information();get_friend_details();render_minifeed();render_wall();•get_photos();count_photos();•get_applications();render_menu_actions();•get_friends();render_friends();•get_networks();render_networks();render_applications();?phpinclude_once(...);•get_profile(true);•get_photos(true);•get_applications(true)•get_friends(true)•get_networks(true)cache_dispatch();parse_arguments();check_permissions();check_friends();check_friend_status();•get_profile();render_basic_information();get_friend_details();render_minifeed();render_wall();get_photos();count_photos();get_applications();render_menu_actions();get_friends();render_friends();get_networks();render_networks();render_applications();LetsmakeitevenfasterMemcachedPHPextension‣ReducedPHPfunctioncallingoverhead‣SocketblockinginCinsteadofuserspace