DebrisGobbler - a much more performant alternative to DebrisService

DebrisGobbler v1.1

DebrisGobbler is a open source, strongly-typed drop-in alternative to DebrisService and task.delay that offers several significant performance and usability improvements.

Roblox model | Github repository

Why DebrisGobbler?

  • DebrisGobbler is much faster than DebrisService (2x faster) and task.delay (3x faster) on insertion.
  • DebrisGobbler is magnitudes faster than DebrisService (up to 1000x faster) and task.delay on destruction.
  • DebrisGobbler is persistent, meaning unlike task.delay if your script is destroyed it will not leave debris behind.
  • DebrisGobbler can release destroyed instances before their expiry
  • DebrisGobbler can handle unlimited instances (vs. DebrisService’s 1000) and will not destroy items before their expiration time.

Alongside these performance improvements, this module retains all of the advantages of DebrisService, such as not creating a new thread or coroutine for each new item and not holding onto destroyed items with none of the disadvantages.

Performance

Insertion


DebrisGobbler is ~3x faster than task.delay and ~2x faster than DebrisService

Comparison code
--[[
This file is for use by Benchmarker (https://boatbomber.itch.io/benchmarker)

|WARNING| THIS RUNS IN YOUR REAL ENVIRONMENT. |WARNING|
--]]

local DebrisGobbler = require(game.ReplicatedStorage.DebrisGobbler.DebrisGobbler)
DebrisGobbler:Init()
local DebrisService = game:GetService('Debris')
local DestructionTime = 7

return {
	ParameterGenerator = function()
		local Parts = {}
		for i = 1, 1000 do
			table.insert(Parts, Instance.new("Part"))
		end
		return Parts
	end,

	Functions = {
		["DebrisService:AddDebris"] = function(Profiler, Parts)
			for _, Part in Parts do
				DebrisService:AddItem(Part, DestructionTime)
			end
		end,
		["DebrisGobbler:AddDebris"] = function(Profiler, Parts)
			for _, Part in Parts do
				DebrisGobbler:AddItem(Part, DestructionTime)
			end
		end,
		["task.delay"] = function(Profiler, Parts)
			for _, Part in Parts do
				task.delay(DestructionTime, Part.Destroy, Part)
			end
		end,
	},
}

Destruction

Unfortunately destruction is much harder to calculate performance benefits for, however we can make estimations based on what has been released on the inner workings of each system.

When it comes to destruction DebrisGobbler is magnitudes faster than DebrisService. While DebrisService iterates through every item during every other frame, resulting in up to 1000 iterations per frame or 30,000 iterations per second, this module only checks the nearest item to destruction per frame. DebrisService also runs on the old scheduler (30hz) which is inconsistent and adds limitations due to it being extremely slow (1000 max items), which means items can be destroyed early.

DebrisGobbler is faster than task.delay on destruction because of optimizations that merge multiple parts to be destroyed in the same frame into a single node, whereas task.delay faces performance penalties from crossing from C to Lua for each destruction alongside managing all the other task scheduling in the game.

Usage

DebrisGobbler should be placed as a module in ReplicatedStorage

DebrisGobbler:Init() must be called on a persistent script (one that will never be destroyed)

DebrisGobbler:Init()

Adds an item to be destroyed in Time. The default is 7 seconds.

DebrisGobbler:AddItem(Item: Instance, Time: number?)

Removes an item from the queue.

DebrisGobbler:RemoveItem(Item: Instance)

License

This project is fully open-source through the MIT license.

70 Likes

Heavy vouch on this one. I’ve noticed sometimes Debris service’s AddItem may remove an item earlier than intended, which interrupts gameplay in our case. Always a good one when verret posts.

6 Likes

This works perfectly, better than the regular service provided by Roblox I would recommend this to anyone using the service!

2 Likes

Is this viable for new work, it’s relatively new but when it comes to GC, it’s important to ask since there is barely any replies here.

there seems to be a memory leak

@verret001

Use this instead.

local destroy = task.delay(timeInSeconds, game.Destroy, item)

-- if you want to cancel
task.cancel(destroy)
5 Likes

having use of this would affect the performance of the task library i assume, It’s better to use the methods of this module but i’m not sure if it’s stable.

1 Like

this doesnt work like debris tho, debris will still destroy the thing even if the place it was executed on gets destroyed

This should be fixed with the latest version!

I’ve also updated the original post with more information that should be much more comprehensive.

1 Like

Is there any implementation fix for the sharedtable becoming so large, In luauheap, i found a table very large that it froze my game indefinitely when i opened it.

The problem that was occurring previously was if the script that initially required DebrisGobbler was destroyed it would stop functioning. I added DebrisGobbler:Init() and some protections to mitigate that.

Nope, it’s still as large and as laggy in the latest version, also players have reported that sometimes the object does not get deleted, for example, a dash velocity object keep may push the player forever if it wasn’t deleted

while this is the lazy method, its super slow

Do you have any evidence to back that up?

1 Like

Hey, I tried DMing you about this but you happen to have your messages off.
I found the issue you were dealing with and have resolved it, if you wouldn’t mind updating to the latest version and making sure it’s fixed for you.
As far as objects not being destroyed, this is when the root script that required the module initially is destroyed. You have to make sure to call DebrisGobbler:Init() on a script that will never be destroyed both on the client and the server.
Please feel free to send me a message if you have any other issues :slight_smile:

I updated the post yesterday with performance information as well as comparisons / benefits of using it over task.delay

I just have to make call Init one time in a perm script to solve the objects not being destroyed? Also i assume that you ruled out all the possibilities that could raise memory leaks.

Thank you verre for your utmost dedication and work for helping me out and bettering your work, I’ll be testing the new version meanwhile and I’ll come to tell you if it’s good & stable!

1 Like

It seems that objects sometimes may not get destroyed even when i call Init in client & server in a permanent script, even the script that was calling the additem didn’t get destroyed, when i kept dashing in my game sometimes the dash velocity object did not get destroyed and stayed permanently.