diff --git a/core/core.services.yml b/core/core.services.yml
index 9e2e188..07a2dcb 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -793,7 +793,15 @@ services:
     class: Drupal\Core\Asset\AssetDumper
   library.discovery:
     class: Drupal\Core\Asset\LibraryDiscovery
-    arguments: ['@cache.discovery', '@module_handler']
+    arguments: ['@library.discovery.collector']
+  library.discovery.parser:
+    class: Drupal\Core\Asset\LibraryDiscoveryParser
+    arguments: ['@module_handler']
+  library.discovery.collector:
+    class: Drupal\Core\Asset\LibraryDiscoveryCollector
+    arguments: ['@cache.discovery', '@lock', '@library.discovery.parser']
+    tags:
+      - { name: needs_destruction }
   info_parser:
     class: Drupal\Core\Extension\InfoParser
   element_info:
diff --git a/core/lib/Drupal/Core/Asset/LibraryDiscovery.php b/core/lib/Drupal/Core/Asset/LibraryDiscovery.php
index 2a25ea3..b0c3696 100644
--- a/core/lib/Drupal/Core/Asset/LibraryDiscovery.php
+++ b/core/lib/Drupal/Core/Asset/LibraryDiscovery.php
@@ -7,14 +7,7 @@
 
 namespace Drupal\Core\Asset;
 
-use Drupal\Component\Serialization\Yaml;
-use Drupal\Component\Serialization\Exception\InvalidDataTypeException;
-use Drupal\Core\Asset\Exception\IncompleteLibraryDefinitionException;
-use Drupal\Core\Asset\Exception\InvalidLibraryFileException;
-use Drupal\Core\Cache\Cache;
-use Drupal\Core\Cache\CacheBackendInterface;
-use Drupal\Core\Extension\ModuleHandlerInterface;
-use Drupal\Core\Extension\ThemeHandlerInterface;
+use Drupal\Core\Cache\CacheCollectorInterface;
 
 /**
  * Discovers available asset libraries in Drupal.
@@ -22,25 +15,11 @@
 class LibraryDiscovery implements LibraryDiscoveryInterface {
 
   /**
-   * Stores the library information keyed by extension.
+   * The library discovery cache collector.
    *
-   * @var array
+   * @var \Drupal\Core\Cache\CacheCollectorInterface
    */
-  protected $libraries;
-
-  /**
-   * The cache backend.
-   *
-   * @var \Drupal\Core\Cache\CacheBackendInterface
-   */
-  protected $cache;
-
-  /**
-   * The module handler.
-   *
-   * @var \Drupal\Core\Extension\ModuleHandlerInterface
-   */
-  protected $moduleHandler;
+  protected $collector;
 
   /**
    * Constructs a new LibraryDiscovery instance.
@@ -50,263 +29,23 @@ class LibraryDiscovery implements LibraryDiscoveryInterface {
    * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
    *   The module handler.
    */
-  public function __construct(CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler) {
-    $this->cache = $cache_backend;
-    $this->moduleHandler = $module_handler;
+  public function __construct(CacheCollectorInterface $library_discovery_collector) {
+    $this->collector = $library_discovery_collector;
   }
 
   /**
    * {@inheritdoc}
    */
   public function getLibrariesByExtension($extension) {
-    $this->ensureLibraryInformation($extension);
-    return $this->libraries[$extension];
+    return $this->collector->get($extension);
   }
 
   /**
    * {@inheritdoc}
    */
   public function getLibraryByName($extension, $name) {
-    $this->ensureLibraryInformation($extension);
-    return isset($this->libraries[$extension][$name]) ? $this->libraries[$extension][$name] : FALSE;
-  }
-
-  /**
-   * Ensures that the libraries property is filled.
-   *
-   * @param string $extension
-   *   The name of the extension that registered a library.
-   */
-  protected function ensureLibraryInformation($extension) {
-    $this->getCache($extension);
-    if (!isset($this->libraries[$extension])) {
-      if ($information = $this->buildLibrariesByExtension($extension)) {
-        $this->libraries[$extension] = $information;
-      }
-      else {
-        $this->libraries[$extension] = FALSE;
-      }
-      $this->setCache($extension, $this->libraries[$extension]);
-    }
-  }
-
-  /**
-   * Fills up the libraries property from cache, if available.
-   *
-   * @param string $extension
-   *   The name of the extension that registered a library.
-   */
-  protected function getCache($extension) {
-    if (!isset($this->libraries[$extension])) {
-      if ($cache = $this->cache->get('library:info:' . $extension)) {
-        $this->libraries[$extension] = $cache->data;
-      }
-    }
-  }
-
-  /**
-   * Sets the library information into a cache entry.
-   *
-   * @param string $extension
-   *   The name of the extension that registered a library.
-   *
-   * @param bool|array $information
-   *   All library definitions of the passed extension or FALSE if no
-   *   information is available.
-   */
-  protected function setCache($extension, $information) {
-    $this->cache->set('library:info:' . $extension, $information, Cache::PERMANENT, array(
-      'extension' => array(TRUE, $extension),
-      'library_info' => array(TRUE),
-    ));
-  }
-
-  /**
-   * Parses and builds up all the libraries information of an extension.
-   *
-   * @param string $extension
-   *   The name of the extension that registered a library.
-   *
-   * @return array
-   *   All library definitions of the passed extension.
-   *
-   * @throws \Drupal\Core\Asset\Exception\IncompleteLibraryDefinitionException
-   *   Thrown when a library has no js/css/setting.
-   * @throws \UnexpectedValueException
-   *   Thrown when a js file defines a positive weight.
-   */
-  protected function buildLibrariesByExtension($extension) {
-    $this->libraries[$extension] = array();
-    if ($extension === 'core') {
-      $path = 'core';
-      $extension_type = 'core';
-    }
-    else {
-      if ($this->moduleHandler->moduleExists($extension)) {
-        $extension_type = 'module';
-      }
-      else {
-        $extension_type = 'theme';
-      }
-      $path = $this->drupalGetPath($extension_type, $extension);
-    }
-    $library_file = $path . '/' . $extension . '.libraries.yml';
-
-    if ($library_file && file_exists(DRUPAL_ROOT . '/' . $library_file)) {
-      $this->libraries[$extension] = array();
-      $this->parseLibraryInfo($extension, $library_file);
-    }
-
-    foreach ($this->libraries[$extension] as $id => &$library) {
-      if (!isset($library['js']) && !isset($library['css']) && !isset($library['settings'])) {
-        throw new IncompleteLibraryDefinitionException(sprintf("Incomplete library definition for '%s' in %s", $id, $library_file));
-      }
-      $library += array('dependencies' => array(), 'js' => array(), 'css' => array());
-
-      if (isset($library['version'])) {
-        // @todo Retrieve version of a non-core extension.
-        if ($library['version'] === 'VERSION') {
-          $library['version'] = \Drupal::VERSION;
-        }
-        // Remove 'v' prefix from external library versions.
-        elseif ($library['version'][0] === 'v') {
-          $library['version'] = substr($library['version'], 1);
-        }
-      }
-
-      foreach (array('js', 'css') as $type) {
-        // Prepare (flatten) the SMACSS-categorized definitions.
-        // @todo After Asset(ic) changes, retain the definitions as-is and
-        //   properly resolve dependencies for all (css) libraries per category,
-        //   and only once prior to rendering out an HTML page.
-        if ($type == 'css' && !empty($library[$type])) {
-          foreach ($library[$type] as $category => $files) {
-            foreach ($files as $source => $options) {
-              if (!isset($options['weight'])) {
-                $options['weight'] = 0;
-              }
-              // Apply the corresponding weight defined by CSS_* constants.
-              $options['weight'] += constant('CSS_' . strtoupper($category));
-              $library[$type][$source] = $options;
-            }
-            unset($library[$type][$category]);
-          }
-        }
-        foreach ($library[$type] as $source => $options) {
-          unset($library[$type][$source]);
-          // Allow to omit the options hashmap in YAML declarations.
-          if (!is_array($options)) {
-            $options = array();
-          }
-          if ($type == 'js' && isset($options['weight']) && $options['weight'] > 0) {
-            throw new \UnexpectedValueException("The $extension/$id library defines a positive weight for '$source'. Only negative weights are allowed (but should be avoided). Instead of a positive weight, specify accurate dependencies for this library.");
-          }
-          // Unconditionally apply default groups for the defined asset files.
-          // The library system is a dependency management system. Each library
-          // properly specifies its dependencies instead of relying on a custom
-          // processing order.
-          if ($type == 'js') {
-            $options['group'] = JS_LIBRARY;
-          }
-          elseif ($type == 'css') {
-            $options['group'] = $extension_type == 'theme' ? CSS_AGGREGATE_THEME : CSS_AGGREGATE_DEFAULT;
-          }
-          // By default, all library assets are files.
-          if (!isset($options['type'])) {
-            $options['type'] = 'file';
-          }
-          if ($options['type'] == 'external') {
-            $options['data'] = $source;
-          }
-          // Determine the file asset URI.
-          else {
-            if ($source[0] === '/') {
-              // An absolute path maps to DRUPAL_ROOT / base_path().
-              if ($source[1] !== '/') {
-                $options['data'] = substr($source, 1);
-              }
-              // A protocol-free URI (e.g., //cdn.com/example.js) is external.
-              else {
-                $options['type'] = 'external';
-                $options['data'] = $source;
-              }
-            }
-            // A stream wrapper URI (e.g., public://generated_js/example.js).
-            elseif ($this->fileValidUri($source)) {
-              $options['data'] = $source;
-            }
-            // By default, file paths are relative to the registering extension.
-            else {
-              $options['data'] = $path . '/' . $source;
-            }
-          }
-
-          if (!isset($library['version'])) {
-            // @todo Get the information from the extension.
-            $options['version'] = -1;
-          }
-          else {
-            $options['version'] = $library['version'];
-          }
-
-          $library[$type][] = $options;
-        }
-      }
-
-      // @todo Introduce drupal_add_settings().
-      if (isset($library['settings'])) {
-        $library['js'][] = array(
-          'type' => 'setting',
-          'data' => $library['settings'],
-        );
-        unset($library['settings']);
-      }
-      // @todo Convert all uses of #attached[library][]=array('provider','name')
-      //   into #attached[library][]='provider/name' and remove this.
-      foreach ($library['dependencies'] as $i => $dependency) {
-        $library['dependencies'][$i] = $dependency;
-      }
-    }
-    return $this->libraries[$extension];
-  }
-
-  /**
-   * Wraps drupal_get_path().
-   */
-  protected function drupalGetPath($type, $name) {
-    return drupal_get_path($type, $name);
-  }
-
-  /**
-   * Wraps file_valid_uri().
-   */
-  protected function fileValidUri($source) {
-    return file_valid_uri($source);
-  }
-
-  /**
-   * Parses a given library file and allows module to alter it.
-   *
-   * This method sets the parsed information onto the library property.
-   *
-   * @param string $extension
-   *   The name of the extension that registered a library.
-   * @param string $library_file
-   *   The relative filename to the DRUPAL_ROOT of the wanted library file.
-   *
-   * @throws \Drupal\Core\Asset\Exception\InvalidLibraryFileException
-   *   Thrown when a parser exception got thrown.
-   */
-  protected function parseLibraryInfo($extension, $library_file) {
-    try {
-      $this->libraries[$extension] = Yaml::decode(file_get_contents(DRUPAL_ROOT . '/' . $library_file));
-    }
-    catch (InvalidDataTypeException $e) {
-      // Rethrow a more helpful exception to provide context.
-      throw new InvalidLibraryFileException(sprintf('Invalid library definition in %s: %s', $library_file, $e->getMessage()), 0, $e);
-    }
-    // Allow modules to alter the module's registered libraries.
-    $this->moduleHandler->alter('library_info', $this->libraries[$extension], $extension);
+    $extension = $this->getLibrariesByExtension($extension);
+    return isset($extension[$name]) ? $extension[$name] : FALSE;
   }
 
 }
diff --git a/core/lib/Drupal/Core/Asset/LibraryDiscoveryCollector.php b/core/lib/Drupal/Core/Asset/LibraryDiscoveryCollector.php
new file mode 100644
index 0000000..62e23ad
--- /dev/null
+++ b/core/lib/Drupal/Core/Asset/LibraryDiscoveryCollector.php
@@ -0,0 +1,75 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Asset\LibraryDiscoveryCollector.
+ */
+
+namespace Drupal\Core\Asset;
+
+use Drupal\Core\Cache\CacheCollector;
+use Drupal\Core\Cache\CacheBackendInterface;
+use Drupal\Core\Lock\LockBackendInterface;
+
+/**
+ * Class LibraryDiscoveryCollector.
+ */
+class LibraryDiscoveryCollector extends CacheCollector {
+
+  /**
+   * The cache key.
+   *
+   * @var string
+   */
+  protected $cacheKey = 'library_info';
+
+  /**
+   * The cache backend.
+   *
+   * @var \Drupal\Core\Cache\CacheBackendInterface
+   */
+  protected $cache;
+
+  /**
+   * The lock backend.
+   *
+   * @var \Drupal\Core\Lock\LockBackendInterface
+   */
+  protected $lock;
+
+  /**
+   * The library discovery parser.
+   *
+   * @var \Drupal\Core\Asset\LibraryDiscoveryParser
+   */
+  protected $discoveryParser;
+
+  /**
+   * Constructs a CacheCollector object.
+   *
+   * @param string $cid
+   *   The cid for the array being cached.
+   * @param \Drupal\Core\Cache\CacheBackendInterface $cache
+   *   The cache backend.
+   * @param \Drupal\Core\Lock\LockBackendInterface $lock
+   *   The lock backend.
+   * @param \Drupal\Core\Asset\LibraryDiscoveryParser $discovery_parser
+   *   The librayr discovery parser.
+   */
+  public function __construct(CacheBackendInterface $cache, LockBackendInterface $lock, LibraryDiscoveryParser $discovery_parser) {
+    parent::__construct($this->cacheKey, $cache, $lock, array($this->cacheKey => array(TRUE)));
+
+    $this->discoveryParser = $discovery_parser;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function resolveCacheMiss($key) {
+    $this->storage[$key] = $this->discoveryParser->buildLibrariesByExtension($key);
+    $this->persist($key);
+
+    return $this->storage[$key];
+  }
+
+}
diff --git a/core/lib/Drupal/Core/Asset/LibraryDiscovery.php b/core/lib/Drupal/Core/Asset/LibraryDiscoveryParser.php
similarity index 74%
copy from core/lib/Drupal/Core/Asset/LibraryDiscovery.php
copy to core/lib/Drupal/Core/Asset/LibraryDiscoveryParser.php
index 2a25ea3..808fe42 100644
--- a/core/lib/Drupal/Core/Asset/LibraryDiscovery.php
+++ b/core/lib/Drupal/Core/Asset/LibraryDiscoveryParser.php
@@ -2,40 +2,30 @@
 
 /**
  * @file
- * Contains \Drupal\Core\Asset\LibraryDiscovery.
+ * Contains \Drupal\Core\Asset\LibraryDiscoveryParser.
  */
 
 namespace Drupal\Core\Asset;
 
-use Drupal\Component\Serialization\Yaml;
-use Drupal\Component\Serialization\Exception\InvalidDataTypeException;
 use Drupal\Core\Asset\Exception\IncompleteLibraryDefinitionException;
 use Drupal\Core\Asset\Exception\InvalidLibraryFileException;
-use Drupal\Core\Cache\Cache;
-use Drupal\Core\Cache\CacheBackendInterface;
 use Drupal\Core\Extension\ModuleHandlerInterface;
-use Drupal\Core\Extension\ThemeHandlerInterface;
+use Drupal\Component\Serialization\Exception\InvalidDataTypeException;
+use Drupal\Component\Serialization\Yaml;
 
 /**
- * Discovers available asset libraries in Drupal.
+ * Parses library files to get extension data.
  */
-class LibraryDiscovery implements LibraryDiscoveryInterface {
+class LibraryDiscoveryParser {
 
   /**
-   * Stores the library information keyed by extension.
+   * An array of discovered library extensions.
    *
    * @var array
    */
   protected $libraries;
 
   /**
-   * The cache backend.
-   *
-   * @var \Drupal\Core\Cache\CacheBackendInterface
-   */
-  protected $cache;
-
-  /**
    * The module handler.
    *
    * @var \Drupal\Core\Extension\ModuleHandlerInterface
@@ -43,85 +33,14 @@ class LibraryDiscovery implements LibraryDiscoveryInterface {
   protected $moduleHandler;
 
   /**
-   * Constructs a new LibraryDiscovery instance.
-   *
-   * @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend
-   *   The cache backend.
    * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
-   *   The module handler.
+   *   The moduel handler.
    */
-  public function __construct(CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler) {
-    $this->cache = $cache_backend;
+  public function __construct(ModuleHandlerInterface $module_handler) {
     $this->moduleHandler = $module_handler;
   }
 
   /**
-   * {@inheritdoc}
-   */
-  public function getLibrariesByExtension($extension) {
-    $this->ensureLibraryInformation($extension);
-    return $this->libraries[$extension];
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getLibraryByName($extension, $name) {
-    $this->ensureLibraryInformation($extension);
-    return isset($this->libraries[$extension][$name]) ? $this->libraries[$extension][$name] : FALSE;
-  }
-
-  /**
-   * Ensures that the libraries property is filled.
-   *
-   * @param string $extension
-   *   The name of the extension that registered a library.
-   */
-  protected function ensureLibraryInformation($extension) {
-    $this->getCache($extension);
-    if (!isset($this->libraries[$extension])) {
-      if ($information = $this->buildLibrariesByExtension($extension)) {
-        $this->libraries[$extension] = $information;
-      }
-      else {
-        $this->libraries[$extension] = FALSE;
-      }
-      $this->setCache($extension, $this->libraries[$extension]);
-    }
-  }
-
-  /**
-   * Fills up the libraries property from cache, if available.
-   *
-   * @param string $extension
-   *   The name of the extension that registered a library.
-   */
-  protected function getCache($extension) {
-    if (!isset($this->libraries[$extension])) {
-      if ($cache = $this->cache->get('library:info:' . $extension)) {
-        $this->libraries[$extension] = $cache->data;
-      }
-    }
-  }
-
-  /**
-   * Sets the library information into a cache entry.
-   *
-   * @param string $extension
-   *   The name of the extension that registered a library.
-   *
-   * @param bool|array $information
-   *   All library definitions of the passed extension or FALSE if no
-   *   information is available.
-   */
-  protected function setCache($extension, $information) {
-    $this->cache->set('library:info:' . $extension, $information, Cache::PERMANENT, array(
-      'extension' => array(TRUE, $extension),
-      'library_info' => array(TRUE),
-    ));
-  }
-
-  /**
    * Parses and builds up all the libraries information of an extension.
    *
    * @param string $extension
@@ -135,8 +54,13 @@ protected function setCache($extension, $information) {
    * @throws \UnexpectedValueException
    *   Thrown when a js file defines a positive weight.
    */
-  protected function buildLibrariesByExtension($extension) {
+  public function buildLibrariesByExtension($extension) {
+    if (isset($this->libraries[$extension])) {
+      return $this->libraries[$extension];
+    }
+
     $this->libraries[$extension] = array();
+
     if ($extension === 'core') {
       $path = 'core';
       $extension_type = 'core';
@@ -267,21 +191,8 @@ protected function buildLibrariesByExtension($extension) {
         $library['dependencies'][$i] = $dependency;
       }
     }
-    return $this->libraries[$extension];
-  }
-
-  /**
-   * Wraps drupal_get_path().
-   */
-  protected function drupalGetPath($type, $name) {
-    return drupal_get_path($type, $name);
-  }
 
-  /**
-   * Wraps file_valid_uri().
-   */
-  protected function fileValidUri($source) {
-    return file_valid_uri($source);
+    return $this->libraries[$extension];
   }
 
   /**
@@ -309,4 +220,18 @@ protected function parseLibraryInfo($extension, $library_file) {
     $this->moduleHandler->alter('library_info', $this->libraries[$extension], $extension);
   }
 
+  /**
+   * Wraps drupal_get_path().
+   */
+  protected function drupalGetPath($type, $name) {
+    return drupal_get_path($type, $name);
+  }
+
+  /**
+   * Wraps file_valid_uri().
+   */
+  protected function fileValidUri($source) {
+    return file_valid_uri($source);
+  }
+
 }
diff --git a/core/tests/Drupal/Tests/Core/Asset/LibraryDiscoveryTest.php b/core/tests/Drupal/Tests/Core/Asset/LibraryDiscoveryTest.php
index 230cac6..52f38b5 100644
--- a/core/tests/Drupal/Tests/Core/Asset/LibraryDiscoveryTest.php
+++ b/core/tests/Drupal/Tests/Core/Asset/LibraryDiscoveryTest.php
@@ -58,11 +58,11 @@ class LibraryDiscoveryTest extends UnitTestCase {
   protected $moduleHandler;
 
   /**
-   * The mocked theme handler.
+   * The mocked lock backend..
    *
-   * @var \Drupal\Core\Extension\ThemeHandlerInterface
+   * @var \Drupal\Core\Lock\LockBackendInterface|\PHPUnit_Framework_MockObject_MockObject
    */
-  protected $themeHandler;
+  protected $lock;
 
   /**
    * {@inheritdoc}
@@ -81,8 +81,8 @@ public static function getInfo() {
   protected function setUp() {
     $this->cache = $this->getMock('Drupal\Core\Cache\CacheBackendInterface');
     $this->moduleHandler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface');
-    $this->themeHandler = $this->getMock('Drupal\Core\Extension\ThemeHandlerInterface');
-    $this->libraryDiscovery = new TestLibraryDiscovery($this->cache, $this->moduleHandler, $this->themeHandler);
+    $this->lock = $this->getMock('Drupal\Core\Lock\LockBackendInterface');
+    $this->libraryDiscovery = new TestLibraryDiscovery($this->cache, $this->moduleHandler, $this->lock);
   }
 
   /**
