diff --git a/core/core.services.yml b/core/core.services.yml
index 6f8cce6..1bff04e 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -58,6 +58,13 @@ services:
     factory_method: get
     factory_service: cache_factory
     arguments: [path]
+  cache.url_generator:
+    class: Drupal\Core\Cache\CacheBackendInterface
+    tags:
+      - { name: cache.bin }
+    factory_method: get
+    factory_service: cache_factory
+    arguments: [url_generator]
   config.cachedstorage.storage:
     class: Drupal\Core\Config\FileStorage
     factory_class: Drupal\Core\Config\FileStorageFactory
@@ -232,9 +239,12 @@ services:
     arguments: ['@router.route_provider']
     calls:
       - [setFinalMatcher, ['@router.matcher.final_matcher']]
-  url_generator:
+  url_generator.uncached:
     class: Drupal\Core\Routing\UrlGenerator
     arguments: ['@router.route_provider', '@path_processor_manager', '@config.factory', '@settings']
+  url_generator:
+    class: Drupal\Core\Routing\CachedUrlGenerator
+    arguments: ['@url_generator.uncached', '@cache.url_generator']
     calls:
       - [setRequest, ['@?request']]
     tags:
diff --git a/core/lib/Drupal/Core/EventSubscriber/PathSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/PathSubscriber.php
index a5dc955..ad5bdb5 100644
--- a/core/lib/Drupal/Core/EventSubscriber/PathSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/PathSubscriber.php
@@ -9,7 +9,6 @@
 
 use Drupal\Core\CacheDecorator\AliasManagerCacheDecorator;
 use Drupal\Core\PathProcessor\InboundPathProcessorInterface;
-use Drupal\Core\Routing\PathBasedGeneratorInterface;
 use Symfony\Component\HttpKernel\HttpKernelInterface;
 use Symfony\Component\HttpKernel\KernelEvents;
 use Symfony\Component\HttpKernel\Event\GetResponseEvent;
diff --git a/core/lib/Drupal/Core/Routing/CachedUrlGenerator.php b/core/lib/Drupal/Core/Routing/CachedUrlGenerator.php
new file mode 100644
index 0000000..83d5a49
--- /dev/null
+++ b/core/lib/Drupal/Core/Routing/CachedUrlGenerator.php
@@ -0,0 +1,198 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Routing\CachedUrlGenerator.
+ */
+
+namespace Drupal\Core\Routing;
+
+use Drupal\Core\Cache\CacheBackendInterface;
+use Drupal\Core\DestructableInterface;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\Routing\RequestContext;
+
+/**
+ * Class used by the PathSubscriber to get the system path and cache path lookups.
+ */
+class CachedUrlGenerator implements DestructableInterface, PathBasedGeneratorInterface {
+
+  /**
+   * The wrapped url generator
+   *
+   * @var \Drupal\Core\Routing\PathBasedGeneratorInterface
+   */
+  protected $urlGenerator;
+
+  /**
+   * The cache backend.
+   *
+   * @var \Drupal\Core\Cache\CacheBackendInterface
+   */
+  protected $cache;
+
+  /**
+   * An array of cached URLs keyed by route name or path.
+   *
+   * @var array
+   */
+  protected $cachedUrls = array();
+
+  /**
+   * Whether the cache needs to be written.
+   *
+   * @var boolean
+   */
+  protected $cacheNeedsWriting = FALSE;
+
+  /**
+   * The cache key to use when caching generated URLs.
+   *
+   * @var string
+   */
+  protected $cacheKey;
+
+  /**
+   * Cache prefix for route names.
+   */
+  const ROUTE_CACHE_PREFIX = 'route::';
+
+  /**
+   * Cache prefix for paths.
+   */
+  const PATH_CACHE_PREFIX = 'path::';
+
+  /**
+   * Constructs a \Drupal\Core\CacheDecorator\AliasManagerCacheDecorator.
+   *
+   * @param \Drupal\Core\Routing\PathBasedGeneratorInterface
+   *   The wrapped url generator
+   * @param \Drupal\Core\Cache\CacheBackendInterface
+   *   The cache backend.
+   */
+  public function __construct(PathBasedGeneratorInterface $url_generator, CacheBackendInterface $cache) {
+    $this->urlGenerator = $url_generator;
+    $this->cache = $cache;
+  }
+
+  /**
+   * Writes the cache of generated URLs.
+   */
+  protected function writeCache() {
+    if ($this->cacheNeedsWriting && !empty($this->cachedUrls) && !empty($this->cacheKey)) {
+      // Set the URL cache to expire in 24 hours.
+      $expire = REQUEST_TIME + (60 * 60 * 24);
+      $this->cache->set($this->cacheKey, $this->cachedUrls, $expire);
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function generate($name, $parameters = array(), $referenceType = self::ABSOLUTE_PATH) {
+    // We can only cache the url if $name is a string, not the actual route
+    // object.
+    $parameter_hash = hash('sha256', serialize($parameters)) . (string) $referenceType;
+    if (is_scalar($name) && isset($this->cachedUrls[self::ROUTE_CACHE_PREFIX . $name . $parameter_hash])) {
+      return $this->cachedUrls[self::ROUTE_CACHE_PREFIX . $name . $parameter_hash];
+    }
+    $url = $this->urlGenerator->generate($name, $parameters, $referenceType);
+    if (is_scalar($name)) {
+      // Cache the url for this route.
+      $this->cachedUrls[self::ROUTE_CACHE_PREFIX . $name . $parameter_hash] = $url;
+      $this->cacheNeedsWriting = TRUE;
+    }
+    return $url;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function generateFromPath($path = NULL, $options = array()) {
+    $options_hash = hash('sha256', serialize($options));
+    if (isset($this->cachedUrls[self::PATH_CACHE_PREFIX . $path . $options_hash])) {
+      return $this->cachedUrls[self::PATH_CACHE_PREFIX . $path . $options_hash];
+    }
+    $url = $this->urlGenerator->generateFromPath($path, $options);
+    // Cache the url for this route.
+    $this->cachedUrls[self::PATH_CACHE_PREFIX . $path . $options_hash] = $url;
+    $this->cacheNeedsWriting = TRUE;
+    return $url;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setRequest(Request $request) {
+    $this->cacheKey = $request->attributes->get('system_path');
+    $cached = $this->cache->get($this->cacheKey);
+    if ($cached) {
+      $this->cachedUrls = $cached->data;
+    }
+    $this->urlGenerator->setRequest($request);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setBaseUrl($url) {
+    $this->urlGenerator->setBaseUrl($url);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setBasePath($path) {
+    $this->urlGenerator->setBasePath($path);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setScriptPath($path) {
+    $this->urlGenerator->setScriptPath($path);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function supports($name) {
+    return $this->urlGenerator->supports($name);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getRouteDebugMessage($name, array $parameters = array()) {
+    return $this->urlGenerator->getRouteDebugMessage($name, $parameters);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function destruct() {
+    $this->writeCache();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setContext(RequestContext $context) {
+    $this->urlGenerator->setContext($context);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getContext() {
+    return $this->urlGenerator->getContext();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getPathFromRoute($name, $parameters = array()) {
+    return $this->urlGenerator->getPathFromRoute($name, $parameters);
+  }
+
+}
diff --git a/core/lib/Drupal/Core/Routing/PathBasedGeneratorInterface.php b/core/lib/Drupal/Core/Routing/PathBasedGeneratorInterface.php
index 79ed373..e40fbdc 100644
--- a/core/lib/Drupal/Core/Routing/PathBasedGeneratorInterface.php
+++ b/core/lib/Drupal/Core/Routing/PathBasedGeneratorInterface.php
@@ -8,11 +8,12 @@
 namespace Drupal\Core\Routing;
 
 use Symfony\Component\HttpFoundation\Request;
+use Symfony\Cmf\Component\Routing\VersatileGeneratorInterface;
 
 /**
  * Defines an interface for generating a url from a path as opposed to a route.
  */
-interface PathBasedGeneratorInterface {
+interface PathBasedGeneratorInterface extends VersatileGeneratorInterface {
 
   /**
    * Generates an internal or external URL.
diff --git a/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkFormController.php b/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkFormController.php
index 8eb4458..8ac4bb7 100644
--- a/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkFormController.php
+++ b/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkFormController.php
@@ -12,7 +12,7 @@
 use Drupal\Core\Language\Language;
 use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Core\Path\AliasManagerInterface;
-use Drupal\Core\Routing\UrlGenerator;
+use Drupal\Core\Routing\PathBasedGeneratorInterface;
 use Drupal\menu_link\MenuLinkStorageControllerInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
@@ -38,19 +38,23 @@ class MenuLinkFormController extends EntityFormController implements EntityContr
   /**
    * The URL generator.
    *
-   * @var \Drupal\Core\Routing\UrlGenerator
+   * @var \Drupal\Core\Routing\PathBasedGeneratorInterface
    */
   protected $urlGenerator;
 
   /**
    * Constructs a new MenuLinkFormController object.
    *
-   * @param \Drupal\Core\Extension\ModuleHandlerInterface
+   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
    *   The module handler service.
+   * @param MenuLinkStorageControllerInterface $menu_link_storage_controller
+   *   The menu link storage controller
    * @param \Drupal\Core\Path\AliasManagerInterface $path_alias_manager
    *   The path alias manager.
+   * @param \Drupal\Core\Routing\PathBasedGeneratorInterface $url_generator
+   *   The url generator.
    */
-  public function __construct(ModuleHandlerInterface $module_handler, MenuLinkStorageControllerInterface $menu_link_storage_controller, AliasManagerInterface $path_alias_manager, UrlGenerator $url_generator) {
+  public function __construct(ModuleHandlerInterface $module_handler, MenuLinkStorageControllerInterface $menu_link_storage_controller, AliasManagerInterface $path_alias_manager, PathBasedGeneratorInterface $url_generator) {
     parent::__construct($module_handler);
     $this->menuLinkStorageController = $menu_link_storage_controller;
     $this->pathAliasManager = $path_alias_manager;
diff --git a/core/tests/Drupal/Tests/Core/Routing/CachedUrlGeneratorTest.php b/core/tests/Drupal/Tests/Core/Routing/CachedUrlGeneratorTest.php
new file mode 100644
index 0000000..0bd0a60
--- /dev/null
+++ b/core/tests/Drupal/Tests/Core/Routing/CachedUrlGeneratorTest.php
@@ -0,0 +1,124 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Tests\Core\Routing\CachedUrlGeneratorTest.
+ */
+
+namespace Drupal\Tests\Core\Routing;
+
+use Drupal\Core\Routing\CachedUrlGenerator;
+use Drupal\Tests\UnitTestCase;
+
+/**
+ * Tests the cache url generator.
+ */
+class CachedUrlGeneratorTest extends UnitTestCase {
+
+  /**
+   * The wrapped url generator.
+   *
+   * @var \Drupal\Core\Routing\PathBasedGeneratorInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $urlGenerator;
+
+  /**
+   * The cache backend.
+   *
+   * @var \Drupal\Core\Cache\CacheBackendInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $cache;
+
+  /**
+   * The actual tested cached url generator.
+   *
+   * @var \Drupal\Core\Routing\CachedUrlGenerator
+   */
+  protected $cachedUrlGenerator;
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Cached UrlGenerator',
+      'description' => 'Confirm that the cached UrlGenerator is functioning properly.',
+      'group' => 'Routing',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+
+    $this->urlGenerator = $this->getMock('Drupal\Core\Routing\PathBasedGeneratorInterface');
+    $this->cache = $this->getMock('Drupal\Core\Cache\CacheBackendInterface');
+
+    $this->cachedUrlGenerator = new CachedUrlGenerator($this->urlGenerator, $this->cache);
+  }
+
+  /**
+   * Tests the generate method.
+   *
+   * @see \Drupal\Core\Routing\CachedUrlGenerator::generate()
+   */
+  public function testGenerate() {
+    $this->urlGenerator->expects($this->once())
+      ->method('generate')
+      ->with('test_route')
+      ->will($this->returnValue('test-route-1'));
+    $this->assertEquals('test-route-1', $this->cachedUrlGenerator->generate('test_route'));
+    $this->assertEquals('test-route-1', $this->cachedUrlGenerator->generate('test_route'));
+  }
+
+  /**
+   * Tests the generate method with the same route name but different parameters.
+   *
+   * @see \Drupal\Core\Routing\CachedUrlGenerator::generate()
+   */
+  public function testGenerateWithDifferentParameters() {
+    $this->urlGenerator->expects($this->exactly(2))
+      ->method('generate')
+      ->will($this->returnValueMap(array(
+        array('test_route', array('key' => 'value1'), CachedUrlGenerator::ABSOLUTE_PATH, 'test-route-1/value1'),
+        array('test_route', array('key' => 'value2'), CachedUrlGenerator::ABSOLUTE_PATH, 'test-route-1/value2'),
+      )));
+    $this->assertEquals('test-route-1/value1', $this->cachedUrlGenerator->generate('test_route', array('key' => 'value1')));
+    $this->assertEquals('test-route-1/value1', $this->cachedUrlGenerator->generate('test_route', array('key' => 'value1')));
+    $this->assertEquals('test-route-1/value2', $this->cachedUrlGenerator->generate('test_route', array('key' => 'value2')));
+    $this->assertEquals('test-route-1/value2', $this->cachedUrlGenerator->generate('test_route', array('key' => 'value2')));
+  }
+
+  /**
+   * Tests the generateFromPath method.
+   *
+   * @see \Drupal\Core\Routing\CachedUrlGenerator::generateFromPath()
+   */
+  public function testGenerateFromPath() {
+    $this->urlGenerator->expects($this->once())
+      ->method('generateFromPath')
+      ->with('test-route-1')
+      ->will($this->returnValue('test-route-1'));
+    $this->assertEquals('test-route-1', $this->cachedUrlGenerator->generateFromPath('test-route-1'));
+    $this->assertEquals('test-route-1', $this->cachedUrlGenerator->generateFromPath('test-route-1'));
+  }
+
+  /**
+   * Tests the generate method with the same path but different options
+   *
+   * @see \Drupal\Core\Routing\CachedUrlGenerator::generateFromPath()
+   */
+  public function testGenerateFromPathWithDifferentParameters() {
+    $this->urlGenerator->expects($this->exactly(2))
+      ->method('generateFromPath')
+      ->will($this->returnValueMap(array(
+        array('test-route-1', array('absolute' => TRUE), 'http://localhost/test-route-1'),
+        array('test-route-1', array('absolute' => FALSE), 'test-route-1'),
+      )));
+    $this->assertEquals('http://localhost/test-route-1', $this->cachedUrlGenerator->generateFromPath('test-route-1', array('absolute' => TRUE)));
+    $this->assertEquals('http://localhost/test-route-1', $this->cachedUrlGenerator->generateFromPath('test-route-1', array('absolute' => TRUE)));
+    $this->assertEquals('test-route-1', $this->cachedUrlGenerator->generateFromPath('test-route-1', array('absolute' => FALSE)));
+    $this->assertEquals('test-route-1', $this->cachedUrlGenerator->generateFromPath('test-route-1', array('absolute' => FALSE)));
+  }
+
+}
+
diff --git a/core/tests/Drupal/Tests/Core/Routing/UrlGeneratorTest.php b/core/tests/Drupal/Tests/Core/Routing/UrlGeneratorTest.php
index d6006ad..72308f0 100644
--- a/core/tests/Drupal/Tests/Core/Routing/UrlGeneratorTest.php
+++ b/core/tests/Drupal/Tests/Core/Routing/UrlGeneratorTest.php
@@ -8,12 +8,8 @@
 namespace Drupal\Tests\Core\Routing;
 
 use Drupal\Component\Utility\Settings;
-use Drupal\Core\Config\ConfigFactory;
-use Drupal\Core\Config\NullStorage;
-use Drupal\Core\Config\Context\ConfigContextFactory;
 use Drupal\Core\PathProcessor\PathProcessorAlias;
 use Drupal\Core\PathProcessor\PathProcessorManager;
-use Symfony\Component\EventDispatcher\EventDispatcher;
 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\Routing\Route;
 use Symfony\Component\Routing\RouteCollection;
@@ -22,6 +18,7 @@
 use Drupal\Tests\UnitTestCase;
 
 use Drupal\Core\Routing\UrlGenerator;
+use Drupal\Core\Routing\CachedUrlGenerator;
 
 /**
  * Basic tests for the Route.
