diff --git a/core/core.services.yml b/core/core.services.yml
index c4d1c47..e6e2d67 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -51,6 +51,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
@@ -212,9 +219,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..101200f
--- /dev/null
+++ b/core/lib/Drupal/Core/Routing/CachedURLGenerator.php
@@ -0,0 +1,178 @@
+<?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 {
+
+  /**
+   * @var \Drupal\Core\Path\AliasManagerInterface
+   */
+  protected $urlGenerator;
+
+  /**
+   * @var \Drupal\Core\Cache\CacheBackendInterface;
+   */
+  protected $cache;
+
+  /**
+   * @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;
+
+  const ROUTE_CACHE_PREFIX = 'route::';
+  const PATH_CACHE_PREFIX = 'path::';
+
+  /**
+   * Constructs a \Drupal\Core\CacheDecorator\AliasManagerCacheDecorator.
+   */
+  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.
+    if (is_scalar($name) && isset($this->cachedURLs[self::ROUTE_CACHE_PREFIX . $name])) {
+      return $this->cachedURLs[self::ROUTE_CACHE_PREFIX . $name];
+    }
+    $url = $this->urlGenerator->generate($name, $parameters, $referenceType);
+    if (is_scalar($name)) {
+      // Cache the url for this route.
+      $this->cachedURLs[self::ROUTE_CACHE_PREFIX . $name] = $url;
+      $this->cacheNeedsWriting = TRUE;
+    }
+    return $url;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function generateFromPath($path = NULL, $options = array()) {
+    if (isset($this->cachedURLs[self::PATH_CACHE_PREFIX . $path])) {
+      return $this->cachedURLs[self::PATH_CACHE_PREFIX . $path];
+    }
+    $url = $this->urlGenerator->generateFromPath($path, $options);
+    // Cache the url for this route.
+    $this->cachedURLs[self::PATH_CACHE_PREFIX . $path] = $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();
+  }
+
+  /**
+   * Passes all unknown calls to the decorated object.
+   */
+  public function __call($method, $args) {
+    return call_user_func_array(array($this->urlGenerator, $method), $args);
+  }
+}
diff --git a/core/lib/Drupal/Core/Routing/PathBasedGeneratorInterface.php b/core/lib/Drupal/Core/Routing/PathBasedGeneratorInterface.php
index 5c91e62..6db7189 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/tests/Drupal/Tests/Core/Routing/UrlGeneratorTest.php b/core/tests/Drupal/Tests/Core/Routing/UrlGeneratorTest.php
index 079213e..2700879 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.
@@ -124,6 +121,50 @@ public function testAbsoluteURLGeneration() {
   }
 
   /**
+   * Tests the Cached URL Generator.
+   */
+  public function testCachedUrlGenerator() {
+    $system_path = 'some_path';
+
+    // Mock a cache backend to pass to the CachedURLGenerator.
+    $cache = $this->getMock('Drupal\Core\Cache\CacheBackendInterface');
+    // Set an expectation that the get() method will be called on the
+    // mock cache backend and make it return a cache object with one
+    // cached URL.
+    $cache->expects($this->at(0))
+      ->method('get')
+      ->with($this->equalTo($system_path))
+      ->will($this->returnValue((object) array('data' => array(CachedUrlGenerator::PATH_CACHE_PREFIX . 'first_path' => 'foo'))));
+    // Set an expectation that the set() method will be called on the
+    // mock cache backend with an array containing two URLS.
+    $cache->expects($this->at(1))
+      ->method('set')
+      ->with($this->equalTo($system_path), $this->equalTo(array(CachedUrlGenerator::PATH_CACHE_PREFIX . 'first_path' => 'foo', CachedUrlGenerator::PATH_CACHE_PREFIX . 'second_path' => 'bar')));
+
+    // Mock a UrlGenerator to pass to the CachedUrlGenerator.
+    $url_generator = $this->getMockBuilder('Drupal\Core\Routing\UrlGenerator')
+      ->disableOriginalConstructor()
+      ->getMock();
+
+    // The decorated url generator should only be consulted
+    // once, for the second path, which was not in the cache.
+    $url_generator->expects($this->once())
+      ->method('generateFromPath')
+      ->with($this->equalTo('second_path'), $this->anything())
+      ->will($this->returnValue('bar'));
+
+    // Instantiate a CachedUrlGenerator and call various methods
+    // on it to ensure the expectations we set on our mocks are met.
+    $cached_url_generator = new CachedUrlGenerator($url_generator, $cache);
+    $request = Request::create('some/path');
+    $request->attributes->set('system_path', $system_path);
+    $cached_url_generator->setRequest($request);
+    $url = $cached_url_generator->generateFromPath('first_path');
+    $url = $cached_url_generator->generateFromPath('second_path');
+    $cached_url_generator->destruct();
+  }
+
+  /**
    * Tests path-based URL generation.
    */
   public function testPathBasedURLGeneration() {
