diff --git a/core/includes/common.inc b/core/includes/common.inc
index 7ce1994..7a6571d 100644
--- a/core/includes/common.inc
+++ b/core/includes/common.inc
@@ -2112,6 +2112,11 @@ function _format_date_callback(array $matches = NULL, $new_langcode = NULL) {
  *   A string containing a URL to the given path.
  */
 function url($path = NULL, array $options = array()) {
+  static $rewrite;
+  // Check for url rewrites, which can affect performance.
+  if (!isset($rewrite)) {
+    $rewrite = (bool) count(module_implements('url_outbound_alter'));
+  }
   // Merge in defaults.
   $options += array(
     'fragment' => '',
@@ -2134,8 +2139,27 @@ function url($path = NULL, array $options = array()) {
   // Preserve the original path before altering or aliasing.
   $original_path = $path;
 
-  // Allow other modules to alter the outbound URL and options.
-  drupal_alter('url_outbound', $path, $options, $original_path);
+  // For performance, pass entity data to the alter hook.
+  if (!empty($rewrite)) {
+    if (!isset($options['entity_type'])) {
+      // No great hit here, as this is already cached.
+      $item = menu_get_item($path);
+      // There may be a better way to do this.
+      if (!empty($item['load_functions'])) {
+        $function = current($item['load_functions']);
+        if (substr_count($function, '_load') > 0) {
+          $type = str_replace('_load', '', $function);
+          $info = entity_get_info($type);
+          if (!empty($info)) {
+            $options['entity_type'] = $type;
+            $options['entity'] = current($item['page_arguments']);
+          }
+        }
+      }
+    }
+    // Allow other modules to alter the outbound URL and options.
+    drupal_alter('url_outbound', $path, $options, $original_path);
+  }
 
   if (isset($options['fragment']) && $options['fragment'] !== '') {
     $options['fragment'] = '#' . $options['fragment'];
