我在应用引擎中的各种请求处理程序中偶尔遇到Exceeded soft private memory limit
错误。我知道这个错误意味着实例使用的RAM超过了分配的数量,以及它如何导致实例关闭。
我想了解可能导致错误的原因,并且首先,我想了解app引擎python实例应该如何管理内存。我的基本假设是:
我如何推测它会起作用,但鉴于我偶尔会 / em>请求处理程序,我现在不太确定。我的问题是:
a)第4步会发生吗?
b)什么可能导致它不发生?还是不完全发生?例如请求之间的内存如何泄漏?c)模块级变量中的存储是否会导致内存使用泄漏? (我不是故意以这种方式使用模块级变量)
d)我可以使用哪些工具/技术来获取更多数据?例如。测量请求处理程序的入口处的内存使用情况?
在答案/评论中,如果可能,请链接到gae文档。
[edit]额外信息:我的应用被归为threadsafe: false
。如果这与答案有关,请说明它是什么。我打算很快换到threadsafe: true
。
[edit] 澄清:此问题是关于内存管理的gae的预期行为。因此,像“gc.collect()
'可能是相关问题的部分解决方案,他们没有完全回答这个问题。直到我理解gae预期会如何表现为止,使用gc.collect()
对我来说就像伏都教编程一样。
最后:如果我把这一切都倒退了,那么我会提前道歉 - 我真的找不到有用的信息,所以我大多猜测......
答案 0 :(得分:3)
gc
仅用于处理垃圾周期 - 当一堆对象永远不会将其引用计数降低到零,因为它们相互引用即使没有可访问外部引用它们。)
因此,记忆很容易泄漏" (在实践中,虽然技术上它不是泄漏)"请求之间"如果你使用任何全局变量 - 所述变量将在处理程序类的实例及其(例如)get
方法中存活 - 即你的点(c),尽管你说你没有这样做。
将模块声明为threadsafe
后,实例可能会同时为多个请求提供服务(直到您在max_concurrent_requests
部分automatic_scaling
部分设置为.yaml
您的模块的instance_class
配置文件;默认值为8)。因此,您的实例的RAM需要是每个请求所需的倍数。
至于(d),到"获得更多数据" (我想你实际上意味着,获得更多内存),你唯一能做的就是为需要内存的模块配置一个更大的ndb
。
要使用更少的内存,有许多技术 - 与App Engine无关,与Python有关,特别是与您的特定代码及其相关的一切非常具体的需求。
我能想到的一个GAE特定问题是ndb
的缓存已被报告泄露 - 请参阅https://code.google.com/p/googleappengine/issues/detail?id=9610;该线程还建议了解决方法,例如关闭db
缓存或移动到旧ndb
(没有缓存且没有泄漏)。如果你正在使用var deck = [
{card: "Two of Clubs", value: 2},
{card: "Three of Clubs", value: 3},
{card: "Four of Clubs", value: 4},
{card: "Five of Clubs", value: 5},
{card: "Six of Clubs", value: 6},
{card: "Seven of Clubs", value: 7},
{card: "Eight of Clubs", value: 8},
{card: "Nine of Clubs", value: 9},
{card: "Ten of Clubs", value: 10},
{card: "Jack of Clubs", value: 10},
{card: "Queen of Clubs", value: 10},
{card: "King of Clubs", value: 10},
{card: "Ace of Clubs", value: 11},
{card: "Two of Hearts", value: 2},
{card: "Three of Hearts", value: 3},
{card: "Four of Hearts", value: 4},
{card: "Five of Hearts", value: 5},
{card: "Six of Hearts", value: 6},
{card: "Seven of Hearts", value: 7},
{card: "Eight of Hearts", value: 8},
{card: "Nine of Hearts", value: 9},
{card: "Ten of Hearts", value: 10},
{card: "Jack of Hearts", value: 10},
{card: "Queen of Hearts", value: 10},
{card: "King of Hearts", value: 10},
{card: "Ace of Hearts", value: 11},
{card: "Two of Spades", value: 2},
{card: "Three of Spades", value: 3},
{card: "Four of Spades", value: 4},
{card: "Five of Spades", value: 5},
{card: "Six of Spades", value: 6},
{card: "Seven of Spades", value: 7},
{card: "Eight of Spades", value: 8},
{card: "Nine of Spades", value: 9},
{card: "Ten of Spades", value: 10},
{card: "Jack of Spades", value: 10},
{card: "Queen of Spades", value: 10},
{card: "King of Spades", value: 10},
{card: "Ace of Spades", value: 11},
{card: "Two of Diamonds", value: 2},
{card: "Three of Diamonds", value: 3},
{card: "Four of Diamonds", value: 4},
{card: "Five of Diamonds", value: 5},
{card: "Six of Diamonds", value: 6},
{card: "Seven of Diamonds", value: 7},
{card: "Eight of Diamonds", value: 8},
{card: "Nine of Diamonds", value: 9},
{card: "Ten of Diamonds", value: 10},
{card: "Jack of Diamonds", value: 10},
{card: "Queen of Diamonds", value: 10},
{card: "King of Diamonds", value: 10},
{card: "Ace of Diamonds", value: 11}
]
function draw(i) {
var drawn = i[Math.floor(Math.random()*i.length)];
// console.log(drawn);
return drawn; // you need to return something!!!
}
var playerCard1 = draw(deck);
var dealerCard1 = draw(deck);
var playerCard2 = draw(deck);
var dealerCard2 = draw(deck);
var player = playerCard1.value + playerCard2.value;
console.log(player);
并且没有关闭其缓存,那可能是"内存泄漏的根本原因"你正在观察的问题。
答案 1 :(得分:2)
第4点是一个无效的假设,Python的垃圾收集器并不容易返回内存,Python的程序占用了那个内存,但它直到垃圾收集器才被使用有通行证。与此同时,如果某些其他请求需要更多内存 - 可能会在第一个请求的内存之上分配新内存。如果要强制Python进行垃圾回收,可以使用gc.collect()
targetlist = {
"server1:/var/www/wiki/",
"server2:/var/www/wiki/"
}
for _, server in ipairs( targetlist ) do
sync{ default.rsync,
source="/var/www/wiki/",
target=server
}
end
答案 2 :(得分:2)
请查看此Q& A,了解检查垃圾收集的方法以及可能的替代解释:Google App Engine DB Query Memory Usage