Weaviate 不断 运行 内存不足

Weaviate constantly running out of memory

我正在尝试 运行 一个 weaviate 实例,但 运行 遇到内存消耗问题。我在具有 16GB 内存的 docker 容器中使用了 运行ning,在文档中查看它似乎足以容纳超过 100 万条记录(我使用 384 个 dim 向量,就像示例中一样) .

连接到 weaviate 的应用程序不断地插入和查询数据。内存使用量继续上升,直到最终 运行 内存不足并且 docker 容器死亡。这只有大约 20k 条记录。

这是垃圾回收从未发生的问题吗?

更新:

有问题的 weaviate 版本是 1.10.1,目前没有使用任何模块。传入记录已经有向量,因此没有使用向量化器。应用程序根据一些元数据和 nearVector 过滤器搜索与传入记录相似的记录,然后插入传入记录。我将升级到 1.12.1 看看这是否有帮助,但与此同时这里有一些建议的内存测量。

7k 条记录:
docker 内存使用统计:2.56GB / 16GB

gc 1859 @750.550s 0%: 0.33+33+0.058 ms clock, 26+1.2/599/1458+4.6 ms cpu, 2105->2107->1102 MB, 2159 MB goal, 80P
gc 1860 @754.322s 0%: 0.17+34+0.094 ms clock, 13+1.0/644/1460+7.5 ms cpu, 2150->2152->1126 MB, 2205 MB goal, 80P
gc 1861 @758.598s 0%: 0.39+35+0.085 ms clock, 31+1.4/649/1439+6.8 ms cpu, 2197->2199->1151 MB, 2253 MB goal, 80P

11k 条记录:
docker 内存使用统计:5.46GB / 16GB

gc 1899 @991.964s 0%: 1.0+65+0.055 ms clock, 87+9.9/1238/3188+4.4 ms cpu, 4936->4939->2589 MB, 5062 MB goal, 80P
gc 1900 @999.496s 0%: 0.17+58+0.067 ms clock, 13+2.8/1117/3063+5.3 ms cpu, 5049->5052->2649 MB, 5178 MB goal, 80P
gc 1901 @1008.717s 0%: 0.38+65+0.072 ms clock, 30+2.7/1242/3360+5.7 ms cpu, 5167->5170->2710 MB, 5299 MB goal, 80P

17k 条记录:
docker 内存使用统计:11.25GB / 16GB

gc 1932 @1392.757s 0%: 0.37+110+0.019 ms clock, 30+4.6/2130/6034+1.5 ms cpu, 10426->10432->5476 MB, 10694 MB goal, 80P
gc 1933 @1409.740s 0%: 0.14+108+0.052 ms clock, 11+0/2075/5666+4.2 ms cpu, 10679->10683->5609 MB, 10952 MB goal, 80P
gc 1934 @1427.611s 0%: 0.31+116+0.10 ms clock, 25+4.6/2249/6427+8.2 ms cpu, 10937->10942->5745 MB, 11218 MB goal, 80P

20k 条记录:
docker 内存使用统计:15.22GB / 16GB

gc 1946 @1658.985s 0%: 0.13+136+0.077 ms clock, 10+1.1/2673/7618+6.1 ms cpu, 14495->14504->7600 MB, 14866 MB goal, 80P
gc 1947 @1681.090s 0%: 0.28+148+0.045 ms clock, 23+0/2866/8142+3.6 ms cpu, 14821->14829->7785 MB, 15201 MB goal, 80P
GC forced
gc 16 @1700.012s 0%: 0.11+2.0+0.055 ms clock, 8.8+0/20/5.3+4.4 ms cpu, 3->3->3 MB, 7MB goal, 80P
gc 1948 @1703.901s 0%: 0.41+147+0.044 ms clock, 33+0/2870/8153+3.5 ms cpu, 15181->15186->7973 MB, 15570 MB goal, 80P
gc 1949 @1728.327s 0%: 0.29+156+0.048 ms clock, 23+18/3028/8519+3.9 ms cpu, 15548->15553->8168 MB, 15946 MB goal, 80P

pprof

     flat  flat%  sum%          cum   cum%
7438.24MB 96.88% 96.88%   7438.74MB 96.88%  github.com/semi-technologies/weaviate/adapters/repos/db/inverted.(*Searcher).docPointersInvertedNoFrequency.func1
 130.83MB  1.70% 98.58%   7594.13MB 98.91%  github.com/semi-technologies/weaviate/adapters/repos/db/inverted.(*Searcher).DocIDs
      1MB 0.013% 98.59%     40.55MB  0.53%  github.com/semi-technologies/weaviate/adapters/repos/vector/hnsw.(*hnsw).Add
        0     0% 98.59%     65.83MB  0.86%  github.com/go-openapi/runtime/middleware.NewOperationExecutor.func1

更新 2:

升级到1.12.1后问题依然存在

既然你提到它已经在大约 20k 条记录时崩溃,那么 运行 宁 OOM 应该没有理由。此外,在 1M 条记录下,16GB 的内存应该足够了,所以我相信一定还有另一个我们可以发现的原因。

首先我们需要一些关于您的设置的信息:

  1. 您运行正在使用哪个版本的 Weaviate?在撰写此答案时,最新版本是 v1.12.1。请确保使用最新版本以排除您正在 运行 解决任何已修复的问题。
  2. 您 运行正在使用多少个模块以及哪些模块(如果有的话)?这是相关的,因为模块中的模型占用的内存量是恒定的。因此,在极端情况下,模块中的模型使用了 15.5GB 的内存,您只剩下 500MB 给 Weaviate。这不太可能,但我们仍应排除某些可能性。
  3. Docker有限制吗?例如,Docker For Mac 对 Docker 虚拟机使用全局内存限制。它们可能低于 system-wide 限制?是否有任何限制?
  4. 你提到你既在插入又在查询。这应该不是问题,但更精确地了解您的用法可能会有所帮助。也许举例说明您 运行 的请求、写入与读取的比率等。虽然这不太可能是任何问题的原因,但任何其他信息都有助于缩小问题范围。

分析

请使用分析结果更新您的原始 post。

要调查内存问题,我们需要一些配置文件。我们可以从外部(OS 看到什么?)和内部(Go 运行 看到什么)获取它们。这两者之间通常存在差异。这是因为 GC 释放的内存可能还没有释放到 OS。

分析准备

  1. 在 Weaviate 容器上,将名称为 GODEBUG 的环境变量设置为值 gctrace=1。这将使 Go 的垃圾收集器变得冗长并将任何 GC activity 记录到控制台。它会在 运行s 时说出堆前后的情况,以及打印下一个目标大小。
  2. 公开 Weaviate 容器的端口 6060。这将允许从 Go 的分析器中生成调试报告。

分析周期

  1. 启动后(当 API 准备就绪时),运行 docker stats 立即打印整个 docker 设置的内存初始使用情况。这将帮助我们了解每个容器最初使用了多少内存。请将结果添加到您的问题中。

  2. 开始导入。

  3. 定期(例如,如果您预计在 20k 个元素时崩溃,我会从导入的 10k 个元素开始,每 3k 个元素拍摄一次快照),将以下命令的输出保存到单独的文件中

    • docker stats 所以我们看到 OS 的视角
    • Weaviate 容器日志中 gc 配置文件的最后三行

    越接近这些配置文件崩溃的那一刻,它们的意义就越大。

  4. (可选)如果前面的步骤确认堆确实完全用完了,例如接近 16GB 的堆使用量,现在有趣的问题是“堆上有什么东西让它 运行 这么早就出来了?”。这个问题可以通过我们之前暴露的gopprof工具和端口6060来回答。对于这个 you need to install a local Go runtime. Alternatively you can run the commands from within a docker container that has a Go runtime 如果你不想在你的主机上安装 Go。在这种情况下,确保容器可以访问 Weaviate 容器,例如通过将它们放在同一个 Docker 网络中。从开始 运行 时间 运行 以下命令 go tool pprof -top http://localhost:6060/debug/pprof/heap。与第 3 步类似,运行 这条命令离它崩溃的那一刻越近,它的意义就越大。 (请注意,我的示例假设您从主机 运行 宁此,端口 6060 公开 Weaviate 容器的端口 6060。如果您 运行 从另一个容器的 Docker 网络内部宁此相应地调整主机名,例如 http://weaviate:6060/...,等等)

一旦您获得了所有这些配置文件并使用这些配置文件编辑了您的原始 post,我很乐意编辑此 post 并附上一些关于如何解释它们的注释。

总而言之,您应该提供以下工件:

  1. 导入前启动后的docker stats输出
  2. 从接近崩溃的时刻开始,我们需要
    • docker stats
    • 的输出
    • 最后几行来自 Weaviate 容器的 GC 日志
  3. 如果(2)的结果确实确认整个 16GB 都被 Weaviate 用完了,我们需要知道用了什么。我们可以从 pprof 堆配置文件中获取此信息。