Python 中清除 LRU 缓存


在本文中,我们将学习如何在 Python 中清除已实现的 LRU 缓存。在深入代码方面之前,让我们先了解一下什么是 LRU 缓存以及为什么它如此受欢迎。

LRU 缓存,也称为最近最少使用缓存,是一种广泛应用于计算机科学的数据结构,通过减少访问常用数据所需的时间来提高应用程序的性能。LRU 缓存存储有限数量的项目,并在缓存已满时删除最近最少使用的项目。这使得最常用的项目保留在缓存中并快速访问,而不太常用的项目则被删除以腾出空间供新项目使用。

LRU 缓存在与检索数据相关的成本很高的应用程序中特别有用,例如磁盘 I/O 或网络访问。在这些情况下,将常用数据缓存在内存中可以通过减少检索数据所需的昂贵操作次数来显著提高应用程序的性能。

LRU 缓存广泛应用于各种应用程序,包括数据库、Web 服务器、编译器和操作系统。它在需要频繁访问大量数据的应用程序中特别有用,例如搜索引擎和数据分析平台。

在 Python 中与 LRU 缓存交互

在 Python 3.2 及更高版本中,functools 模块包含一个强大的功能,允许程序员与 LRU 缓存交互。此功能可以通过在类或函数定义上方放置一个装饰器来使用。通过将此装饰器应用于需要频繁变量访问和更改的函数,可以显著提高函数的性能。

在处理需要处理大量数据或复杂计算的函数时,使用 LRU 缓存可以大大加快执行时间。这是因为 LRU 缓存将常用数据存储在内存中,允许函数快速访问和处理数据,而无需承担耗时的 I/O 操作的成本。

通过利用 LRU 缓存,Python 程序员可以减少应用程序的执行时间并提高其性能。这在处理大型应用程序或需要实时数据处理的应用程序时尤其重要,即使是性能上的微小改进也会带来巨大的收益。

总之,Python 中的 functools 模块提供了一种强大的机制来与 LRU 缓存交互。通过使用 LRU 缓存,程序员可以通过减少昂贵的变量访问和更改操作所需的时间来提高其应用程序的性能。LRU 缓存的使用在需要实时数据处理或处理大量数据的应用程序中尤其有利。

现在我们对 LRU 缓存有了一些了解,让我们在 Python 中使用它。

Python 中 functools 模块的 cache clear() 方法可用于清除 LRU(最近最少使用)缓存。

使用此技术可以完全清除缓存。

示例代码片段

from functools import lru_cache

@lru_cache(maxsize=128)
def some_function(arg):
	# function implementation
	return result

# clear the cache
some_function.cache_clear()

解释

在上面的示例中,some_function 使用 lru_cache 进行装饰,这将创建一个最大大小为 128 的 LRU 缓存。要清除缓存,可以在函数对象上调用 cache_clear() 方法,这将删除缓存中的所有条目。

请注意,调用 cache_clear() 将清除所有参数的缓存。如果要清除特定参数集的缓存,可以使用其他缓存实现,例如 functools.typed_lru_cache,它允许您使用带参数的 cache_clear() 方法清除特定参数的缓存。

现在让我们使用上面的代码,并编写一个可运行的示例。

考虑以下所示的代码。

示例

from functools import lru_cache

@lru_cache(maxsize=128)
def fibonacci(n):
	"""Return the nth Fibonacci number."""
	if n < 2:
    	return n
	return fibonacci(n-1) + fibonacci(n-2)

# Call the function with some arguments to populate the cache
print(fibonacci(10))  # Output: 55
print(fibonacci(15))  # Output: 610

# Clear the cache
fibonacci.cache_clear()

# Call the function again to see that it's recomputed
print(fibonacci(10))  # Output: 55

解释

在此示例中,fibonacci 函数使用 lru_cache 来记忆其结果。缓存的最大大小为 128,因此该函数将记住最近 128 次调用的结果。

我们首先使用一些参数调用该函数以填充缓存。然后,我们使用 cache_clear() 方法清除缓存。最后,我们再次使用相同的参数调用该函数以查看它是重新计算而不是使用缓存的结果。

要运行上述代码,我们需要运行以下所示的命令。

命令

python3 main.py

运行上述命令后,我们应该期望输出类似于以下所示的输出。

输出

55
610
55

如果需要,我们也可以在上述代码中打印缓存的当前状态信息,为此,我们需要使用 cache_info() 方法。

考虑以下所示的更新代码。

示例

from functools import lru_cache

@lru_cache(maxsize=128)
def fibonacci(n):
	"""Return the nth Fibonacci number."""
	if n < 2:
    	return n
	return fibonacci(n-1) + fibonacci(n-2)

# Call the function with some arguments to populate the cache
print(fibonacci(10))  # Output: 55
print(fibonacci(15))  # Output: 610

print(fibonacci.cache_info())

# Clear the cache
fibonacci.cache_clear()

# Call the function again to see that it's recomputed
print(fibonacci(10))  # Output: 55

print(fibonacci.cache_info())

解释

上面的代码中的 @lru cache 装饰器接受可选参数 maxsize,该参数指定缓存的最大大小。

如果未定义 maxsize,则缓存大小是无限的。

如果缓存已满,则会删除最近最少使用的项目,以便为新项目腾出空间。

@lru cache 使用的缓存位于函数对象本身中。

因此,缓存对函数是私有的,并且不会由函数的其他版本共享。此外,这里不同的部分是 cache_info() 方法,该方法用于打印有关 fibonacci 函数使用的 LRU 缓存的信息。这包括缓存命中和未命中的次数,以及缓存的大小。

要运行上述代码,我们需要运行以下所示的命令。

命令

python3 main.py

运行上述命令后,我们应该期望输出类似于以下所示的输出。

输出

55
610
CacheInfo(hits=14, misses=16, maxsize=128, currsize=16)
55
CacheInfo(hits=8, misses=11, maxsize=128, currsize=11)

现在我们已经了解了如何清除缓存,让我们在另一个示例中使用它。

考虑以下所示的代码。

示例

from functools import lru_cache

@lru_cache(maxsize=128)
def edit_distance(s1, s2):
	"""
	Compute the edit distance between two strings using dynamic programming.
	"""
	if not s1:
    	return len(s2)
	elif not s2:
    	return len(s1)
	elif s1[0] == s2[0]:
    	return edit_distance(s1[1:], s2[1:])
	else:
    	d1 = edit_distance(s1[1:], s2) + 1  # deletion
    	d2 = edit_distance(s1, s2[1:]) + 1  # insertion
    	d3 = edit_distance(s1[1:], s2[1:]) + 1  # substitution
    	return min(d1, d2, d3)

# Call the function with some arguments to populate the cache
print(edit_distance("kitten", "sitting"))  # Output: 3
print(edit_distance("abcde", "vwxyz"))	# Output: 5

# Clear the cache
edit_distance.cache_clear()

# Call the function again to see that it's recomputed
print(edit_distance("kitten", "sitting"))  # Output: 3

解释

在此示例中,edit_distance 函数使用动态规划计算两个字符串之间的编辑距离。该函数是递归的,并具有三个基本情况:如果其中一个字符串为空,则编辑距离是另一个字符串的长度;如果两个字符串的第一个字符相同,则编辑距离是其余字符串之间的编辑距离;否则,编辑距离是三种可能操作的编辑距离的最小值:删除、插入和替换。

为了提高函数的性能,我们使用 lru_cache 来记忆其结果。缓存的最大大小为 128,因此该函数将记住最近 128 次调用的结果。这使我们能够避免为相同的参数重新计算编辑距离。

我们首先使用一些参数调用该函数以填充缓存。然后,我们使用 cache_clear() 方法清除缓存。最后,我们再次使用相同的参数调用该函数以查看它是重新计算而不是使用缓存的结果。

请注意,edit_distance 函数只是一个示例,并且有更有效的方法来计算两个字符串之间的编辑距离(例如,使用 Wagner-Fischer 算法)。此示例的目的是演示如何使用 lru_cache 来记忆递归函数的结果。

结论

总之,在某些情况下,清除 Python 中的 LRU(最近最少使用)缓存对于管理内存并确保缓存保持最新至关重要。LRU 缓存是由 Python 的 functools 模块提供的内置缓存机制,可用于根据函数的参数缓存函数的结果。@lru_cache 装饰器用于为函数启用缓存,并且可以指定 maxsize 来设置缓存大小的限制。

可以使用装饰的函数对象的 cache clear() 方法来清除 LRU 缓存。通过清除所有缓存的结果,此技术使缓存保持最新,同时释放内存。如果函数已更新或输入数据频繁更改,则可能需要清除缓存。

总的来说,LRU 缓存提供了一种简单而有效的方法来提高 Python 函数的性能,尤其是那些计算密集型或多次使用相同参数调用的函数。在必要时清除缓存有助于维持通过缓存获得的性能提升,并确保缓存在减少计算时间方面保持有效。

更新于: 2023年8月2日

10K+ 次浏览

开启您的 职业生涯

通过完成课程获得认证

开始学习
广告