2

我正在从 PHP 切换到 Python + Django 并寻找相当于 PHP 的“数组缓存”的过程。

对于来自数据库的小型数据集,例如很少更改但经常访问的“类别”,我使用的是数组缓存。

http://www.mysqlperformanceblog.com/2006/08/09/cache-performance-comparison/

它的概念是使用类别树生成 PHP 源代码,当打开操作码时,它就像将数据嵌入到应用程序源中一样工作。它是可以想象到的最快的缓存,对于大负载非常有帮助。

Django 手册(https://docs.djangoproject.com/en/1.4/topics/cache/)指出:

到目前为止,Django 可用的最快、最有效的缓存类型 Memcached..

所以问题是:

  • 使用 python 字典/列表生成 .py 文件是否有意义?
  • 这会比 Memcached 快吗?如果不是为什么?
  • 是否有任何已知的实现?
  • Python 是否有类似 PHP 的 var_export() 函数?

编辑:

正如答案中所指出的,我可以使用 repr() 并且可以轻松地进行基准测试,因此我创建了一个简单的基准:

https://github.com/fsw/pythonCachesBenchmark

这个在我的本地机器上的输出是:

FIRST RUN
get_categories_from_db
6.57282209396
get_categories_from_memcached
(SET CACHE IN 0.000940)
4.88948512077
get_categories_from_pickledfile
(SET CACHE IN 0.000917)
2.87856888771
get_categories_from_pythonsrc
(SET CACHE IN 0.000489)
0.0930788516998
SECOND RUN
get_categories_from_db
6.63035202026
get_categories_from_memcached
4.60877108574
get_categories_from_pickledfile
2.87137699127
get_categories_from_pythonsrc
0.0903170108795

get_categories_from_pythonsrc 是我所说的 PHP 数组缓存的简单实现:

def get_categories_from_pythonsrc():
    if not os.path.exists('catcache.py'):
        start = time.time()
        f = open( 'catcache.py', 'wb' )
        categories = get_categories_from_db()
        f.write('x = ' + repr(categories))
        f.close()
        print '(SET CACHE IN %f)' % (time.time() - start)
    import catcache
    return catcache.x

这是我简单的pickledfile缓存实现:

def get_categories_from_pickledfile():
    path = 'catcache.p'
    if not os.path.exists(path):
        start = time.time()
        pickle.dump( get_categories_from_db(), open( path, 'wb' ) )
        print '(SET CACHE IN %f)' % (time.time() - start)
    return pickle.load(open( path, 'rb' ));

完整来源:

https://github.com/fsw/pythonCachesBenchmark/blob/master/test.py

稍后我将在此基准测试中添加“Django 的低级缓存 API”,以了解它们的含义。

所以我的直觉建议在 python .py 文件中缓存字典是我能得到的最快方法(比 cPickle + 文件快 30 倍以上)

如前所述,我是 Python 新手,所以我可能在这里遗漏了一些东西?

如果不是:为什么这个解决方案没有被广泛使用?

4

2 回答 2

1

还有另一种方法。您可以使用一些ASYNC 服务器,如 gevent,并在一些全局命名空间中拥有活动对象。
我不知道你对这样的工作流程有多熟悉,它不同于 apache/php “每个请求都开始裸露”。

基本上,您加载您的应用程序,并使用它来处理请求。如果没有请求,它一直处于活动状态并且正在休眠。从数据库加载“类别”后,将它们存储在全局变量或某个模块中。

假设您启动 WSGI 实例并将其命名为 app。之后,您可以在该应用程序中拥有字典并在那里存储缓存。所以没有序列化、网络协议,所有数据都直接在 RAM 中可用。

EDIT1:不要经常使用全局变量,这只是非常罕见的情况之一,可以在global命名空间中存储一些东西(在我看来)。

于 2013-02-05T22:22:34.990 回答
1

Python 有几种可能在这里工作的解决方案:

  • Memcached(如您所知),
  • 泡菜(正如 Blender 提到的) - 当然可以与例如一起使用。内存缓存,
  • 其他几种缓存(例如,用于本地内存)和序列化(例如simplejson)解决方案,

通常pickle非常快(cPickle如果您需要更快的速度,请使用),并且在 Python 中您不需要类似的东西var_export()(尽管您可以使用repr()变量来获得有效的文字,如果它们是原始类型之一)。pickle在 Python 中更类似于serialize在 PHP 中。

你的问题不是很具体,但上面应该给你一些见解。您还需要考虑到 PHP 和 Python 有不同的理念,因此相同问题的解决方案可能看起来不同。在这种特定情况下pickle,模块应该可以解决您的问题。

于 2013-02-05T20:57:29.970 回答