我有一个非常大的自定义数据结构(类似于trie,虽然这对问题并不重要)我正在使用它来访问和提供数据。我正在将我的应用程序移动到uWSGI以供生产使用,我绝对不希望每个工人重新加载。我可以以某种方式在工作进程之间共享它吗?我只需加载一次结构,然后通过apscheduler每分钟重新加载一次。没有任何工作人员以任何方式修改数据结构。还有另一种更好的解决方案可以解决这类问题吗?每个工人加载相同的东西是非常浪费的。
答案 0 :(得分:0)
根据数据结构的类型,您可以尝试使用内存映射文件。有一个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需要在您访问它们时将文件中的任何字节复制到内存中。如果您经常以小块读取整个文件,这会导致积极的垃圾收集,或者如果您阅读大块文件,则会破坏内存映射的共享内存优势。