Need help finding what is causing lag spikes

You can write your topic however you want, but you need to answer these questions:

  1. What do you want to achieve? Keep it simple and clear!
    I need to figure out what these labels in the micro profiler are referring to so I can make my code run better.

  2. What is the issue? Include screenshots / videos if possible!

Whenever I run a script that makes an explosion and subtracts parts of a wall using geometry service’s subtractasync method I get a big lag spike. I don’t know what the labels in the micro profiler are referring to in this case so I’m not sure what it is that I need to change to stop the lag spikes.


lag spike in micro profiler^


zoomed in lag spike^

  1. What solutions have you tried so far? Did you look for solutions on the Creator Hub?

I’ve checked the documentation for information on what this could be but I haven’t been able to find anything.

I’ve searched the forum for if anyone else has had this issue but all I could find was issues with the “write marshalled” label and I’ve learned that it is data being converted to be sent over the network but I haven’t been able to find what the “commit” or “stat::send” labels mean.

If this is an issue with the network then I assume it is because the explosion is done on the server and then all the changes would have to be replicated to the client, so if this is the case then what could I do to prevent a big lag spike such as this when the data is being sent between them?

When I test the explosions I have also looked at the network received graph under the performance stats and it goes up a bit after an explosion but it never goes above the target of 50 kb/s so shouldn’t that have a big spike if the lag is caused by the network?

Also this issue has just started today. When I was working on the explosions yesterday there was a little bit of lag but it was never as much as it is now. For example I could have my character walking and notice a very small frame drop but it would still be fairly smooth. Now it freeze entirely for a little bit. The issue gets worse the larger the radius of the explosion is. I haven’t really changed anything about how the explosions are done since then either so idk

Thanks

I’m still trying to resolve this issue. I’ve tried restoring a previous place version when it was running smoothly previously but it also now has a lag spike issue.


Microprofiler in previous place version ^

Now when I test it there are other labels as well but commit and stat::send are still the two lowest in the order.

I’ve also noticed that sometimes the CPU graph in the performance stats spikes. Does anyone know how to fix this? Or is it a bug?

I’m still looking for what is causing the issue and haven’t been able to find anything

From your live server example, it does look like networking is the issue. Even though your clip shows a receive rate that hovers around 20 KB/s, that statistic is averaged, and it is only about 500 B/s prior to the explosion, so the client must be receiving a huge chunk of data all at once to inflate the average that much. While the issue cropping up suddenly could be the result of engine changes to networking logic, the underlying problem is still there.

Without seeing any code or knowing what you need the system to achieve, it is difficult to provide recommendations. The bricks seem like the strongest avenue for improvement since it looks like many of them are modified all at once, but I’m not sure what you’re doing to them.

Ok. When the explosion is triggered, all the bricks in the radius are compiled into a list which is passed through this function. Basically what it does is create parts around each brick which are then subtracted from the wall. It also rewelds appropriate parts.

function physicsModule.cutBricks(brickList)
	--getting mortar parts (if there is more than 1)
	local mortarList={}
	
	for _, brick in brickList do
		local mortar=brick.Parent:FindFirstChild("Mortar")
		
		if not table.find(mortarList,mortar) then
			table.insert(mortarList,mortar)
		end
	end
	
	for _, mortar in mortarList do
		--get bricks based on mortar parts and create holes
		local holeList={}

		for _, brick in mortar:GetConnectedParts() do
			if brick.Name=="Brick" and table.find(brickList,brick) then
				local hole=holePart:Clone()
				hole.CFrame=brick.CFrame
				hole.Size=brick.Size+Vector3.new(0.3,0.3,0.3)

				table.insert(holeList,hole)
			end
		end

		--subtract holes from mortar
		local success, newMortarParts = pcall(function()
			return GS:SubtractAsync(mortar,holeList,subtractOptions)
			--return {mortar}
		end)

		--Positions new mortar parts in workspace and rewelds bricks to applicable newmortar parts
		for _, newMortar in newMortarParts do
			newMortar.CFrame=mortar.CFrame
			newMortar.Anchored=mortar.Anchored
			newMortar.Name=mortar.Name
			newMortar.Parent=mortar.Parent

			for _, brick in workspace:GetPartsInPart(newMortar) do
				if brick.Name=="Brick" then
					local mortarWeld=brick:FindFirstChild("BrickWeld")

					if mortarWeld then
						mortarWeld.Part1=newMortar
					end
				end
			end
		end

		--split wall into seperate walls if mortar is split into pieces
		if #newMortarParts>1 then
			physicsModule.splitWall(newMortarParts)
		end
		--reweld parts based on new walls


		--recreate welds for parts that are not bricks
		local welds=GS:CalculateConstraintsToPreserve(mortar,newMortarParts,options)	--use to get touching parts that are not bricks, change to alter preexisting welds with stone/wood
		local newWelds={}

		for _, weld in welds do
			if weld.WeldConstraintPart0.Name~="Brick" then
				local newWeldConstraint=Instance.new("WeldConstraint")
				newWeldConstraint.Part0=weld.WeldConstraintPart0
				newWeldConstraint.Part1=weld.WeldConstraintPart1
				newWeldConstraint.Parent=weld.WeldConstraintParent
			end
		end

		mortar:Destroy()
		--destroy old mortar's joints

		for _, hole in holeList do
			hole:Destroy()
		end
	end
	
	--destroy welds for bricks being cut
	for _, brick in brickList do
		local mortarWeld=brick:FindFirstChild("BrickWeld")
		
		if math.random(1,10)>1 then
			brick:Destroy()
		end
		
		if mortarWeld then
			mortarWeld:Destroy()
		end
	end
end

What I’ll try doing is instead of creating a hole part for each individual brick I’ll group adjacent hole parts into singular parts. Do you think that would be enough? If not then what else can I do to decrease the data being replicated?

Thanks

Okay, after reading the code, it does seem like the :SubtractAsync() call is the bottleneck, not networking. Using the live server clip as my reference, that first explosion appears to include roughly 450-500 bricks in its calculation. It takes my computer 1.5 seconds to perform a :SubtractAsync() with that many parts, which results in a huge “write marshalled” tag in the microprofiler like you’ve experienced, even in edit mode with no networking going on.

The simplest solution is to just reduce the fidelity of the cutout by simply removing a sphere or cylinder or something, but that obviously hurts the vision of what you’ve got going on here.

If you define a particular collection of collinear bricks as a wall, you can shortcut the amount of work the system need to do by greedy-meshing rows of bricks together, using a single part to represent a span of adjacent bricks. This would cut down the amount of parts being used in the reference clip from ~475 down to only 27 for the front wall and 15 for the side wall (plus the columns’ parts? I don’t know if they’re being used in the calculation or not).

Thanks for the help, I’ll try meshing the parts. If that doesn’t work then I guess I’ll just have to do what you recommended with a single part based on the explosion’s radius rather than each individual brick. The columns are a lot simpler, they’re just made of 1x1x1 stud voxels which are randomly destroyed.

Thanks

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.