diff --git a/ldapserver/dn.py b/ldapserver/dn.py
index f291face5d1e1352d9200d26e172dc0c1a5c4b40..76a371f046b1f56fc9d8c65320ec1516f341fa9e 100644
--- a/ldapserver/dn.py
+++ b/ldapserver/dn.py
@@ -16,6 +16,7 @@ Limitations:
 
 import typing
 import re
+import functools
 
 from . import exceptions
 
@@ -45,6 +46,7 @@ class DN(tuple):
 	# distinguishedName = [ relativeDistinguishedName *( COMMA relativeDistinguishedName ) ]
 
 	@classmethod
+	@functools.lru_cache(maxsize=128, typed=False)
 	def from_str(cls, schema, expr):
 		'''Parse string representation of a DN according to RFC 4514
 
diff --git a/ldapserver/rfc4518_stringprep.py b/ldapserver/rfc4518_stringprep.py
index 6e4c93c2a06fff0346de78518c0d06fd5c3658ea..889b94b6a9f2ad1cafd1f6c5b3f84ee61c4ed1e1 100644
--- a/ldapserver/rfc4518_stringprep.py
+++ b/ldapserver/rfc4518_stringprep.py
@@ -1,6 +1,7 @@
 import unicodedata
 import stringprep
 import enum
+import functools
 
 SPACE = 0x0020
 
@@ -159,6 +160,7 @@ class SubstringType(enum.Enum):
 	ANY = enum.auto()
 	FINAL = enum.auto()
 
+@functools.lru_cache(maxsize=128, typed=False)
 def prepare(value, matching_type=MatchingType.EXACT_STRING,
             substring_type=SubstringType.NONE):
 	# Algortihm according to RFC 4518
diff --git a/ldapserver/schema/types.py b/ldapserver/schema/types.py
index 4f3dcee37ec08019e363c7b0384727a03bf667d2..aba3bed5a5df4a77f8e78ba53c808a1ace5f55c6 100644
--- a/ldapserver/schema/types.py
+++ b/ldapserver/schema/types.py
@@ -543,3 +543,6 @@ class Schema(OIDDict):
 		                   matching_rule_definitions=value.matching_rule_definitions,
 		                   attribute_type_definitions=value.attribute_type_definitions,
 		                   object_class_definitions=value.object_class_definitions)
+
+	def __hash__(self):
+		return id(self)