diff --git a/django/template/defaultfilters.py b/django/template/defaultfilters.py
index 1500a05..3d1bff4 100644
--- a/django/template/defaultfilters.py
+++ b/django/template/defaultfilters.py
@@ -706,7 +706,7 @@ def date(value, arg=None):
         arg = settings.DATE_FORMAT
     try:
         return formats.date_format(value, arg)
-    except AttributeError:
+    except (AttributeError, UnicodeEncodeError):
         try:
             return format(value, arg)
         except AttributeError:
@@ -722,7 +722,7 @@ def time(value, arg=None):
         arg = settings.TIME_FORMAT
     try:
         return formats.time_format(value, arg)
-    except AttributeError:
+    except (AttributeError, UnicodeEncodeError):
         try:
             return dateformat.time_format(value, arg)
         except AttributeError:
diff --git a/django/utils/encoding.py b/django/utils/encoding.py
index e2d7249..9301419 100644
--- a/django/utils/encoding.py
+++ b/django/utils/encoding.py
@@ -58,6 +58,11 @@ def force_unicode(s, encoding='utf-8', strings_only=False, errors='strict'):
 
     If strings_only is True, don't convert (some) non-string-like objects.
     """
+    # Handle the common case first, saves 30-40% in performance when s
+    # is an instance of unicode. This function gets called often in that
+    # setting.
+    if isinstance(s, unicode):
+        return s
     if strings_only and is_protected_type(s):
         return s
     try:
diff --git a/django/utils/formats.py b/django/utils/formats.py
index 372998f..69c9fed 100644
--- a/django/utils/formats.py
+++ b/django/utils/formats.py
@@ -7,14 +7,32 @@ from django.utils.importlib import import_module
 from django.utils.encoding import smart_str
 from django.utils import dateformat, numberformat, datetime_safe
 
+# These constants are here so that we don't need to construct a new string 
+# every time x_format is called.
+DECIMAL_SEPARATOR = 'DECIMAL_SEPARATOR'
+NUMBER_GROUPING = 'NUMBER_GROUPING'
+THOUSAND_SEPARATOR = 'THOUSAND_SEPARATOR'
+DATE_FORMAT = 'DATE_FORMAT'
+TIME_FORMAT = 'TIME_FORMAT'
+DATETIME_FORMAT = 'DATETIME_FORMAT'
+DATE_INPUT_FORMATS = 'DATE_INPUT_FORMATS'
+TIME_INPUT_FORMATS = 'TIME_INPUT_FORMATS'
+DATETIME_INPUT_FORMATS = 'DATETIME_INPUT_FORMATS'
+
+# format_cache is a mapping from (format_type, lang) to the format string.
+# By using the cache, it is possible to avoid running get_format_modules
+# repeatedly.
+_format_cache = {}
+
 def get_format_modules(reverse=False):
     """
     Returns an iterator over the format modules found in the project and Django
     """
+    lang = get_language()
     modules = []
-    if not check_for_language(get_language()) or not settings.USE_L10N:
+    if not check_for_language(lang) or not settings.USE_L10N:
         return modules
-    locale = to_locale(get_language())
+    locale = to_locale(lang)
     if settings.FORMAT_MODULE_PATH:
         format_locations = [settings.FORMAT_MODULE_PATH + '.%s']
     else:
@@ -34,19 +52,28 @@ def get_format_modules(reverse=False):
         modules.reverse()
     return modules
 
-def get_format(format_type):
+def get_format(format_type, lang=None):
     """
     For a specific format type, returns the format for the current
     language (locale), defaults to the format in the settings.
     format_type is the name of the format, e.g. 'DATE_FORMAT'
     """
-    format_type = smart_str(format_type)
+    global _format_cache
     if settings.USE_L10N:
-        for module in get_format_modules():
-            try:
-                return getattr(module, format_type)
-            except AttributeError:
-                pass
+        if lang is None:
+            lang = get_language()
+        try:
+            return _format_cache[(format_type, lang)] \
+                or getattr(settings, format_type)
+        except KeyError:
+	    for module in get_format_modules():
+	        try:
+		    val = getattr(module, format_type)
+		    _format_cache[(format_type, lang)] = val
+		    return val
+	        except AttributeError:
+		    pass
+	    _format_cache[(format_type, lang)] = None
     return getattr(settings, format_type)
 
 def date_format(value, format=None):
@@ -54,24 +81,27 @@ def date_format(value, format=None):
     Formats a datetime.date or datetime.datetime object using a
     localizable format
     """
-    return dateformat.format(value, get_format(format or 'DATE_FORMAT'))
+    return dateformat.format(value, get_format(format or DATE_FORMAT))
 
 def time_format(value, format=None):
     """
     Formats a datetime.time object using a localizable format
     """
-    return dateformat.time_format(value, get_format(format or 'TIME_FORMAT'))
+    return dateformat.time_format(value, get_format(format or TIME_FORMAT))
 
 def number_format(value, decimal_pos=None):
     """
     Formats a numeric value using localization settings
     """
+    lang = None
+    if settings.USE_I18N:
+        lang = get_language()
     return numberformat.format(
         value,
-        get_format('DECIMAL_SEPARATOR'),
+        get_format(DECIMAL_SEPARATOR, lang),
         decimal_pos,
-        get_format('NUMBER_GROUPING'),
-        get_format('THOUSAND_SEPARATOR'),
+        get_format(NUMBER_GROUPING, lang),
+        get_format(THOUSAND_SEPARATOR, lang),
     )
 
 def localize(value):
@@ -82,11 +112,11 @@ def localize(value):
     if isinstance(value, (decimal.Decimal, float, int)):
         return number_format(value)
     elif isinstance(value, datetime.datetime):
-        return date_format(value, 'DATETIME_FORMAT')
+        return date_format(value, DATETIME_FORMAT)
     elif isinstance(value, datetime.date):
         return date_format(value)
     elif isinstance(value, datetime.time):
-        return time_format(value, 'TIME_FORMAT')
+        return time_format(value, TIME_FORMAT)
     else:
         return value
 
@@ -99,14 +129,14 @@ def localize_input(value, default=None):
         return number_format(value)
     if isinstance(value, datetime.datetime):
         value = datetime_safe.new_datetime(value)
-        format = smart_str(default or get_format('DATETIME_INPUT_FORMATS')[0])
+        format = smart_str(default or get_format(DATETIME_INPUT_FORMATS)[0])
         return value.strftime(format)
     elif isinstance(value, datetime.date):
         value = datetime_safe.new_date(value)
-        format = smart_str(default or get_format('DATE_INPUT_FORMATS')[0])
+        format = smart_str(default or get_format(DATE_INPUT_FORMATS)[0])
         return value.strftime(format)
     elif isinstance(value, datetime.time):
-        format = smart_str(default or get_format('TIME_INPUT_FORMATS')[0])
+        format = smart_str(default or get_format(TIME_INPUT_FORMATS)[0])
         return value.strftime(format)
     return value
 
@@ -116,14 +146,14 @@ def sanitize_separators(value):
     thousand separator setting. Used with form field input.
     """
     if settings.USE_L10N:
-        decimal_separator = get_format('DECIMAL_SEPARATOR')
+        decimal_separator = get_format(DECIMAL_SEPARATOR)
         if isinstance(value, basestring):
             parts = []
             if decimal_separator in value:
                 value, decimals = value.split(decimal_separator, 1)
                 parts.append(decimals)
             if settings.USE_THOUSAND_SEPARATOR:
-                parts.append(value.replace(get_format('THOUSAND_SEPARATOR'), ''))
+                parts.append(value.replace(get_format(THOUSAND_SEPARATOR), ''))
             else:
                 parts.append(value)
             value = '.'.join(reversed(parts))
diff --git a/django/utils/numberformat.py b/django/utils/numberformat.py
index 129c27f..d6dbef8 100644
--- a/django/utils/numberformat.py
+++ b/django/utils/numberformat.py
@@ -1,4 +1,6 @@
 from django.conf import settings
+from django.utils.safestring import mark_safe
+
 
 def format(number, decimal_sep, decimal_pos, grouping=0, thousand_sep=''):
     """
@@ -11,15 +13,20 @@ def format(number, decimal_sep, decimal_pos, grouping=0, thousand_sep=''):
     * thousand_sep: Thousand separator symbol (for example ",")
 
     """
+    use_grouping = settings.USE_L10N and settings.USE_THOUSAND_SEPARATOR \
+                   and grouping
+    # Make the common case fast:
+    if isinstance(number, int) and not use_grouping and not decimal_pos:
+        return mark_safe(unicode(number))
     # sign
     if float(number) < 0:
         sign = '-'
     else:
         sign = ''
-    # decimal part
     str_number = unicode(number)
     if str_number[0] == '-':
         str_number = str_number[1:]
+    # decimal part
     if '.' in str_number:
         int_part, dec_part = str_number.split('.')
         if decimal_pos:
@@ -30,13 +37,12 @@ def format(number, decimal_sep, decimal_pos, grouping=0, thousand_sep=''):
         dec_part = dec_part + ('0' * (decimal_pos - len(dec_part)))
     if dec_part: dec_part = decimal_sep + dec_part
     # grouping
-    if settings.USE_L10N and settings.USE_THOUSAND_SEPARATOR and grouping:
+    if use_grouping:
         int_part_gd = ''
         for cnt, digit in enumerate(int_part[::-1]):
             if cnt and not cnt % grouping:
                 int_part_gd += thousand_sep
             int_part_gd += digit
         int_part = int_part_gd[::-1]
-
     return sign + int_part + dec_part
 
