diff --git a/core/includes/common.inc b/core/includes/common.inc
index ab11ddf..7c16197 100644
--- a/core/includes/common.inc
+++ b/core/includes/common.inc
@@ -13,8 +13,8 @@
 use Drupal\Core\Language\Language;
 use Symfony\Component\HttpFoundation\Response;
 use Symfony\Component\HttpFoundation\Request;
-use Symfony\Component\Yaml\Parser;
-use Symfony\Component\Yaml\Exception\ParseException;
+use Drupal\Core\Serialization\Yaml;
+use Drupal\Core\Serialization\Exception\InvalidDataTypeException;
 use Drupal\Component\PhpStorage\PhpStorageFactory;
 use Drupal\Component\Utility\NestedArray;
 use Drupal\Core\Datetime\DrupalDateTime;
@@ -2767,12 +2767,11 @@ function drupal_get_library($extension, $name = NULL) {
 
     if ($library_file && file_exists(DRUPAL_ROOT . '/' . $library_file)) {
       $libraries[$extension] = array();
-      $parser = new Parser();
       try {
-        $libraries[$extension] = $parser->parse(file_get_contents(DRUPAL_ROOT . '/' . $library_file));
+        $libraries[$extension] = Yaml::readFile($library_file);
       }
-      catch (ParseException $e) {
-        // Rethrow a more helpful exception, since ParseException lacks context.
+      catch (InvalidDataTypeException $e) {
+        // Rethrow a more helpful exception to provide context.
         throw new \RuntimeException(sprintf('Invalid library definition in %s: %s', $library_file, $e->getMessage()), 0, $e);
       }
       // Allow modules to alter the module's registered libraries.
diff --git a/core/lib/Drupal/Component/Discovery/YamlDiscovery.php b/core/lib/Drupal/Component/Discovery/YamlDiscovery.php
index 5ac0b7d..465adec 100644
--- a/core/lib/Drupal/Component/Discovery/YamlDiscovery.php
+++ b/core/lib/Drupal/Component/Discovery/YamlDiscovery.php
@@ -7,7 +7,7 @@
 
 namespace Drupal\Component\Discovery;
 
-use Symfony\Component\Yaml\Parser;
+use Drupal\Core\Serialization\Yaml;
 
 /**
  * Provides discovery for YAML files within a given set of directories.
@@ -29,13 +29,6 @@ class YamlDiscovery implements DiscoverableInterface {
   protected $directories = array();
 
   /**
-   * The symfony YAML parser.
-   *
-   * @var \Symfony\Component\Yaml\Parser
-   */
-  protected $parser;
-
-  /**
    * Constructs a YamlDiscovery object.
    *
    * @param string $name
@@ -54,29 +47,14 @@ public function __construct($name, array $directories) {
    */
   public function findAll() {
     $all = array();
-    $parser = $this->parser();
-
     foreach ($this->findFiles() as $provider => $file) {
-      $all[$provider] = $parser->parse(file_get_contents($file));
+      $all[$provider] = Yaml::readFile($file);
     }
 
     return $all;
   }
 
   /**
-   * Returns the YAML parser.
-   *
-   * @return \Symfony\Component\Yaml\Parser
-   *   The symfony YAML parser.
-   */
-  protected function parser() {
-    if (!isset($this->parser)) {
-      $this->parser = new Parser();
-    }
-    return $this->parser;
-  }
-
-  /**
    * Returns an array of file paths, keyed by provider.
    *
    * @return array
diff --git a/core/lib/Drupal/Core/Config/FileStorage.php b/core/lib/Drupal/Core/Config/FileStorage.php
index 2df9fbd..572f20d 100644
--- a/core/lib/Drupal/Core/Config/FileStorage.php
+++ b/core/lib/Drupal/Core/Config/FileStorage.php
@@ -8,9 +8,8 @@
 namespace Drupal\Core\Config;
 
 use Drupal\Component\Utility\String;
-use Symfony\Component\Yaml\Dumper;
-use Symfony\Component\Yaml\Exception\DumpException;
-use Symfony\Component\Yaml\Parser;
+use Drupal\Core\Serialization\Yaml;
+use Drupal\Core\Serialization\Exception\InvalidDataTypeException;
 
 /**
  * Defines the file storage controller.
@@ -25,20 +24,6 @@ class FileStorage implements StorageInterface {
   protected $directory = '';
 
   /**
-   * A shared YAML dumper instance.
-   *
-   * @var Symfony\Component\Yaml\Dumper
-   */
-  protected $dumper;
-
-  /**
-   * A shared YAML parser instance.
-   *
-   * @var Symfony\Component\Yaml\Parser
-   */
-  protected $parser;
-
-  /**
    * Constructs a new FileStorage controller.
    *
    * @param string $directory
@@ -78,16 +63,22 @@ public function exists($name) {
   /**
    * Implements Drupal\Core\Config\StorageInterface::read().
    *
-   * @throws Symfony\Component\Yaml\Exception\ParseException
+   * @throws \Drupal\Core\Config\UnsupportedDataTypeConfigException
    */
   public function read($name) {
     if (!$this->exists($name)) {
       return FALSE;
     }
-    $data = file_get_contents($this->getFilePath($name));
-    // @todo Yaml throws a ParseException on invalid data. Is it expected to be
-    //   caught or not?
-    $data = $this->decode($data);
+    //$data = file_get_contents($this->getFilePath($name));
+    try {
+      $data = Yaml::readFile($this->getFilePath($name));
+    }
+    catch (InvalidDataTypeException $e) {
+      throw new UnsupportedDataTypeConfigException(String::format('Invalid data type in config @name: !message', array(
+        '@name' => $name,
+        '!message' => $e->getMessage(),
+      )));
+    }
     return $data;
   }
 
@@ -114,8 +105,11 @@ public function write($name, array $data) {
     try {
       $data = $this->encode($data);
     }
-    catch(DumpException $e) {
-      throw new UnsupportedDataTypeConfigException(String::format('Invalid data type for used in config: @name', array('@name' => $name)));
+    catch (InvalidDataTypeException $e) {
+      throw new UnsupportedDataTypeConfigException(String::format('Invalid data type in config @name: !message', array(
+        '@name' => $name,
+        '!message' => $e->getMessage(),
+      )));
     }
 
     $target = $this->getFilePath($name);
@@ -154,51 +148,17 @@ public function rename($name, $new_name) {
   }
 
   /**
-   * Gets the YAML dumper instance.
-   *
-   * @return Symfony\Component\Yaml\Dumper
-   */
-  protected function getDumper() {
-    if (!isset($this->dumper)) {
-      $this->dumper = new Dumper();
-      // Set Yaml\Dumper's default indentation for nested nodes/collections to
-      // 2 spaces for consistency with Drupal coding standards.
-      $this->dumper->setIndentation(2);
-    }
-    return $this->dumper;
-  }
-
-  /**
-   * Gets the YAML parser instance.
-   *
-   * @return Symfony\Component\Yaml\Parser
-   */
-  protected function getParser() {
-    if (!isset($this->parser)) {
-      $this->parser = new Parser();
-    }
-    return $this->parser;
-  }
-
-  /**
    * Implements Drupal\Core\Config\StorageInterface::encode().
-   *
-   * @throws Symfony\Component\Yaml\Exception\DumpException
    */
   public function encode($data) {
-    // The level where you switch to inline YAML is set to PHP_INT_MAX to ensure
-    // this does not occur. Also set the exceptionOnInvalidType parameter to
-    // TRUE, so exceptions are thrown for an invalid data type.
-    return $this->getDumper()->dump($data, PHP_INT_MAX, 0, TRUE);
+    return Yaml::encode($data);
   }
 
   /**
    * Implements Drupal\Core\Config\StorageInterface::decode().
-   *
-   * @throws Symfony\Component\Yaml\Exception\ParseException
    */
   public function decode($raw) {
-    $data = $this->getParser()->parse($raw);
+    $data = Yaml::decode($raw);
     // A simple string is valid YAML for any reason.
     if (!is_array($data)) {
       return FALSE;
diff --git a/core/lib/Drupal/Core/Extension/InfoParser.php b/core/lib/Drupal/Core/Extension/InfoParser.php
index 4a23ad8..03a336f 100644
--- a/core/lib/Drupal/Core/Extension/InfoParser.php
+++ b/core/lib/Drupal/Core/Extension/InfoParser.php
@@ -8,8 +8,8 @@
 namespace Drupal\Core\Extension;
 
 use Drupal\Component\Utility\String;
-use Symfony\Component\Yaml\Exception\ParseException;
-use Symfony\Component\Yaml\Parser;
+use Drupal\Core\Serialization\Yaml;
+use Drupal\Core\Serialization\Exception\InvalidDataTypeException;
 
 /**
  * Parses extension .info.yml files.
@@ -24,13 +24,6 @@ class InfoParser implements InfoParserInterface {
   protected static $parsedInfos = array();
 
   /**
-   * Symfony YAML parser object.
-   *
-   * @var \Symfony\Component\Yaml\Parser
-   */
-  protected $parser;
-
-  /**
    * {@inheritdoc}
    */
   public function parse($filename) {
@@ -40,16 +33,16 @@ public function parse($filename) {
       }
       else {
         try {
-          static::$parsedInfos[$filename] = $this->getParser()->parse(file_get_contents($filename));
+          static::$parsedInfos[$filename] = Yaml::readFile($filename);
         }
-        catch (ParseException $e) {
-          $message = String::format("Unable to parse !file. Parser error !error.", array('!file' => $filename, '!error' => $e->getMessage()));
-          throw new InfoParserException($message, $filename);
+        catch (InvalidDataTypeException $e) {
+          $message = String::format("Unable to parse !file: !error", array('!file' => $filename, '!error' => $e->getMessage()));
+          throw new InfoParserException($message);
         }
         $missing_keys = array_diff($this->getRequiredKeys(), array_keys(static::$parsedInfos[$filename]));
         if (!empty($missing_keys)) {
           $message = format_plural(count($missing_keys), 'Missing required key (!missing_keys) in !file.', 'Missing required keys (!missing_keys) in !file.', array('!missing_keys' => implode(', ', $missing_keys), '!file' => $filename));
-          throw new InfoParserException($message, $filename);
+          throw new InfoParserException($message);
         }
         if (isset(static::$parsedInfos[$filename]['version']) && static::$parsedInfos[$filename]['version'] === 'VERSION') {
           static::$parsedInfos[$filename]['version'] = \Drupal::VERSION;
@@ -60,19 +53,6 @@ public function parse($filename) {
   }
 
   /**
-   * Returns a parser for parsing .info.yml files.
-   *
-   * @return \Symfony\Component\Yaml\Parser
-   *   Symfony YAML parser object.
-   */
-  protected function getParser() {
-    if (!$this->parser) {
-      $this->parser = new Parser();
-    }
-    return $this->parser;
-  }
-
-  /**
    * Returns an array of keys required to exist in .info.yml file.
    *
    * @return array
diff --git a/core/lib/Drupal/Core/Extension/InfoParserException.php b/core/lib/Drupal/Core/Extension/InfoParserException.php
index 2804bf6..df8071f 100644
--- a/core/lib/Drupal/Core/Extension/InfoParserException.php
+++ b/core/lib/Drupal/Core/Extension/InfoParserException.php
@@ -10,35 +10,4 @@
  * An exception thrown by the InfoParser class whilst parsing info.yml files.
  */
 class InfoParserException extends \RuntimeException {
-
-  /**
-   * The info.yml filename.
-   *
-   * @var string
-   */
-  protected $infoFilename;
-
-  /**
-   * Constructs the InfoParserException object.
-   *
-   * @param string $message
-   *   The Exception message to throw.
-   * @param string $filename
-   *   The info.yml filename.
-   */
-  public function __construct($message, $info_filename) {
-    $this->infoFilename = $info_filename;
-    parent::__construct($message);
-  }
-
-  /**
-   * Gets the info.yml filename.
-   *
-   * @return string
-   *   The info.yml filename.
-   */
-  public function getInfoFilename () {
-    return $this->infoFilename;
-  }
-
 }
diff --git a/core/lib/Drupal/Core/Serialization/Exception/InvalidDataTypeException.php b/core/lib/Drupal/Core/Serialization/Exception/InvalidDataTypeException.php
new file mode 100644
index 0000000..e6b8ce6
--- /dev/null
+++ b/core/lib/Drupal/Core/Serialization/Exception/InvalidDataTypeException.php
@@ -0,0 +1,14 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Serialization\Exception\InvalidDataTypeException.
+ */
+
+namespace Drupal\Core\Serialization\Exception;
+
+/**
+ * Exception thrown when a data type is invalid.
+ */
+class InvalidDataTypeException extends \InvalidArgumentException {
+}
diff --git a/core/lib/Drupal/Core/Serialization/SerializationInterface.php b/core/lib/Drupal/Core/Serialization/SerializationInterface.php
new file mode 100644
index 0000000..726c1da
--- /dev/null
+++ b/core/lib/Drupal/Core/Serialization/SerializationInterface.php
@@ -0,0 +1,56 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Serialization\SerializationInterface.
+ */
+
+namespace Drupal\Core\Serialization;
+
+/**
+ * Defines an interface for serialization formats.
+ */
+interface SerializationInterface {
+
+  /**
+   * Encodes data into the serialization format.
+   *
+   * @param mixed $data
+   *   The data to encode.
+   *
+   * @return string
+   *   The encoded data.
+   */
+  public static function encode($data);
+
+  /**
+   * Decodes data from the serialization format.
+   *
+   * @param string $raw
+   *   The raw data string to decode.
+   *
+   * @return mixed
+   *   The decoded data.
+   */
+  public static function decode($raw);
+
+  /**
+   * Returns the file extension for this serialization format.
+   *
+   * @return string
+   *   The file extension, without leading dot.
+   */
+  public static function getFileExtension();
+
+  /**
+   * Reads a file containing data in the serialization format.
+   *
+   * @param string $file
+   *   The file path to read.
+   *
+   * @return mixed
+   *   The decoded data.
+   */
+  public static function readFile($file);
+
+}
diff --git a/core/lib/Drupal/Core/Serialization/Yaml.php b/core/lib/Drupal/Core/Serialization/Yaml.php
new file mode 100644
index 0000000..dd0056a
--- /dev/null
+++ b/core/lib/Drupal/Core/Serialization/Yaml.php
@@ -0,0 +1,85 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Serialization\Yaml.
+ */
+
+namespace Drupal\Core\Serialization;
+
+use Drupal\Component\Utility\Settings;
+
+/**
+ * Default serialization for YAML.
+ *
+ * Automatically uses the optimal YAML implementation, unless overridden in
+ * Settings.
+ */
+class Yaml implements SerializationInterface {
+
+  /**
+   * The YAML implementation to use.
+   *
+   * @var \Drupal\Core\Serialization\SerializationInterface
+   */
+  protected static $instance;
+
+  /**
+   * Determines the optimal implementation to use for encoding and parsing Yaml.
+   *
+   * The selection is made based on the enabled PHP extensions, with the most
+   * performant available option chosen.
+   */
+  public function __construct() {
+    if (isset(static::$instance)) {
+      return;
+    }
+    $settings = Settings::getSingleton();
+    // If there is a settings.php override, use that.
+    if ($settings && ($class = $settings->get('yaml_parser_class'))) {
+      static::$instance = new $class();
+    }
+    else {
+      // Otherwise, fallback to the Symfony implementation.
+      static::$instance = new YamlSymfony();
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function encode($data) {
+    if (!isset(static::$instance)) {
+      new static();
+    }
+    return static::$instance->encode($data);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function decode($raw) {
+    if (!isset(static::$instance)) {
+      new static();
+    }
+    return static::$instance->decode($raw);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getFileExtension() {
+    return 'yml';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function readFile($file) {
+    if (!isset(static::$instance)) {
+      new static();
+    }
+    return static::$instance->readFile($file);
+  }
+
+}
diff --git a/core/lib/Drupal/Core/Serialization/YamlPrecompile.php b/core/lib/Drupal/Core/Serialization/YamlPrecompile.php
new file mode 100644
index 0000000..769df69
--- /dev/null
+++ b/core/lib/Drupal/Core/Serialization/YamlPrecompile.php
@@ -0,0 +1,222 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Serialization\YamlPrecompile.
+ */
+
+namespace Drupal\Core\Serialization;
+
+use Drupal\Component\Utility\Variable;
+use Drupal\Component\Utility\Settings;
+use Drupal\Core\Serialization\Exception\InvalidDataTypeException;
+
+
+/**
+ * Default serialization for YAML using the Symfony component.
+ */
+class YamlPrecompile implements SerializationInterface {
+
+  protected static $directory;
+
+  /**
+   * Determines the optimal implementation to use for encoding and parsing Yaml.
+   *
+   * The selection is made based on the enabled PHP extensions, with the most
+   * performant available option chosen.
+   */
+  public function __construct($directory = NULL) {
+    if (isset($directory)) {
+      static::$directory = $directory;
+    }
+    else {
+      static::$directory = Settings::getSingleton()->get('yaml_precompile_directory');
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function encode($data) {
+    return YamlSymfony::encode($data);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function decode($raw) {
+    return YamlSymfony::decode($raw);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getFileExtension() {
+    return YamlSymfony::getFileExtension();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function readFile($file) {
+    $path_info = pathinfo($file);
+    $compile_path = static::compiledPath($path_info);
+    if (file_exists($compile_path)) {
+      $var_name = static::variableName($path_info);
+      include $compile_path;
+      return ${$var_name};
+    }
+    return YamlSymfony::readFile($file);
+  }
+
+  protected static function compiledPath($path_info) {
+    if ($path_info['dirname'][0] == DIRECTORY_SEPARATOR) {
+      // Absolute path.
+      $root = new \SplFileInfo(__DIR__ . '/../../../../../');
+      $path_info['dirname'] = str_replace($root->getRealPath() . DIRECTORY_SEPARATOR, '', $path_info['dirname']);
+    }
+    return static::$directory . DIRECTORY_SEPARATOR . $path_info['dirname'] . DIRECTORY_SEPARATOR . $path_info['filename'] . '.php';
+  }
+
+  protected static function variableName($path_info) {
+    return str_replace(array('.', '-'), '_', $path_info['filename']);
+  }
+
+  public function compile($file) {
+    $path_info = pathinfo($file);
+    $compile_path = static::compiledPath($path_info);
+    $this->ensureDirectory(dirname($compile_path));
+    $var_name = static::variableName($path_info);
+    $data = Variable::export(YamlSymfony::readFile($file));
+    $content =<<<EOF
+<?php
+\$$var_name = $data;
+EOF;
+    file_put_contents($compile_path, $content);
+  }
+
+  public function compileCore() {
+    $files = array();
+    $dirs = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator(__DIR__ . '/../../../../', \RecursiveDirectoryIterator::FOLLOW_SYMLINKS));
+    foreach ($dirs as $dir) {
+      $pathname = $dir->getPathname();
+      // Exclude vendor.
+      if ($dir->getExtension() == 'yml' && strpos($pathname, '/../../../../vendor') === FALSE) {
+        $rel = 'core' . DIRECTORY_SEPARATOR . substr($pathname, strlen(__DIR__ . '/../../../../'));
+        $this->compile($rel);
+      }
+    }
+    return $files;
+
+  }
+
+  /**
+   * Ensures the directory exists, has the right permissions, and a .htaccess.
+   *
+   * For compatibility with open_basedir, the requested directory is created
+   * using a recursion logic that is based on the relative directory path/tree:
+   * It works from the end of the path recursively back towards the root
+   * directory, until an existing parent directory is found. From there, the
+   * subdirectories are created.
+   *
+   * @param string $directory
+   *   The directory path.
+   * @param int $mode
+   *   The mode, permissions, the directory should have.
+   *
+   * @return bool
+   *   TRUE if the directory exists or has been created, FALSE otherwise.
+   */
+  protected function ensureDirectory($directory, $mode = 0777) {
+    if ($this->createDirectory($directory, $mode)) {
+      $htaccess_path =  $directory . '/.htaccess';
+      if (!file_exists($htaccess_path) && file_put_contents($htaccess_path, static::htaccessLines())) {
+        @chmod($htaccess_path, 0444);
+      }
+    }
+  }
+
+  /**
+   * Ensures the requested directory exists and has the right permissions.
+   *
+   * For compatibility with open_basedir, the requested directory is created
+   * using a recursion logic that is based on the relative directory path/tree:
+   * It works from the end of the path recursively back towards the root
+   * directory, until an existing parent directory is found. From there, the
+   * subdirectories are created.
+   *
+   * @param string $directory
+   *   The directory path.
+   * @param int $mode
+   *   The mode, permissions, the directory should have.
+   * @param bool $is_backwards_recursive
+   *   Internal use only.
+   *
+   * @return bool
+   *   TRUE if the directory exists or has been created, FALSE otherwise.
+   */
+  protected function createDirectory($directory, $mode = 0777, $is_backwards_recursive = FALSE) {
+    // If the directory exists already, there's nothing to do.
+    if (is_dir($directory)) {
+      return TRUE;
+    }
+    // Otherwise, try to create the directory and ensure to set its permissions,
+    // because mkdir() obeys the umask of the current process.
+    if (is_dir($parent = dirname($directory))) {
+      // If the parent directory exists, then the backwards recursion must end,
+      // regardless of whether the subdirectory could be created.
+      if ($status = mkdir($directory)) {
+        // Only try to chmod() if the subdirectory could be created.
+        $status = chmod($directory, $mode);
+      }
+      return $is_backwards_recursive ? TRUE : $status;
+    }
+    // If the parent directory and the requested directory does not exist and
+    // could not be created above, walk the requested directory path back up
+    // until an existing directory is hit, and from there, recursively create
+    // the sub-directories. Only if that recursion succeeds, create the final,
+    // originally requested subdirectory.
+    return static::createDirectory($parent, $mode, TRUE) && mkdir($directory) && chmod($directory, $mode);
+  }
+
+  /**
+   * Returns the standard .htaccess lines that Drupal writes to file directories.
+   *
+   * This code is located here so this component can be stand-alone, but it is
+   * also called by file_htaccess_lines().
+   *
+   * @param bool $private
+   *   (Optional) Set to FALSE to return the .htaccess lines for an open and
+   *   public directory. The default is TRUE, which returns the .htaccess lines
+   *   for a private and protected directory.
+   *
+   * @return string
+   *   The desired contents of the .htaccess file.
+   */
+  protected static function htaccessLines($private = TRUE) {
+    $lines = <<<EOF
+# Turn off all options we don't need.
+Options None
+Options +FollowSymLinks
+
+# Set the catch-all handler to prevent scripts from being executed.
+SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006
+<Files *>
+  # Override the handler again if we're run later in the evaluation list.
+  SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003
+</Files>
+
+# If we know how to do it safely, disable the PHP engine entirely.
+<IfModule mod_php5.c>
+  php_flag engine off
+</IfModule>
+EOF;
+
+    if ($private) {
+      $lines = "Deny from all\n\n" . $lines;
+    }
+
+    return $lines;
+  }
+
+}
diff --git a/core/lib/Drupal/Core/Serialization/YamlSymfony.php b/core/lib/Drupal/Core/Serialization/YamlSymfony.php
new file mode 100644
index 0000000..74f55c6
--- /dev/null
+++ b/core/lib/Drupal/Core/Serialization/YamlSymfony.php
@@ -0,0 +1,56 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Serialization\YamlSymfony.
+ */
+
+namespace Drupal\Core\Serialization;
+
+use Drupal\Core\Serialization\Exception\InvalidDataTypeException;
+use Symfony\Component\Yaml\Yaml as Symfony;
+
+/**
+ * Default serialization for YAML using the Symfony component.
+ */
+class YamlSymfony implements SerializationInterface {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function encode($data) {
+    try {
+      return Symfony::dump($data, PHP_INT_MAX, 2, TRUE);
+    }
+    catch (\Exception $e) {
+      throw new InvalidDataTypeException($e->getMessage(), $e->getCode(), $e);
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function decode($raw) {
+    try {
+      return Symfony::parse($raw, TRUE);
+    }
+    catch (\Exception $e) {
+      throw new InvalidDataTypeException($e->getMessage(), $e->getCode(), $e);
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getFileExtension() {
+    return 'yml';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function readFile($file) {
+    return static::decode(file_get_contents($file));
+  }
+
+}
diff --git a/core/modules/config/lib/Drupal/config/Tests/Storage/ConfigStorageTestBase.php b/core/modules/config/lib/Drupal/config/Tests/Storage/ConfigStorageTestBase.php
index d986835..0ed768f 100644
--- a/core/modules/config/lib/Drupal/config/Tests/Storage/ConfigStorageTestBase.php
+++ b/core/modules/config/lib/Drupal/config/Tests/Storage/ConfigStorageTestBase.php
@@ -27,7 +27,6 @@
    * Tests storage controller CRUD operations.
    *
    * @todo Coverage: Trigger PDOExceptions / Database exceptions.
-   * @todo Coverage: Trigger Yaml's ParseException and DumpException.
    */
   function testCRUD() {
     $name = 'config_test.storage';
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php
index e1bcc90..44d0bf7 100644
--- a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php
+++ b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php
@@ -160,6 +160,15 @@
   public $dieOnFail = FALSE;
 
   /**
+   * Whether to use precompiled YAML.
+   *
+   * @var boolean
+   *
+   * @see run-tests.sh
+   */
+  public $precompileYaml = FALSE;
+
+  /**
    * The DrupalKernel instance used in the test.
    *
    * @var \Drupal\Core\DrupalKernel
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/UnitTestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/UnitTestBase.php
index 9d93fa0..4e1f874 100644
--- a/core/modules/simpletest/lib/Drupal/simpletest/UnitTestBase.php
+++ b/core/modules/simpletest/lib/Drupal/simpletest/UnitTestBase.php
@@ -39,5 +39,9 @@ function __construct($test_id = NULL) {
   protected function setUp() {
     file_prepare_directory($this->public_files_directory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);
     $this->settingsSet('file_public_path', $this->public_files_directory);
+    if ($this->precompileYaml) {
+      $this->settingsSet('yaml_parser_class', 'Drupal\Core\Serialization\YamlPrecompile');
+      $this->settingsSet('yaml_precompile_directory', $this->originalFileDirectory . '/simpletest/yml');
+    }
   }
-}
+}
\ No newline at end of file
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
index a442dd0..d97ea77 100644
--- a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
+++ b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
@@ -797,6 +797,20 @@ protected function setUp() {
       'value' => $this->originalProfile,
       'required' => TRUE,
     );
+
+    if ($this->precompileYaml) {
+      $this->settingsSet('yaml_parser_class', 'Drupal\Core\Serialization\YamlPrecompile');
+      $this->settingsSet('yaml_precompile_directory', $this->originalFileDirectory . '/simpletest/yml');
+    }
+    $settings['settings']['yaml_parser_class'] = (object) array(
+      'value' => 'Drupal\Core\Serialization\YamlPrecompile',
+      'required' => TRUE,
+    );
+    $settings['settings']['yaml_precompile_directory'] = (object) array(
+      'value' => $this->originalFileDirectory . '/simpletest/yml',
+      'required' => TRUE,
+    );
+
     $this->writeSettings($settings);
 
     // Since Drupal is bootstrapped already, install_begin_request() will not
diff --git a/core/modules/system/lib/Drupal/system/Tests/Extension/InfoParserUnitTest.php b/core/modules/system/lib/Drupal/system/Tests/Extension/InfoParserUnitTest.php
index 8be4af9..f59dad6 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Extension/InfoParserUnitTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Extension/InfoParserUnitTest.php
@@ -90,7 +90,7 @@ public function testInfoParser() {
     $info_values = $this->infoParser->parse('core/modules/system/tests/fixtures/common_test.info.txt');
     $this->assertEqual($info_values['simple_string'], 'A simple string', 'Simple string value was parsed correctly.', 'System');
     $this->assertEqual($info_values['version'], \Drupal::VERSION, 'Constant value was parsed correctly.', 'System');
-    $this->assertEqual($info_values['double_colon'], 'dummyClassName::', 'Value containing double-colon was parsed correctly.', 'System');
+    $this->assertEqual($info_values['double_colon'], 'dummyClassName::foo', 'Value containing double-colon was parsed correctly.', 'System');
   }
 
 }
diff --git a/core/modules/system/tests/fixtures/common_test.info.txt b/core/modules/system/tests/fixtures/common_test.info.txt
index 7e57dfe..ff535b1 100644
--- a/core/modules/system/tests/fixtures/common_test.info.txt
+++ b/core/modules/system/tests/fixtures/common_test.info.txt
@@ -4,4 +4,4 @@ type: module
 description: 'testing info file parsing'
 simple_string: 'A simple string'
 version: "VERSION"
-double_colon: dummyClassName::
+double_colon: dummyClassName::foo
diff --git a/core/scripts/run-tests.sh b/core/scripts/run-tests.sh
index 5594dd5..df261ab 100755
--- a/core/scripts/run-tests.sh
+++ b/core/scripts/run-tests.sh
@@ -7,6 +7,8 @@
 require_once __DIR__ . '/../vendor/autoload.php';
 
 use Drupal\Component\Utility\Timer;
+use Drupal\Core\Serialization\YamlPrecompile;
+use Drupal\Core\StreamWrapper\PublicStream;
 
 const SIMPLETEST_SCRIPT_COLOR_PASS = 32; // Green.
 const SIMPLETEST_SCRIPT_COLOR_FAIL = 31; // Red.
@@ -78,6 +80,10 @@
 
 simpletest_script_reporter_init();
 
+if ($args['precompile-yaml']) {
+  simpletest_precompile_yaml();
+}
+
 // Execute tests.
 for ($i = 0; $i < $args['repeat']; $i++) {
   simpletest_script_execute_batch($test_list);
@@ -160,6 +166,9 @@ function simpletest_script_help() {
 
   --repeat    Number of times to repeat the test.
 
+  --precompile-yaml
+              Use the YAML precompiler.
+
   --die-on-fail
 
               Exit test execution immediately upon any failed assertion. This
@@ -218,6 +227,7 @@ function simpletest_script_parse_args() {
     'test-id' => 0,
     'execute-test' => '',
     'xml' => '',
+    'precompile-yaml' => TRUE,
   );
 
   // Override with set values.
@@ -497,6 +507,7 @@ function simpletest_script_run_one_test($test_id, $test_class) {
     $test = new $test_class($test_id);
     $test->dieOnFail = (bool) $args['die-on-fail'];
     $test->verbose = (bool) $args['verbose'];
+    $test->precompileYaml = (bool) $args['precompile-yaml'];
     $test->run();
     $info = $test->getInfo();
 
@@ -531,7 +542,7 @@ function simpletest_script_command($test_id, $test_class) {
   $command .= ' --url ' . escapeshellarg($args['url']);
   $command .= ' --php ' . escapeshellarg($php);
   $command .= " --test-id $test_id";
-  foreach (array('verbose', 'keep-results', 'color', 'die-on-fail') as $arg) {
+  foreach (array('verbose', 'keep-results', 'color', 'die-on-fail', 'precompile-yaml') as $arg) {
     if ($args[$arg]) {
       $command .= ' --' . $arg;
     }
@@ -901,3 +912,10 @@ function simpletest_script_color_code($status) {
   }
   return 0; // Default formatting.
 }
+
+function simpletest_precompile_yaml() {
+  $dir = PublicStream::basePath() . '/simpletest/yml';
+  file_prepare_directory($dir, FILE_CREATE_DIRECTORY);
+  $pre = new YamlPrecompile($dir);
+  $pre->compileCore();
+}
diff --git a/core/tests/Drupal/Tests/Core/Serialization/YamlTest.php b/core/tests/Drupal/Tests/Core/Serialization/YamlTest.php
new file mode 100644
index 0000000..0f1fa19
--- /dev/null
+++ b/core/tests/Drupal/Tests/Core/Serialization/YamlTest.php
@@ -0,0 +1,160 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Tests\Core\Serialization\YamlTest.
+ */
+
+namespace Drupal\Tests\Core\Serialization;
+
+use Drupal\Core\Serialization\YamlSymfony;
+use Drupal\Core\Serialization\YamlPecl;
+use Drupal\Tests\UnitTestCase;
+
+/**
+ * Tests the \Drupal\Core\Serialization\Yaml* implementations.
+ *
+ * @group Drupal
+ * @group Serialization
+ */
+class YamlTest extends UnitTestCase {
+
+  public static function getInfo() {
+    return array(
+      'name' => 'YAML',
+      'description' => "Tests encoding and decoding of YAML is consistent between PECL and Symfony implementations.",
+      'group' => 'Serialization API',
+    );
+  }
+
+  protected function setUp() {
+    if (!extension_loaded('yaml')) {
+      $this->markTestSkipped('The PECL Yaml extension is not available.');
+    }
+  }
+
+  /**
+   * Tests encoding with Symfony and decoding with PECL and vice versa.
+   *
+   * @dataProvider providerYamlData
+   * @covers \Drupal\Core\Serialization\Yaml::encode
+   * @covers \Drupal\Core\Serialization\Yaml::decode
+   * @covers \Drupal\Core\Serialization\YamlPecl::encode
+   * @covers \Drupal\Core\Serialization\YamlPecl::decode
+   * @covers \Drupal\Core\Serialization\YamlSymfony::encode
+   * @covers \Drupal\Core\Serialization\YamlSymfony::decode
+   */
+  public function testEncodeDecode($data, $parser_class, $dumper_class) {
+    $dumper = new $dumper_class;
+    $parser = new $parser_class;
+
+    $dumped = $dumper->encode($data);
+
+    $parsed = $parser->decode($dumped);
+
+    $this->assertEquals($data, $parsed);
+  }
+
+  /**
+   * Tests decoding YAML node anchors with both Symfony and PECL.
+   *
+   * @dataProvider providerYamlNodeAnchors
+   */
+  public function testDecodeNodeAnchors($data) {
+    $symfony = new YamlSymfony();
+    $pecl = new YamlPecl();
+    $this->assertEquals($symfony->decode($data), $pecl->decode($data));
+  }
+
+  /**
+   * Data provider for YAML instance tests.
+   *
+   * @return array
+   */
+  public function providerYamlData() {
+    $object = array(
+      'foo' => 'bar',
+      'id' => 'schnitzel',
+      'ponies' => array('nope', 'thanks'),
+      'how' => array(
+        'about' => 'if',
+        'i' => 'ask',
+        'nicely'
+      ),
+      'the' => array(
+        'answer' => array(
+          'still' => 'would',
+          'be' => 'Y',
+        ),
+      ),
+      'how_many_times' => 123,
+      'should_i_ask' => FALSE,
+      1,
+      FALSE,
+      array(1, FALSE),
+      array(10),
+      array(0 => '123456'),
+    );
+
+    // Test parsing with Symfony and dumping with PECL.
+    $data[] = array(
+      $object,
+      'Drupal\Core\Serialization\YamlSymfony',
+      'Drupal\Core\Serialization\YamlPecl'
+    );
+    // Test parsing with PECL and dumping with Symfony.
+    $data[] = array(
+      $object,
+      'Drupal\Core\Serialization\YamlPecl',
+      'Drupal\Core\Serialization\YamlSymfony'
+    );
+    return $data;
+  }
+
+  /**
+   * Data provider for YAML instance tests.
+   *
+   * @return array
+   */
+  public function providerYamlNodeAnchors() {
+    $yaml = <<<EOF
+jquery.ui:
+  version: &jquery_ui 1.10.2
+
+jquery.ui.accordion:
+  version: *jquery_ui
+EOF;
+    $data[] = array($yaml);
+    return $data;
+  }
+
+  /**
+   * Tests all YAML files are decoded in the same way with both Symfony and PECL.
+   *
+   * @dataProvider providerYamlFilesInCore
+   */
+  public function testYamlFilesInCore($file) {
+    $data = file_get_contents($file);
+    $symfony = new YamlSymfony();
+    $pecl = new YamlPecl();
+    $this->assertEquals($symfony->decode($data), $pecl->decode($data));
+  }
+
+  /**
+   * Data provider for YAML files in core test.
+   * @return array
+   */
+  public function providerYamlFilesInCore() {
+    $files = array();
+    $dirs = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator(__DIR__ . '/../../../../../', \RecursiveDirectoryIterator::FOLLOW_SYMLINKS));
+    foreach ($dirs as $dir) {
+      $pathname = $dir->getPathname();
+      // Exclude vendor.
+      if ($dir->getExtension() == 'yml' && strpos($pathname, '/../../../../../vendor') === FALSE) {
+        $files[] = array($dir->getRealPath());
+      }
+    }
+    return $files;
+  }
+
+}
