Index: t3lib/class.t3lib_page.php
===================================================================
--- t3lib/class.t3lib_page.php	(revision 9186)
+++ t3lib/class.t3lib_page.php	(working copy)
@@ -1046,6 +1046,39 @@
 	}
 
 	/**
+	 * Returns the cached configuration for a menu item.
+	 *
+	 * Every menu item has a hash identifier. This identifier connects with a
+	 * configuration string stored in the table "cache_menu", which is found by
+	 * using an intermediate table "cache_menu_mm".
+	 *
+	 * @param string $hash Hash-string which was used to store the configuration
+	 * @return string Serialized configuration string for the menu item
+	 */
+	public static function getMenuHash($hash) {
+		$hashContent = null;
+
+		$databaseResource = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
+			'cache_menu.content',
+			'cache_menu,cache_menu_mm',
+			'
+				cache_menu.id = cache_menu_mm.uid_foreign
+				AND cache_menu_mm.hash=' . $GLOBALS['TYPO3_DB']->fullQuoteStr(
+					$hash,
+					'cache_menu_mm'
+				) . '
+			'
+		);
+
+		$row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($databaseResource);
+		if ($row) {
+			$hashContent = $row['content'];
+		}
+
+		return $hashContent;
+	}
+
+	/**
 	 * Stores a string value in the cache_hash cache identified by $hash.
 	 * Can be used from your frontend plugins if you like. You can call it
 	 * directly like t3lib_pageSelect::storeHash()
@@ -1080,6 +1113,60 @@
 	}
 
 	/**
+	 * Stores the configuration of a menu item in the "cache_menu" table using
+	 * an intermediate table "cache_menu_mm" which contains the hash identifier.
+	 *
+	 * First it tries to find an identical record in the "cache_menu" table. If
+	 * available, it only stores the relation to this record using the table
+	 * "cache_menu_mm"
+	 *
+	 * @param string $hash Hash-string which is used to store the configuration
+	 * @param string $data Serialized array with the menu item configuration
+	 * @param integer $linkToPage The page where this menu item links to.
+	 * @param integer $lifetime The lifetime for the cache entry in seconds
+	 * @return void
+	 */
+	public static function storeMenuHash($hash, $data, $linkToPage, $lifetime = 0) {
+			// Check if data already exists in cache_menu
+		$databaseResource = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
+			'id',
+			'cache_menu',
+			'content=' . $GLOBALS['TYPO3_DB']->fullQuoteStr($data, 'cache_menu')
+		);
+
+		if ($GLOBALS['TYPO3_DB']->sql_num_rows($databaseResource) > 0) {
+				// Data is already in cache_menu, so we get the id
+			$row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($databaseResource);
+			$cacheMenuId = $row['id'];
+		} else {
+				// Data is not in cache_menu, insert it and get the id
+			$GLOBALS['TYPO3_DB']->exec_INSERTquery(
+				'cache_menu',
+				array(
+					'content' => $data,
+					'tstamp' => $GLOBALS['EXEC_TIME']
+				)
+			);
+			$cacheMenuId = $GLOBALS['TYPO3_DB']->sql_insert_id();
+		}
+			// Delete old entry with same hash in cache_menu_mm
+		$GLOBALS['TYPO3_DB']->exec_DELETEquery(
+			'cache_menu_mm',
+			'hash=' . $GLOBALS['TYPO3_DB']->fullQuoteStr($hash, 'cache_menu_mm')
+		);
+			// Insert new entry with the uid_foreign in cache_menu_mm
+		$GLOBALS['TYPO3_DB']->exec_INSERTquery(
+			'cache_menu_mm',
+			array(
+				'hash' => $hash,
+				'uid_foreign' => $cacheMenuId,
+				'link_page' => $linkToPage,
+				'tstamp' => $GLOBALS['EXEC_TIME']
+			)
+		);
+	}
+
+	/**
 	 * Returns the "AND NOT deleted" clause for the tablename given IF $TCA configuration points to such a field.
 	 *
 	 * @param	string		Tablename
Index: t3lib/class.t3lib_tcemain.php
===================================================================
--- t3lib/class.t3lib_tcemain.php	(revision 9186)
+++ t3lib/class.t3lib_tcemain.php	(working copy)
@@ -3391,10 +3391,10 @@
 
 		if ($TCA[$table])	{
 
-				// In case the record to be moved turns out to be an offline version, 
+				// In case the record to be moved turns out to be an offline version,
 				// we have to find the live version and work on that one (this case
 				// happens for pages with "branch" versioning type)
-				// note: as "branch" versioning is deprecated since TYPO3 4.2, this 
+				// note: as "branch" versioning is deprecated since TYPO3 4.2, this
 				// functionality will be removed in TYPO3 4.7 (note by benni: a hook could replace this)
 			if ($lookForLiveVersion = t3lib_BEfunc::getLiveVersionOfRecord($table,$uid,'uid'))	{
 				$uid = $lookForLiveVersion['uid'];
@@ -6596,7 +6596,7 @@
 						} else {
 							$GLOBALS['TYPO3_DB']->exec_DELETEquery('cache_pages','page_id IN ('.implode(',',$GLOBALS['TYPO3_DB']->cleanIntArray($list_cache)).')');
 							$GLOBALS['TYPO3_DB']->exec_DELETEquery('cache_pagesection', 'page_id IN ('.implode(',',$GLOBALS['TYPO3_DB']->cleanIntArray($list_cache)).')');
-
+							$GLOBALS['TYPO3_DB']->exec_DELETEquery('cache_menu_mm', 'link_page IN ('.implode(',',$GLOBALS['TYPO3_DB']->cleanIntArray($list_cache)).')');
 						}
 					}
 				}
@@ -6685,6 +6685,8 @@
 						}
 						$this->internal_clearPageCache();
 						$GLOBALS['TYPO3_DB']->exec_TRUNCATEquery('cache_hash');
+						$GLOBALS['TYPO3_DB']->exec_TRUNCATEquery('cache_menu');
+						$GLOBALS['TYPO3_DB']->exec_TRUNCATEquery('cache_menu_mm');
 					}
 
 						// Clearing additional cache tables:
Index: t3lib/stddb/tables.sql
===================================================================
--- t3lib/stddb/tables.sql	(revision 9186)
+++ t3lib/stddb/tables.sql	(working copy)
@@ -132,7 +132,6 @@
   KEY hash (hash)
 ) ENGINE=InnoDB;
 
-
 #
 # Table structure for table 'cachingframework_cache_hash'
 #
@@ -174,6 +173,27 @@
 ) ENGINE=InnoDB;
 
 #
+# Table structure for table 'cache_menu'
+#
+CREATE TABLE cache_menu (
+  id int(11) unsigned NOT NULL auto_increment,
+  content mediumblob,
+  tstamp int(11) unsigned DEFAULT '0' NOT NULL,
+  PRIMARY KEY (id)
+) ENGINE=InnoDB;
+
+#
+# Table structure for table 'cache_menu_mm'
+#
+CREATE TABLE cache_menu_mm (
+  hash varchar(32) DEFAULT '' NOT NULL,
+  uid_foreign int(11) unsigned DEFAULT '0' NOT NULL,
+  link_page int(11) unsigned DEFAULT '0' NOT NULL,
+  tstamp int(11) unsigned DEFAULT '0' NOT NULL,
+  PRIMARY KEY (hash)
+) ENGINE=InnoDB;
+
+#
 # Table structure for table 'pages'
 #
 CREATE TABLE pages (
Index: typo3/sysext/cms/tslib/class.tslib_menu.php
===================================================================
--- typo3/sysext/cms/tslib/class.tslib_menu.php	(revision 9186)
+++ typo3/sysext/cms/tslib/class.tslib_menu.php	(working copy)
@@ -897,7 +897,6 @@
 				if (!is_array($this->parentMenuArr)) {$this->parentMenuArr=array();}
 				$this->menuArr = $this->userProcess('itemArrayProcFunc',$this->menuArr);
 			}
-			$this->hash = md5(serialize($this->menuArr).serialize($this->mconf).serialize($this->tmpl->rootLine).serialize($this->MP_array));
 
 				// Get the cache timeout:
 			if ($this->conf['cache_period']) {
@@ -906,14 +905,45 @@
 				$cacheTimeout = $GLOBALS['TSFE']->get_cache_timeout();
 			}
 
-			$serData = $this->sys_page->getHash($this->hash);
-			if (!$serData)	{
-				$this->generate();
-				$this->sys_page->storeHash($this->hash, serialize($this->result), 'MENUDATA', $cacheTimeout);
-			} else {
-				$this->result = unserialize($serData);
+			$menuData = array();
+			$generated = FALSE;
+
+				// Go through each menu item in menuArr
+			foreach($this->menuArr as $key => $menu) {
+					// Generate a hash for the menu item
+				$this->hash = md5(
+					serialize($menu) .
+					serialize($this->mconf) .
+					serialize($this->tmpl->rootLine) .
+					serialize($this->MP_array)
+				);
+					// Try to retrieve a stored instance of this menu item
+				$serializedMenuData = $this->sys_page->getMenuHash($this->hash);
+
+				if (!empty($serializedMenuData)) {
+						// The data was cached. Add this item to the result
+					$menuData[$key] = unserialize($serializedMenuData);
+				} else {
+						// The data was not cached
+					if (!$generated) {
+							// Generate complete result only once
+						$this->generate();
+						$generated = TRUE;
+					}
+						// Cache the menu item
+					$this->sys_page->storeMenuHash(
+						$this->hash,
+						serialize($this->result[$key]),
+						$menu['uid'],
+						$cacheTimeout
+					);
+						// Add the item to the result
+					$menuData[$key] = $this->result[$key];
+				}
 			}
 
+			$this->result = $menuData;
+
 				// End showAccessRestrictedPages
 			if ($this->mconf['showAccessRestrictedPages'])	{
 					// RESTORING where_groupAccess
