BetterDebris - Replacement for the service "Debris"

Better alternative for Debris.

Source Code:

local RunService = game:GetService("RunService")

local function init()
	if shared.BetterDebris then return end
	shared.BetterDebris = {}
	
	if shared.BetterDebris.Bin then return end
	shared.BetterDebris.Bin = {}
	
	if shared.BetterDebris.Collector then return end
	shared.BetterDebris.Collector = RunService.PreRender:Connect(function()
		for item, infoTable in pairs(shared.BetterDebris.Bin) do

			if os.clock() - infoTable.Time >= infoTable.Duration then
				item:Destroy()
				shared.BetterDebris.Bin[item] = nil
			end
		end
	end)
end

local function errorCheck(item, duration)
	if not item then 
		error(`Item cannot be of type "nil".`)
		return
	end
	if not item.Destroy then
		error(`Missing method "Destroy".`)
		return
	end
	if type(duration) ~= "number" then
		error(`Duration must be of type "number"`)
		return
	end

end

local function addItem(item: Instance, duration: number)
	errorCheck(item, duration)
	
	shared.BetterDebris.Bin[item] = {
		Time = os.clock(),
		Duration = duration or 0
	}
end

init()
return {Add = addItem}
9 Likes

How is this “more performant” though?

1 Like

It uses tasks for asynchronous work, type-checking and proper cleanup, like setting empty variables to nil after removal to prevent memory leaks. (Anyone correct me if I’m wrong, I’m still working on my LUA vocab)

How is that related to the script? About the performance though:

Service functions are written in C, which is obviously way more performant than Lua code. You can check whenever some function is a C function using debug.info(func, 's'), which returns '[C]' if the function is written in C.
image
In this case, lua code cannot be faster.

A Roblox Engineer themselves said you should avoid using DebrisService due it being outdated and that it’d just be faster to do it yourself. I can find it and quote it if you would like me to.

3 Likes

Fair, but I’d still prefer Debris due to being reliable and immune to script getting destroyed.

task.delay → destroy is more performant then Debris:AddItem

just use Collector, task.delay bla bla destroy isnt performant when youre using debris for aton of stuff at a time
sorry to burst your bubble

2 Likes

Oh, I didn’t know this actually, thanks for educating me. I thought by performance you meant how the code written in that module is handled and its usage on CPU within the game, not how it can be compared to how the debris service works internally.

When I give it more thought in fact, that slipped my mind; the first thing I should’ve considered was the internal functionality of the original debris service before responding. Thanks for making me aware.

I suppose at the very least this resource solves the issue where Debris automatically deletes instances before their expected cleanup time if overflowed with requests.

Either way though, you’re right; good for me to learn something today.

1 Like

Debris is used when you want to destroy something within a script that may also get destroyed. Doing something like that yourself is significantly harder and less efficient than simply having a built-in method.

Also, depending on the implementation it can spawn a ton of unnecessary threads.

1 Like

Me when I make new threads every time I want to schedule an object for deletion:

This is fairly naïve implementation for Debris service; it also makes some assumptions on the callers’ usage of the API, which isn’t really good (mainly no nilability check on the module.Items[item]), quite expensive on the memory side, and somewhat… not really performant in general, I’d say

That is not equivalent to using Debris, which even the documentation for Debris states. If the script gets destroyed with that code, the object will not get destroyed.

Also, if the instance is already destroyed then the code will error. A more proper way to do so in a single line that prevents this issue:

task.delay(5, instance.Destroy--[[game.Destroy works too]], instance)

Personally i doubt the user is going to delete the the one module they have thats main purpose is to delete instances

Is that not what the module does?

module.Items[item] = task.delay(duration, item.Destroy, item)

Say you have a script inside of a tool, and the tool has a possibility of getting destroyed from the player dying.

If you call Debris:AddItem() on something and the script gets destroyed, the instance will still destroy after the duration. That won’t happen using this module or with the code the admin said was equivalent.

For a quick code example:

This won’t work:

local baseplate = workspace:WaitForChild("Baseplate")

task.delay(1, baseplate.Destroy, baseplate)
script:Destroy()

However, this will:

local Debris = game:GetService("Debris")

local baseplate = workspace:WaitForChild("Baseplate")

Debris:AddItem(baseplate, 1)
script:Destroy()

That’s why this module doesn’t work properly as an alternative to Debris lol.

IIRC there are actual working alternatives like Collector or DebrisGobbler, but wouldn’t just updating the service be a better option than deprecating it and make old projects that use it smoother?

this makes allot more sense, i was thinking of a whole other situation

1 Like
  • Items now get deleted even if the script is destroyed.
  • Changed how deletion works.
1 Like