Huge memory buildup - LUA


#1

I don’t know why, but whenever I use this type of code the memory usage goes crazy. And with that I mean, reaching 4gb of ram, making chrome die on me. I’ve tried testing different ways of making things work, commenting out parts I didn’t need, etc, (even attempted to do some manual garbage clearing/collecting). It all ended up going crazy and hit the 4gig cap… Which is a pretty amazing thing to hit. This is just one of the scripts that does that, but I have loads of previous attempts to get more creative in doing things, but all leading to just having chrome die. :confused:

Lua should easily be able to handle this, if not more… So, please, what’s going on?

Big long code:

-- Go to the far right edge of the level to find new areas.
-- Check the guide for more details.
local neutralEnemy = {"sand-yak"=true, "raven"=true}

local moveSpeed = self.maxSpeed
local maxAttackRange = self.attackRange

function toPositive(number)
	if number < 0 then
		return 0-number
	else
		return number
	end
end

function fleeFrom(target)
	local myx = self.pos.x
	local myy = self.pos.y
	local gotoPos = {x=(myx-target.pos.x)*10, y=(myy-target.pos.y)*10}
	local modifier = self:distanceTo({x=gotoPos.x+myx, y=gotoPos.y+myy})
	gotoPos.x = (gotoPos.x/modifier)*moveSpeed
	gotoPos.y = (gotoPos.y/modifier)*moveSpeed
	if self:isPathClear(self.pos, {x=myx+gotoPos.x, y=myy+gotoPos.y}) then
		self:move({x=myx+gotoPos.x, y=myy+gotoPos.y})
		--self:say("Fleeing! 1")
	else
	--[[
	if self:isPathClear(self.pos, {x=myx+gotoPos.y, y=myy+gotoPos.x}) then
		self:move({x=myx+gotoPos.y, y=myy+gotoPos.x})
		--self:say("Fleeing! 2")
	elseif self:isPathClear(self.pos, {x=myx-gotoPos.y, y=myy-gotoPos.x}) then
		self:move({x=myx-gotoPos.y, y=myy-gotoPos.x})
		--self:say("Fleeing! 3")
	else
	]]
		if toPositive(gotoPos.x) > toPositive(gotoPos.y) then -- more x than y
			if gotoPos.x > 0 then
				if self:isPathClear(self.pos, {x=myx+moveSpeed, y=myy}) then
					self:move({x=myx+moveSpeed, y=myy})
				elseif self:isPathClear(self.pos, {x=myx, y=myy+moveSpeed}) then
					self:move({x=myx, y=myy+moveSpeed})
				elseif self:isPathClear(self.pos, {x=myx, y=myy-moveSpeed}) then
					self:move({x=myx, y=myy-moveSpeed})
				else
					self:say("Help me!")
				end
			else
				if self:isPathClear(self.pos, {x=myx-moveSpeed, y=myy}) then
					self:move({x=myx-moveSpeed, y=myy})
				elseif self:isPathClear(self.pos, {x=myx, y=myy+moveSpeed}) then
					self:move({x=myx, y=myy+moveSpeed})
				elseif self:isPathClear(self.pos, {x=myx, y=myy-moveSpeed}) then
					self:move({x=myx, y=myy-moveSpeed})
				else
					self:say("Help me!")
				end
			end
		else
			if gotoPos.y > 0 then
				if self:isPathClear(self.pos, {x=myx, y=myy+moveSpeed}) then
					self:move({x=myx+moveSpeed, y=myy})
				elseif self:isPathClear(self.pos, {x=myx+moveSpeed, y=myy}) then
					self:move({x=myx+moveSpeed, y=myy})
				elseif self:isPathClear(self.pos, {x=myx-moveSpeed, y=myy}) then
					self:move({x=myx-moveSpeed, y=myy})
				else
					self:say("Help me!")
				end
			else
				if self:isPathClear(self.pos, {x=myx, y=myy-moveSpeed}) then
					self:move({x=myx-moveSpeed, y=myy})
				elseif self:isPathClear(self.pos, {x=myx+moveSpeed, y=myy}) then
					self:move({x=myx+moveSpeed, y=myy})
				elseif self:isPathClear(self.pos, {x=myx-moveSpeed, y=myy}) then
					self:move({x=myx-moveSpeed, y=myy})
				else
					self:say("Help me!")
				end
			end
		end
	end
end

loop
	local allEnemies = self:findEnemies()
	local selectedEnemy = nil
	local enemyCount = 0
	local closeEnemies = 0
	local closestEnemy = 99
	local closeEnemyHealth = 0
	local numEnemies = #allEnemies
	if numEnemies > 20 then 
		break
	end
	if numEnemies > 0 then
		local en = 1
		while en <= numEnemies do
			local curEnemy = allEnemies[en]
			if curEnemy.type ~= "sand-yak" and curEnemy.type ~= "raven" and curEnemy.health > 0 then
				enemyCount = enemyCount + 1;
				local distance = self:distanceTo(curEnemy)
				if distance <= maxAttackRange then
					if distance < closestEnemy then --and self:isPathClear(self.pos, enemy.pos) then
						selectedEnemy = curEnemy
						closestEnemy = distance
					end
					if curEnemy.type == "brittle-skeleton-archer" or distance < 6 then -- they can attack us!
						closeEnemies = closeEnemies + 1
						closeEnemyHealth = closeEnemyHealth + curEnemy.health
					end
				end
			end
			curEnemy = nil
			en = en + 1
		end
		allEnemies = nil
	end
	
	
	if enemyCount > 0 then
		
		if self:hasEffect("hide") then
			if closestEnemy > 30 then
				self:wait(0.25);
				-- just fiddle around as we wait I guess?
			else
				if selectedEnemy then
					fleeFrom(selectedEnemy)
				else
					self:wait(1)
				end
			end
		elseif closeEnemies > 1 and closeEnemyHealth > 21 then
			if self:canCast("invisibility", self) then
				self:cast("invisibility", self)
			elseif self:isReady("hide") then
				self:hide()
			else
				if selectedEnemy then
					fleeFrom(selectedEnemy)
				else
					self:wait(1)
				end
			end
		else
			if selectedEnemy then
				if closeEnemies > 0 and closeEnemyHealth > 21 then
					fleeFrom(selectedEnemy)
				end
				
				if selectedEnemy.health > 21 then
					if closestEnemy < 20 then
						--if self:canElectrocute(selectedEnemy) then
						--	self:electrocute(selectedEnemy)
						--end
					else
						if selectedEnemy.health > 39 and self:isReady("envenom") then
							self:envenom()
						end
					end
					if self:isReady("power-up") then
						self:powerUp()
					else
						self:attack(selectedEnemy)
					end
				else
					self:attack(selectedEnemy)
				end
			else
				self:wait(1)
				self:say("No enemy selected")
			end
		
		end
	else
		local moveTo = {x=self.pos.x+moveSpeed, y=self.pos.y}
		if moveTo.x >= 118 or self:isPathClear(self.pos, moveTo) then
			self:move(moveTo)
		else
			if self.pos.y > 37 then
				moveTo = {x=self.pos.x, y=self.pos.y-moveSpeed}
			else
				moveTo = {x=self.pos.x, y=self.pos.y+moveSpeed}
			end
			
			if self:isPathClear(self.pos, moveTo) then
				self:move(moveTo)
			else
				self:say("I'm stuck...")
				self:wait(5)
			end
		end
		moveTo = nil
		self:wait(1)
	end
end

the java log: https://i.gyazo.com/20d549fe2f6e11f30d07270f8b6c4bf3.png


Edit:

with the use of the bug described at Bug with Stranded in the Dunes I was able to test what happened if the situation wouldn’t change, and basicly the same wave of yaks came in, teleported back, and rushed in again… And the memory just gets bigger and bigger, untill it reaches the 4gb cap, and dies. In other words, this has to be a massive memory leak.

the script I used to test this: (in the Stranded in the Dunes, using the glitch to spawn Yaks that shouldn’t be there XD)

self:move({x=self.pos.x+math.random(0,2)-1,y=self.pos.y+math.random(0,2)-1})
self:move({x=self.pos.x+math.random(0,2)-1,y=self.pos.y+math.random(0,2)-1})

local moveSpeed = self.maxSpeed

function toPositive(number)
	if number < 0 then
		return 0-number
	else
		return number
	end
end


function fleeFrom(target)
	local myx = self.pos.x
	local myy = self.pos.y
	local gotoPos = {x=(myx-target.pos.x)*10, y=(myy-target.pos.y)*10}
	local modifier = self:distanceTo({x=gotoPos.x+myx, y=gotoPos.y+myy})
	gotoPos.x = (gotoPos.x/modifier)*moveSpeed
	gotoPos.y = (gotoPos.y/modifier)*moveSpeed
	if self:isPathClear(self, {x=myx+gotoPos.x, y=myy+gotoPos.y}) then
		self:move({x=myx+gotoPos.x, y=myy+gotoPos.y})
		--self:say("Fleeing! 1")
	elseif self:isPathClear(self, {x=myx+gotoPos.y, y=myy+gotoPos.x}) then
		self:move({x=myx+gotoPos.y, y=myy+gotoPos.x})
		--self:say("Fleeing! 2")
	elseif self:isPathClear(self, {x=myx-gotoPos.y, y=myy-gotoPos.x}) then
		self:move({x=myx-gotoPos.y, y=myy-gotoPos.x})
		--self:say("Fleeing! 3")
	else
		self:wait(0.001)
		if toPositive(gotoPos.x) > toPositive(gotoPos.y) then -- more x than y
			if gotoPos.x > 0 then
				if self:isPathClear(self, {x=myx+moveSpeed, y=myy}) then
					self:move({x=myx+moveSpeed, y=myy})
				elseif self:isPathClear(self, {x=myx, y=myy+moveSpeed}) then
					self:move({x=myx, y=myy+moveSpeed})
				elseif self:isPathClear(self, {x=myx, y=myy-moveSpeed}) then
					self:move({x=myx, y=myy-moveSpeed})
				else
					self:say("Help me!")
				end
			else
				if self:isPathClear(self, {x=myx-moveSpeed, y=myy}) then
					self:move({x=myx-moveSpeed, y=myy})
				elseif self:isPathClear(self, {x=myx, y=myy+moveSpeed}) then
					self:move({x=myx, y=myy+moveSpeed})
				elseif self:isPathClear(self, {x=myx, y=myy-moveSpeed}) then
					self:move({x=myx, y=myy-moveSpeed})
				else
					self:say("Help me!")
				end
			end
		else
			if gotoPos.y > 0 then
				if self:isPathClear(self, {x=myx, y=myy+moveSpeed}) then
					self:move({x=myx+moveSpeed, y=myy})
				elseif self:isPathClear(self, {x=myx+moveSpeed, y=myy}) then
					self:move({x=myx+moveSpeed, y=myy})
				elseif self:isPathClear(self, {x=myx-moveSpeed, y=myy}) then
					self:move({x=myx-moveSpeed, y=myy})
				else
					self:say("Help me!")
				end
			else
				if self:isPathClear(self, {x=myx, y=myy-moveSpeed}) then
					self:move({x=myx-moveSpeed, y=myy})
				elseif self:isPathClear(self, {x=myx+moveSpeed, y=myy}) then
					self:move({x=myx+moveSpeed, y=myy})
				elseif self:isPathClear(self, {x=myx-moveSpeed, y=myy}) then
					self:move({x=myx-moveSpeed, y=myy})
				else
					self:say("Help me!")
				end
			end
		end
		--self:say("Help!")
	end
end

loop
	local enemies = self:findEnemies()
	local selected = nil
	local closest = 999
	local count = 0
	for en=1, #enemies do 
		local enemy = enemies[en]
		if enemy.type ~= "raven" and enemy.health > 0 then
			local distance = self:distanceTo(enemy)
			count = count + 1
			if distance < closest then
			   selected = enemy 
			   closest = distance
			end
		end
	end
	
	if self:distanceTo({x=32, y=26}) < 0.1 then
		if count > 0 then
			if selected and closest < 20 then
				fleeFrom(selected)
			end
			if self:hasEffect("hide") then
				self:say("Sneaky sneak!")
			else
				if self:canCast("invisibility", self) then
					self:cast("invisibility", self)
				elseif self:isReady("hide") then
					self:hide()
				else
					self:say("Uh oh! they can see me!")
				end
			end
		end
	else 
		self:move({x=32, y=26})
	end
end

Edit 2:

So, I’ve translated the exact same script to JavaScript… and it’s perfectly smooth, memory is completely stable, and no problems whatsoever.

var moveSpeed = this.maxSpeed;

function toPositive(arg1){
	if (arg1 < 0){
		return 0-arg1;
	}else{
		return arg1;
	}
}
var self = this;
function fleeFrom(target){
	var myx = self.pos.x;
	var myy = self.pos.y;
	var gotoPos = {x:(myx-target.pos.x)*10, y:(myy-target.pos.y)*10};
	var modifier = self.distanceTo({x:gotoPos.x+myx, y:gotoPos.y+myy});
	gotoPos.x = (gotoPos.x/modifier)*moveSpeed;
	gotoPos.y = (gotoPos.y/modifier)*moveSpeed;
	if( self.isPathClear(self, {x:myx+gotoPos.x, y:myy+gotoPos.y}) ){
		self.move({x:myx+gotoPos.x, y:myy+gotoPos.y});
		
	}else if( self.isPathClear(self, {x:myx+gotoPos.y, y:myy+gotoPos.x}) ){
		self.move({x:myx+gotoPos.y, y:myy+gotoPos.x});
		
	}else if( self.isPathClear(self, {x:myx-gotoPos.y, y:myy-gotoPos.x}) ){
		self.move({x:myx-gotoPos.y, y:myy-gotoPos.x});
	}else{
		if( toPositive(gotoPos.x) > toPositive(gotoPos.y) ){ // more x than y
			if( gotoPos.x > 0 ){
				if (self.isPathClear(self, {x:myx+moveSpeed, y:myy}) ){
					self.move({x:myx+moveSpeed, y:myy});
				}else if( self.isPathClear(self, {x:myx, y:myy+moveSpeed}) ){
					self.move({x:myx, y:myy+moveSpeed});
				}else if( self.isPathClear(self, {x:myx, y:myy-moveSpeed}) ){
					self.move({x:myx, y:myy-moveSpeed});
				}else{
					self.say("Help me!");
				}
			}else{
				if (self.isPathClear(self, {x:myx-moveSpeed, y:myy}) ){
					self.move({x:myx-moveSpeed, y:myy});
				}else if( self.isPathClear(self, {x:myx, y:myy+moveSpeed}) ){
					self.move({x:myx, y:myy+moveSpeed});
				}else if( self.isPathClear(self, {x:myx, y:myy-moveSpeed}) ){
					self.move({x:myx, y:myy-moveSpeed});
				}else{
					self.say("Help me!");
				}
			}
		}else{
			if( gotoPos.y > 0 ){
				if (self.isPathClear(self, {x:myx, y:myy+moveSpeed}) ){
					self.move({x:myx, y:myy+moveSpeed});
				}else if( self.isPathClear(self, {x:myx+moveSpeed, y:myy}) ){
					self.move({x:myx+moveSpeed, y:myy});
				}else if( self.isPathClear(self, {x:myx-moveSpeed, y:myy}) ){
					self.move({x:myx-moveSpeed, y:myy});
				}else{
					self.say("Help me!");
				}
			}else{
				if (self.isPathClear(self, {x:myx, y:myy-moveSpeed}) ){
					self.move({x:myx, y:myy-moveSpeed});
				}else if( self.isPathClear(self, {x:myx+moveSpeed, y:myy}) ){
					self.move({x:myx+moveSpeed, y:myy});
				}else if( self.isPathClear(self, {x:myx-moveSpeed, y:myy}) ){
					self.move({x:myx-moveSpeed, y:myy});
				}else{
					self.say("Help me!");
				}
			}
		}
	}
}


loop {
	
	var enemies = this.findEnemies();
	var selected = null;
	var closest = 999;
	var count = 0;
	
	for(var en = 1; en < enemies.length; en++){
		var enemy = enemies[en];
		if(enemy.type !== "raven" && enemy.health > 0){
			var distance = this.distanceTo(enemy);
			count++;
			if(distance < closest){
				selected = enemy;
				closest = distance;
			}
		}
	}
	
	if(this.distanceTo({x:32, y:26}) < 0.1 ){
		if( count > 0 ){
			if( selected && closest < 20 ){
				fleeFrom(selected);
			}
			
			if(this.hasEffect("hide")){
				this.say("Sneaky sneak!");
			}else{
				if(this.canCast("invisibility", this)){
					this.cast("invisibility", this);
				}else if(this.isReady("hide") ){
					this.hide();
				}else{
					this.say("Uh oh! they can see me!");
				}
			}
		}
	}else{
		this.move({x:32, y:26});
	}
	
}

As I stated before… It’s not my code. There is a massive memory leak going on with the lua coding.


Game Pacing, Gem Deprivation and Difficulty spike