如何通过Python模块全局初始化避免延迟?

2024-09-28 21:55:27 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图优化用python编写的web应用程序的一般加载时间。我的应用程序使用了很多模块,其中有些模块可能对给定的请求实际需要,也可能不需要。在

由于页面加载时间是最终用户感知到的站点质量的一个重要因素,所以我试图减少加载可能不必要的模块的影响,尤其是减少初始化可能根本不需要的全局变量所需的时间(和内存)。在

简单地说,我的目标是:

  1. 尽可能减少模块初始化时间(而不是CPU使用率)。在
  2. 减少不需要全局变量占用的内存。在

下面是一个简单的模块示例:

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

Tags: 模块incacheforreturndef时间range
1条回答
网友
1楼 · 发布于 2024-09-28 21:55:27

import语句执行该模块,因此不应更改其语义。在

把import语句塞进需要它们的函数或方法中怎么样?这样,它们只会在需要时发生,而不是在应用程序启动时。在

全局变量也一样,可以将它们转换为类静态或其他东西。不管怎么说,拥有大量的全球数据都是不好的风格。在

但为什么这甚至是个问题?你真的包含了这么多模块,只是找到它们会减慢速度,还是包含的一些包进行了大量昂贵的初始化(例如,打开连接)?我的钱在第二个。如果您已经编写了负责减慢速度的模块,请考虑将初始化包装到适当的构造函数中。在

相关问题 更多 >