Deferred Engine Events

It randomly adds : or / before some messages still.
Last week it was still having issues scrolling automatically when people send multi-line messages (though that might be fixed now?

2 Likes

I notice it significantly changes the behavior of game.Players.PlayerRemoving event. With deferred signaling, it is handled AFTER player parent is set to nil, not before. The same in case of instance.Destroying event.

@tnavarts

1 Like

Hi please move any TextChatService related conversation to TextChatService is now the default for new experiences!, thank you!

1 Like

Plugins do not have settings at present that would make it easy to configure which signalling behavior they use. We are aware of this issue though and we are thinking about how best to solve it.

1 Like

This update is, believe it or not, awful. I’ve been getting so many unreproducible bugs because of this new behavior. I’m sure it’s because of this, as none of them happen for hours of testing when the behavior is set back to Immediate. Why does the behavior have to change?? For security? Performance? Consistency? Maybe for the engine, but not for my game. Immediate events make so much more sense.

I would hate for this to be the default. This should at least come with a way to debug or a way to easily visualize what is going on here.

When looking at this image (on the right):

What does that mean? Event A, B, and C? Is that a connection, or a script signal? A whole bunch of connections? How and when is the order of execution affected? What does the left image mean by ‘yields’?

The left clearly looks less preformant, but it makes much more sense. Deferred events may make sense when replicating between the client-server boundary. I may feel better if this is better explained. When I think of ‘Deferred’, I think the event is going to be fired on the next frame, maybe that’s why I’m confused.

For now, I’m switching back to Immediate until I can get an understanding of what is going on with Deferred events. I’ve been used to Immediate for 4 years.

1 Like

If you want another way to think of it. It’s a queue, like a checkout queue at the store:

  • Whenever an event is fired it has to wait at the back of the queue, behind all the events that got fired before it.

  • That customer may call someone else and tell them to get something while they’re in the queue. That other person will have to wait at the back of the queue too (event fires another event while being handled).

  • Customers sometimes enter the queue while the teller is busy with something else like cleanup on isle 5 (C++ code is running). The customers will eventually get served but only once the the teller is available again (C++ code reaches an invocation point and starts running handlers from the queue).

  • This leads to performance wins because it’s easier for the teller to get their other work done all at once rather than being interrupted by rude customers who demand the teller stops what they’re doing and serves them right this instant all the time (what happens right now).

  • It also leads to security wins because the teller might lose track of what they were doing when they drop everything to serve the customer immediately.

Hope that analogy helps.

9 Likes

I guess it does help, but there’s a problem. With all my old code, I don’t really know where these connections are being made anymore. It’s like forcing a rewrite. Do you have an idea of when this update will roll out for everybody?

The saving grace is that you likely don’t actually have to change much code: While it may be tricky to find the lines of code that need to change at first for a large existing codebase, if you execute the changeover correctly it’s very unlikely that you actually have to change many lines of code total.

The timeline is long. As the post says:

Our goal for 2023 is to change the default (which is to say, the behavior of places with SignalBehavior set to Default) from immediate mode to deferred mode.

That’s just change the default in 2023, not remove the setting.

4 Likes

Just curious, is the performance/security boost live for games that have this enabled, and how much of a performance boost is this (in % or something similar)?

Unfortunately we actually have to move to a world where there is no setting and events are always deferred before we can reap most of the benefits.

That’s because even though some people have switched to deferred mode, the C++ code still has to be written in the slower way which is capable of handling interruption by immediate mode events while the setting exists. (Technically we could write multiple different variants of various pieces of code now depending on the setting value but that’s a great way to have twice as many bugs too, so not really worth it)

2 Likes

I wish I could diff the behavior of my game with and without this property enabled. My worst fear is this introducing bugs in my datastore layer (which is third party), or creating memory leaks. Too much of Roblox is not easily unit testable or possible to deeply analyze.

3 Likes

let us able to read SignalBehavior Property on workspace from code
like print(game:GetService(“Workspace”).SignalBehavior) ← SignalBehavior is not a valid member of Workspace “Workspace” (error)

1 Like

After switching to Deferred, my game runs fine on studio, however, when I test on the live client, it freezes up and crashes.

The only point of interest in the client log dump was spamming this
0.572.0.5720484_20230421T140754Z_Player_8650F_last.log

2023-04-21T14:09:17.866Z,82.866776,144c,6 [FLog::Error] Exception caught in TGenericSlotWrapper. bad allocation
2023-04-21T14:09:17.866Z,82.866776,144c,6 [FLog::Error] Exception caught in TGenericSlotWrapper. bad allocation
2023-04-21T14:09:17.866Z,82.866776,144c,6 [FLog::Error] Exception caught in TGenericSlotWrapper. bad allocation
2 Likes

As a modeler and builder mostly but amateur scripter, can somebody explain this change like I am 5?

See my post above: Deferred Engine Events - #78 by tnavarts

Unfortunately I don’t think this property will ever be script readable, but here’s a bit of a hacky workaround.

local isDeferred: boolean do
	local function checkDeferred()
		isDeferred = true
		local bind = Instance.new("BindableEvent")
		bind.Event:Once(function() isDeferred = false end)
		bind:Fire()
		bind:Destroy()
	end
	checkDeferred()
	
	workspace.Changed:Connect(function( property )
		if ( property ~= "SignalBehavior" ) then return end
		checkDeferred()
	end) 
end

that detect the signalbehavior changed but its un changeable while in game (running on live server) so useless

Oh, I moreso thought you needed it for a plugin, not in game.
What are you planning to make? If it’s something like an admin console, you can just leave in the first few lines and remove the .Changed part.

its for my networking module to track/detect what the game signalbehavior currently using on, so i can alert user to use :Once if it was Deferred, if possible my network library module could adapt with deferred without need change to :Once over :Listen (aka :Connect) without any problem happens

1 Like

why not make a new method :Immediate() for the old behavior instead of a property of workspace that globally effects signal behavior in that place
also now since its live why cant we read workspace.SignalBehavior