PSA: Don't use Instance.new() with parent argument

I was thinking “It can’t be that much of a difference can it?”

Oh my. Time to go change some things.

236 Likes

Good to know! By a stroke of luck, I frequently use my own implementation of util.Create, but it already does parent assignment last so properties are what they should be when ChildAdded/etc fire.

12 Likes

Oh.

Oh no.

EDIT: Never mind, as far as I can tell I had been taking this into account the whole time. whew

19 Likes

I’ve always done this. Now I’m justified! :smiley:

83 Likes

Time to start CTRL+F-ing

50 Likes

Oh dear, I was under the assumption that none of this would happen until the next frame. Better get round to some optimization.

9 Likes

Not to sound grumpy, but there’s a reason not to look into how ROBLOX gears works.
From a selected few gears, not only is there this sort of code, but also issues with people getting stuck with it, it’s not cross-platform compatible, and even invites to collision-related exploits for people to teleport outside of game barriers. Bites lip in disgust - that is, recode it all

:confounded:

22 Likes

A lot of CoreGui uses this, should probably look into cleaning those up.

23 Likes

You just gave me flashbacks on all the times I used the second/third method

27 Likes

Rip me, I used this at every chance I could. Guess now would be a good time to stop

19 Likes

I almost feel like I need to find something worse just to upset zeuxcg further.

Perhaps

Instance.new("Object")
  .Transparency(0)
  .Size(Vector3.new(2, 2, 2))
  .Anchored(true)
  .CFrame(CFrame.new(5, 5, 5))
  .BrickColor(BrickColor.new("Bright red"))
.Parent(workspace)

Through the use of a metatable.

Enjoy suffering some more @zeuxcg

do
	local create = Instance.new
	local object, parentFunction, setFunction, tab
	tab = setmetatable({}, {
		__index = function (_, index)
			if index == "Parent" then
				return parentFunction
			else
				return function (value)
					return setFunction(index, value)
				end
			end
		end
	})
	parentFunction, setFunction = function (parent)
		object.Parent = parent
		return object
	end, function (index, value)
		object[index] = value
		return tab
	end
	Instance = {
	new = function (class)
		object = create(class)
		return tab
	end
	}
end
19 Likes

NEVER NEVER NEVER read ROBLOX gear code.

Please.

100 Likes


I would, if it didn’t cause… this to appear.

4 Likes

Oh my

Time to go change all my instancing I guess

5 Likes

Tbh, if your game needs this kind of optimization…

@zeuxcg wouldn’t it be possible for the engine to only start doing the queueing for new objects when the thread yields?
E.g.

local obj = Instance.new("Part",workspace) -- state: instantiation
-- set properties
-- state: still instantiation
coroutine.yield() -- or wait()
-- thread yielded, obj's state becomes "initial setup" or "doing the queueing"
10 Likes

Oh my. I had observed this but I hadn’t connected it to setting properties after setting Parent. Good to know.

I’ve added a warning to the wiki documentation for Instance.new.

6 Likes

Reading ROBLOX Gear code is how I got started with Lua in the first place.

31 Likes

Keep in mind in his example the first 100 parts have already been created when the second for loop runs, it would be better to test fresh both times.

I just tried it (restarting each time) and got 0.0027530193328857 and 0.10685229301453 (40x difference) over 100 iterations, which is still a lot.

9 Likes

For those of you wondering how to find all cases of where you may have done this, search your game with this:

Instance.new\([\s\S]*,

Make sure you check “Regular expression”

This used to be necessary to avoid having WaitForChild hang itself when parenting AND THEN renaming (now fixed I believed)

55 Likes

There are many issues with parenting early which are not simply performance benchmarks. A while ago I ran into an issue where I had parented a part to workspace with the surface type defaulted to studs, upon parenting the engine had automatically created snap joints with the baseplate. Immediately after I set the Parent I would also set the surface types to smooth but since the snaps were already made and they stuck around. Ultimately, my projectiles ended up a little more stationary than intended…
This anecdote may have changed in our iterations of the physics solver, but I think it still serves as a good lesson!

9 Likes