我正在尝试优化用 python 编写的 Web 应用程序的一般加载时间。我的应用程序使用了很多模块,其中一些模块对于给定的请求可能实际需要也可能不需要。
由于页面加载时间是最终用户感知网站质量的重要因素,因此我试图减少加载可能不必要的模块的影响 - 特别是尝试减少初始化全局变量所需的时间(和内存)可能根本不需要。
简单地说,我的目标是:
- 尽可能减少模块初始化时间(不是 CPU 使用率)。
- 减少不需要的全局变量占用的内存。
为了说明,这是一个简单的模块示例:
COMMON = set(('alice', 'has', 'cat', 'with', 'blue', 'eyes'))
构建集合需要时间COMMON
- 如果COMMON
不使用,那会浪费加载时间和内存。
显然对于单个模块/全局,成本可以忽略不计,但是如果您有100 个模块和 100 个变量怎么办?
一种加快速度的方法是延迟初始化,如下所示:
__cache_common = None
def getCommon():
global __cache_common
# not use before
if __cache_common is None:
__cache_common = set(('alice', 'has', 'cat', 'with', 'blue', 'eyes'))
# get cached value
return __cache_common
它节省了加载时间和内存,牺牲了一些 CPU。
我尝试了其他一些技术(见下文),其中两种比上面的简单缓存要快一些。
我可以使用另一种技术来进一步减少可能不会在给定请求上使用的模块和全局变量的加载时间吗?
到目前为止我尝试过的方法需要 Python 2.6+:
from timeit import Timer
__repeat = 1000000
__cache = None
def getCache():
return __cache
def getCacheTest():
for i in range(__repeat):
getCache()
def getLocal():
return set(('alice', 'has', 'cat', 'with', 'blue', 'eyes'))
def getLocalTest():
for i in range(__repeat):
getLocal()
def getLazyIf():
global __cache
if __cache is None:
__cache = getLocal()
return __cache
def getLazyIfTest():
for i in range(__repeat):
getLazyIf()
def __realLazy():
return __cache
def getLazyDynamic():
global __cache, getLazyDynamic
__cache = getLocal()
getLazyDynamic = __realLazy
return __cache
def getLazyDynamicTest():
for i in range(__repeat):
getLazyDynamic()
def getLazyDynamic2():
global __cache, getLazyDynamic2
__cache = getLocal()
def __realLazy2():
return __cache
getLazyDynamic2 = __realLazy2
return __cache
def getLazyDynamic2Test():
for i in range(__repeat):
getLazyDynamic2()
print sum(Timer(getCacheTest).repeat(3, 1)), getCacheTest, 'raw access'
print sum(Timer(getLocalTest).repeat(3, 1)), getLocalTest, 'repeat'
print sum(Timer(getLazyIfTest).repeat(3, 1)), getLazyIfTest, 'conditional'
print sum(Timer(getLazyDynamicTest).repeat(3, 1)), getLazyDynamicTest, 'hook'
print sum(Timer(getLazyDynamic2Test).repeat(3, 1)), getLazyDynamic2Test, 'scope hook'
使用 Python 2.7,我得到了这些时间(最好的是没有范围的钩子):
1.01902420559 <function getCacheTest at 0x012AE170> raw access
5.40701374057 <function getLocalTest at 0x012AE1F0> repeat
1.39493902158 <function getLazyIfTest at 0x012AE270> conditional
1.06692051643 <function getLazyDynamicTest at 0x012AE330> hook
1.15909591862 <function getLazyDynamic2Test at 0x012AE3B0> scope hook