Skip to content

Change E2 time quota to be per player#3558

Merged
Astralcircle merged 19 commits intowiremod:masterfrom
Astralcircle:perplayertime
Mar 25, 2026
Merged

Change E2 time quota to be per player#3558
Astralcircle merged 19 commits intowiremod:masterfrom
Astralcircle:perplayertime

Conversation

@Astralcircle
Copy link
Contributor

@Astralcircle Astralcircle commented Mar 21, 2026

I think this would be beneficial for servers, because servers care more about the overall load from a player than about their specific chip. Currently, players can simply spread the load across multiple chips to bypass the quota limit, but this won't eliminate it, it will only increase the overhead
It also turns on E2 disabling by default when disconnecting because it allows to avoids a lot of problems

Thanks Redox/thegrb93 for helping with code

I think this would be beneficial for servers, because servers care more about the overall load from a player than about their specific chip. Currently, players can simply spread the load across multiple chips to bypass the quota limit, but this won't eliminate it; it will only increase the overhead
@Astralcircle Astralcircle marked this pull request as draft March 21, 2026 08:06
@Astralcircle Astralcircle marked this pull request as ready for review March 21, 2026 10:33
@Astralcircle Astralcircle marked this pull request as draft March 21, 2026 11:34
@Astralcircle
Copy link
Contributor Author

I plan to change this to use the average CPU time per player as SF to also get rid of the chip crash during lag spikes. Until then, PR will remain Draft

@Astralcircle Astralcircle marked this pull request as ready for review March 23, 2026 20:48
@Astralcircle Astralcircle requested a review from thegrb93 March 23, 2026 23:56
@thegrb93
Copy link
Contributor

Looks ok, but I know a lot of people are going to complain about their chips breaking when spawning props for the first time since there's always lag when loading models. Probably should have a pretty lenient average to prevent that.

@Astralcircle
Copy link
Contributor Author

Astralcircle commented Mar 24, 2026

Like what? The current one is already 0.05

@thegrb93
Copy link
Contributor

I mean an average to smooth the spikes. Does e2 already do that somewhere?

@Astralcircle
Copy link
Contributor Author

Yes
image

@thegrb93
Copy link
Contributor

thegrb93 commented Mar 24, 2026

I'd suggest a class for cleaner code

local PlayerChips = {}
PlayerChips.__index = PlayerChips
function PlayerChips:new() -- static method
	return setmetatable({chips = {}}, self)
end
function PlayerChips:getTotalTime()
	local total_time = 0
	for _, chip in ipairs(self.chips) do
		local tab = chip:GetTable()
		if tab.error then continue end

		local context = tab.context
		if not context then continue end

		total_time = total_time + context.timebench
	end
	return total_time
end
function PlayerChips:findMaxTimeChip()
	local max_chip, max_time = nil, 0
	for _, chip in ipairs(self.chips) do
		local tab = chip:GetTable()
		if tab.error then continue end

		local context = tab.context
		if not context then continue end

		if context.timebench > max_time then
			max_time = context.timebench
			max_chip = chip
		end
	end
	return max_chip, max_time
end
function PlayerChips:checkCpuTime()
	local total_time = self:getTotalTime()
	while total_time > e2_timequota do
		local max_chip, max_time = self:findMaxTimeChip()
		if max_chip then
			total_time = total_time - max_time
			max_chip:Error("Expression 2 (" .. max_chip.name .. "): Per-player time quota exceeded", "per-player time quota exceeded")
			max_chip:Destruct()
		else
			-- It shouldn't happen, but if something breaks, it will prevent an infinity loop
			break
		end
	end
end
function PlayerChips:add(chip)
	table.insert(self.chips, chip)
end
function PlayerChips:remove(rmchip)
	for index, chip in ipairs(self.chips) do
		if rmchip == chip then
			table.remove(self.chips, index)
			break
		end
	end
end

E2Lib.PlayerChips = setmetatable({},{__index = function(t,ply) local r=PlayerChips:new() t[ply]=r return r end})

hook.Add("Think", "E2_Think", function()
	if e2_timequota < 0 then return end
		for ply, plychips in pairs(E2Lib.PlayerChips) do
			plychips:checkCpuTime()
		end
	end
end)

-- init.lua
E2Lib.PlayerChips[owner]:add(self)

@thegrb93
Copy link
Contributor

Also need to make sure that the max_chip:Error and max_chip:Destruct remove the chip from the 'chips' otherwise it'll just keep trying to error the first chip.

@Astralcircle
Copy link
Contributor Author

if tab.error then continue end protects against this, and chips should not be removed from the table because they can be recompiled

@thegrb93
Copy link
Contributor

Oh yeah, good point

@Astralcircle
Copy link
Contributor Author

I'd suggest a class for cleaner code

Is this really necessary? I don't condemn this approach, but personally, i like when everything is simply in one function

@thegrb93
Copy link
Contributor

thegrb93 commented Mar 25, 2026

Well, imagine you want to later add an e2 function for total time. It would be good to be able to just use return E2Lib.PlayerChips[self.owner]:getTotalTime(). It's good practice imo since it organizes code, even though you're right the code here is a little too simple to be turned into a class. It would be good if more things in wire did it (e.g. ports). I don't mind either way though, not my call.

@thegrb93
Copy link
Contributor

Probably should add a total time e2function now that e2 chips will need to check it to not error.

@Astralcircle
Copy link
Contributor Author

I think now everything is ready, i also added the totalCpuUsage function as you said

@Astralcircle Astralcircle changed the title Add per player time quota for E2 Change E2 time quota to be per player Mar 25, 2026
@Astralcircle Astralcircle merged commit 98571dc into wiremod:master Mar 25, 2026
1 check passed
@Astralcircle Astralcircle deleted the perplayertime branch March 25, 2026 20:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants