【问题标题】:Caching a function containing some constants, in Django在 Django 中缓存包含一些常量的函数
【发布时间】:2016-10-06 06:14:43
【问题描述】:

在我维护的一个 Django 网站(v 1.7)中,我将每天 24 小时分成不同的时间窗口,然后根据用户登录的时间窗口,我为所述用户处理一些内容。日期无关紧要,重要的是时间窗口。

目前,时间窗口及其相关处理是在我的 views.py 中的一个函数中完成的,如下所示:

from datetime import time as time_object

def WhichWindow(time_now):
    window1_least = time_object(hour=0, minute=0)
    window1_most = time_object(hour=3, minute=0) 
    window2_least = time_object(hour=3, minute=0)
    window2_most = time_object(hour=6, minute=30)
    window3_least = time_object(hour=6, minute=30) 
    window3_most = time_object(hour=11, minute=50)
    window4_least = time_object(hour=11, minute=50)
    window4_most = time_object(hour=14, minute=55)
    window5_least = time_object(hour=14, minute=55)
    window5_most = time_object(hour=16, minute=55)
    window6_least = time_object(hour=16, minute=55)
    window6_most = time_object(hour=20, minute=0)
    window7_least = time_object(hour=20, minute=0)
    window7_most = time_object(hour=0, minute=0)
    if window1_least <= time_now < window1_most:
        variable1 = #something
        variable2 = #something
        variable3 = #something
    elif window2_least <= time_now < window2_most:
        variable1 = #something
        variable2 = #something
        variable3 = #something
    elif window3_least <= time_now < window3_most:
        variable1 = #something
        variable2 = #something
        variable3 = #something
    elif window4_least <= time_now < window4_most:
        variable1 = #something
        variable2 = #something
        variable3 = #something
    elif window5_least <= time_now < window5_most:
        variable1 = #something
        variable2 = #something
        variable3 = #something
    elif window6_least <= time_now < window6_most:
        variable1 = #something
        variable2 = #something
        variable3 = #something
    elif window7_least <= time_now < window7_most:
        variable1 = #something
        variable2 = #something
        variable3 = #something
    else:
        variable1 = #something
        variable2 = #something
        variable3 = #something
    return variable1, variable2, variable3

注意:函数中的time_now本质上是datetime.now().time()

每个用户都非常频繁地访问上述功能。我觉得如果我 cache 我的时间窗口定义,这将是一个性能提升。

我该怎么办?我是否应该在此函数之上简单地添加 @cache_page(60 * 60 * 24) 装饰器?我觉得如果我这样做,那也会缓存这个函数的结果,而我只想缓存时间窗口定义。所以我该怎么做?

请提供实现此目的的最佳执行方式,并提供说明性示例。我是一个新手,并且仍然围绕着这些概念中的大多数。

【问题讨论】:

  • “这也会缓存这个函数的结果”……是的,这就是缓存的作用。不想缓存结果,怎么缓存函数?
  • @syntonym:我只想缓存时间窗口定义。它们是静态的,不会改变。
  • 然后您可以将它们移出模块中的函数(或者,如果您愿意,可以移出不同的模块或类)。
  • 函数做一些事情,因为你有一些静态数据。你应该把它放在静态的地方,而不是创建一个函数并缓存它。

标签: python django performance caching


【解决方案1】:

如果您确实需要提高性能,您应该考虑重新组织窗口,因为它们是从午夜开始检查的(这可能不是您拥有最多流量的时间)。

只是提供第二种方法,您可以这样做:

from datetime import datetime, time

windows = {}

window1_least = time(hour=0, minute=0)
window1_most = time(hour=3, minute=0)
window2_least = time(hour=3, minute=0)
window2_most = time(hour=6, minute=30)
window3_least = time(hour=6, minute=30)
window3_most = time(hour=11, minute=50)
window4_least = time(hour=11, minute=50)
window4_most = time(hour=14, minute=55)
window5_least = time(hour=14, minute=55)
window5_most = time(hour=16, minute=55)
window6_least = time(hour=16, minute=55)
window6_most = time(hour=20, minute=0)
window7_least = time(hour=20, minute=0)
window7_most = time(hour=0, minute=0)


def which_window(minutes):
    hour = minutes // 60
    minute = minutes % 60
    curent_time = time(hour=hour, minute=minute)
    if window1_least <= curent_time < window1_most:
        return 1
    elif window2_least <= curent_time < window2_most:
        return 2
    elif window3_least <= curent_time < window3_most:
        return 3
    elif window4_least <= curent_time < window4_most:
        return 4
    elif window5_least <= curent_time < window5_most:
        return 5
    elif window6_least <= curent_time < window6_most:
        return 6
    elif window7_least <= curent_time < window7_most:
        return 7


windows = {minute: which_window(minute) for minute in range(1440)}

def get_current_window():
    current_minute = datetime.now().hour * 60 + datetime.now().minute
    return windows[current_minute]

# Just for testing
print get_current_window()

通过这种方式,您正在创建一个长字典来保存一天中的每一分钟,但它会发生一次(当服务器启动时),然后您的性能会好得多,O(1),因为您是使用字典。

一旦你有了这个,你可以根据需要创建一个 1k 的窗口,检查将保持“即时”

【讨论】:

    【解决方案2】:

    如果声明是静态的,您可以将它们放在函数之外。因此,它们不会在每次函数运行时都被执行:

    from datetime import time as time_object
    
    
    window1_least = time_object(hour=0, minute=0)
    window1_most = time_object(hour=3, minute=0) 
    window2_least = time_object(hour=3, minute=0)
    window2_most = time_object(hour=6, minute=30)
    window3_least = time_object(hour=6, minute=30) 
    window3_most = time_object(hour=11, minute=50)
    window4_least = time_object(hour=11, minute=50)
    window4_most = time_object(hour=14, minute=55)
    window5_least = time_object(hour=14, minute=55)
    window5_most = time_object(hour=16, minute=55)
    window6_least = time_object(hour=16, minute=55)
    window6_most = time_object(hour=20, minute=0)
    window7_least = time_object(hour=20, minute=0)
    window7_most = time_object(hour=0, minute=0)
    
    
    def WhichWindow(time_now):
    
        if window1_least <= time_now < window1_most:
            variable1 = #something
            variable2 = #something
            variable3 = #something
        elif window2_least <= time_now < window2_most:
            variable1 = #something
            variable2 = #something
            variable3 = #something
        elif window3_least <= time_now < window3_most:
            variable1 = #something
            variable2 = #something
            variable3 = #something
        elif window4_least <= time_now < window4_most:
            variable1 = #something
            variable2 = #something
            variable3 = #something
        elif window5_least <= time_now < window5_most:
            variable1 = #something
            variable2 = #something
            variable3 = #something
        elif window6_least <= time_now < window6_most:
            variable1 = #something
            variable2 = #something
            variable3 = #something
        elif window7_least <= time_now < window7_most:
            variable1 = #something
            variable2 = #something
            variable3 = #something
        else:
            variable1 = #something
            variable2 = #something
            variable3 = #something
        return variable1, variable2, variable3
    

    当然你也可以把它们放在模块、类、列表中……

    通过 PEP8 模块级别的常量应该是大写的。

    【讨论】:

    • 我明白了,您的意思是将它们定义为全局变量。那么当我在类或函数内部使用这些全局定义时,我应该先声明global window1_leastglobal_window1_most等等?
    • 不需要重新声明,直接使用即可
    • 如果你想写入它们,你只需要 global 关键字(因为否则写入的值将在当前范围而不是全局范围内)。因为你只阅读它们,所以不需要全局。
    猜你喜欢
    • 1970-01-01
    • 2012-05-19
    • 2011-06-22
    • 1970-01-01
    • 2022-01-16
    • 2015-05-31
    • 1970-01-01
    • 1970-01-01
    • 2019-05-24
    相关资源
    最近更新 更多