Index: trac/ticket/api.py
===================================================================
--- trac/ticket/api.py	(revision 5545)
+++ trac/ticket/api.py	(working copy)
@@ -15,6 +15,10 @@
 # Author: Jonas Borgström <jonas@edgewall.com>
 
 import re
+try:
+    import threading
+except ImportError:
+    import dummy_threading as threading
 
 from trac.config import *
 from trac.core import *
@@ -68,6 +72,9 @@
         [TracTickets#Assign-toasDrop-DownList Assign-to as Drop-Down List]
         (''since 0.9'').""")
 
+    def __init__(self):
+         self._fields_lock = threading.RLock()
+  
     # Public API
 
     def get_available_actions(self, ticket, perm_):
@@ -85,6 +92,18 @@
 
     def get_ticket_fields(self):
         """Returns the list of fields available for tickets."""
+        # This is now cached - as it makes quite a number of things faster,
+        # e.g. #6436
+        if self._fields is None:
+            self._fields_lock.acquire()
+            try:
+                self._fields = self._get_ticket_fields()
+            finally:
+                self._fields_lock.release()
+        return [f.copy() for f in self._fields]
+
+    _fields = None
+    def _get_ticket_fields(self):
         from trac.ticket import model
 
         db = self.env.get_db_cnx()
@@ -155,6 +174,16 @@
         return fields
 
     def get_custom_fields(self):
+        if self._custom_fields is None:
+            self._fields_lock.acquire()
+            try:
+                self._custom_fields = self._get_custom_fields()
+            finally:
+                self._fields_lock.release()
+        return [f.copy() for f in self._custom_fields]
+
+    _custom_fields = None
+    def _get_custom_fields(self):
         fields = []
         config = self.config['ticket-custom']
         for name in [option for option, value in config.options()
