【问题标题】:Preventing multiple loading of large objects in uWSGI workers?防止在uWSGI工作人员中多次加载大对象?
【发布时间】:2015-09-10 22:32:29
【问题描述】:

我有一个非常大的自定义数据结构(类似于 trie,尽管它对问题并不重要),用于访问和提供数据。我现在将我的应用程序移动到 uWSGI 以供生产使用,我绝对不希望每个工作人员都重新加载它。我可以以某种方式在工作进程之间共享它吗?我只加载一次结构,然后通过 apscheduler 每分钟重新加载一次。没有任何工作人员以任何方式修改数据结构。对于此类问题,还有其他更好的解决方案吗?每个工人加载相同的东西是非常浪费的。

【问题讨论】:

    标签: python uwsgi


    【解决方案1】:

    根据数据结构的类型,您可以尝试使用内存映射文件。有一个Python library 封装了相关的系统调用。

    文件的结构需要反映您正在使用的数据结构。例如,如果您需要一个 trie,您可以将所有字符串存储在一个排序列表中,然后对前缀进行二进制搜索以查看哪些字符串具有该前缀。

    当您访问文件中的页面时,它们将通过操作系统的磁盘读取缓存加载到内存中。对同一页面的后续请求将很快。因为磁盘缓存可以在进程之间共享,所有 UWSGI 工作人员都将受益于访问缓存页面的速度。

    我在 Linux 上尝试了这个,强制它在两个单独的进程中扫描一个大文件。创建一个名为“big”的大文件,然后在两个单独的 Python 进程中运行以下命令:

    import mmap
    with open('big') as fp:
        map = mmap.mmap(fp.fileno(), 0, mmap.MAP_PRIVATE)
        if x == 'a':  # Make sure 'a' doesn't occur in the file!
            break
    

    您会注意到两个进程的常驻内存在扫描文件时会增加,但是共享内存使用量也会增加。例如,如果big 是一个 1 GB 的文件,则两个进程似乎都在使用大约 1 GB 的内存。但是,系统上的整体内存负载只会增加 1 GB,而不是 2 GB。

    显然,这种方法存在一些限制,主要是您要共享的数据结构很容易以二进制格式表示。此外,每当您访问它们时,Python 都需要将文件中的任何字节复制到内存中。如果您经常以小块的形式读取整个文件,这可能会导致积极的垃圾收集,或者如果您读取大块,则会破坏内存映射的共享内存优势。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-06-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多