我试图优化用python编写的web应用程序的一般加载时间。我的应用程序使用了很多模块,其中有些模块可能对给定的请求实际需要,也可能不需要。在
由于页面加载时间是最终用户感知到的站点质量的一个重要因素,所以我试图减少加载可能不必要的模块的影响,尤其是减少初始化可能根本不需要的全局变量所需的时间(和内存)。在
简单地说,我的目标是:
下面是一个简单的模块示例:
COMMON = set(('alice', 'has', 'cat', 'with', 'blue', 'eyes'))
为COMMON
构建集合需要时间—如果COMMON
将不被使用,那将浪费加载时间和内存。
显然,对于单个模块/全局,成本可以忽略不计,但是如果有100个变量的100个模块,会怎么样?在
加快速度的一种方法是这样延迟初始化:
^{pr2}$它节省了加载时间和内存,牺牲了一些CPU。在
我尝试了其他一些技术(见下文),其中两种比上面的简单缓存快一些。在
是否还有其他技术可以用来进一步减少模块和全局参数的加载时间,而这些模块和全局参数可能无法用于给定的请求?
到目前为止,我尝试过的方法需要Python2.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'
在Python2.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
import语句执行该模块,因此不应更改其语义。在
把import语句塞进需要它们的函数或方法中怎么样?这样,它们只会在需要时发生,而不是在应用程序启动时。在
全局变量也一样,可以将它们转换为类静态或其他东西。不管怎么说,拥有大量的全球数据都是不好的风格。在
但为什么这甚至是个问题?你真的包含了这么多模块,只是找到它们会减慢速度,还是包含的一些包进行了大量昂贵的初始化(例如,打开连接)?我的钱在第二个。如果您已经编写了负责减慢速度的模块,请考虑将初始化包装到适当的构造函数中。在
相关问题 更多 >
编程相关推荐