Hello devs! Yesterday i was testing how much parts can be spawned without using any form of wait inside a loop. Turns out, its A LOT, after playing around ive decided to try to make code that creates 30000 parts run as fast as possible.
This post is about my journey on how i optimized the script to create 30000 parts more than 2.5 times faster!! And trust me, even though i am not ultra advanced programmer, some of these optimizations that i found i believe might shock some great devs
This is the first code:
task.wait(3.5)
local startTime = os.clock()
for i = 1,30000 do
local x = Instance.new("Part", workspace)
x.Position = Vector3.new(math.random(10,35), math.random(2,20),math.random(10,35))
x.Size = Vector3.new(1,1,1)
x.Anchored = true
end
print(os.clock()-startTime)
There are 2 rules:
- code has to spawn 30000 parts, no more, no less
- These 4 properties of the part have to stay the same, meaning you can optimize everything but you can’t change its position to Vector3.new(5,3,1) for example, Anchored has to stay the same, position also and its Parent has to be in the workspace
os.clock() is being used to measure time between start and end of the script so we could have as precise measure as possible.
The code right now runs in ~0.665s
- Setting Parent last!!!
The first and best thing we can do is setting Part.Parent last.
Insted of
local x = Instance.new("Part", workspace) ----
we do this
local x = Instance.new("Part")
x.Position = Vector3.new(math.random(10,35), math.random(2,20),math.random(10,35))
x.Size = Vector3.new(1,1,1)
x.Anchored = true
x.Parent = workspace ----
This alone decreases our time to about 0.41s
0.2 sec differece just by changing one line one code! But why is that?
How it works is part properties are being set before going to the workspace, Think of this like this…
you are in bed and you want to do eggs for breakfast. When setting parent first, you instantly stand up and the time starts, you go to the kitchen, then you are searching for the pan, then you are searching for the eggs, for seasonings etc etc
When you set Parent last, you think where everything is before leaving the bed, now that you know where everything is, you stand up, time starts, you go to the kitchen and you get everything much faster because you dont have to think and search where the stuff are.
- table.insert()
Second optimization we can do is use table and table.insert()
task.wait(3.5)
local startTime = os.clock()
local parts = {}
for i = 1,30000 do
local x = Instance.new("Part")
x.Position = Vector3.new(math.random(10,35), math.random(2,20),math.random(10,35))
x.Size = Vector3.new(1,1,1)
x.Anchored = true
table.insert(parts, x)
end
for i,v in parts do
v.Parent = workspace
end
print(os.clock()-startTime)
went from ~0.41 to ~0.34
How this optimization works is it creates a parts and sets its properties, then it inserts it into a table that we created, then with the for i,v loop it sets all of the part parents to workspace
You might be thinking, why not put every property into the for i,v loop then? Well, for some reason this makes the code run faster by ~0.03s (it will be ~0.3s total) but later it will make the code slower.
code already runs almost 2 times faster, but were not stopping there!
- Creating folder for parts
Instead of putting all these parts into the workspace, we can store them into a folder that will be inside a workspace
The only thing in the code that we have to change is
for i,v in parts do
v.Parent = workspace
end
to
for i,v in parts do
v.Parent = workspace.Folder
end
We are almost reaching measures below 0.3 seconds!!
Second thing we can do is changing workspace.Folder
to a variable
local folder = workspace.Folder
for i,v in parts do
v.Parent = folder
end
With this, code got another minor optimisation and we did reach measures below 0.3 and even below 0.29!
We can change Vector3.new to Vector3.one which should run a little bit faster
current code:
task.wait(3.5)
local startTime = os.clock()
local parts = {}
local min = 10
local max = 35
local folder = workspace.Folder
for i = 1,30000 do
local x = Instance.new("Part")
x.Anchored = true
x.Size = Vector3.one
x.Position = Vector3.new(math.random(min, max), math.random(2,20),math.random(min,max))
table.insert(parts, x)
end
for i,v in parts do
v.Parent = folder
end
print(os.clock()-startTime)
- Shocking discoveries
Now, how code works is, it creates 30000 parts and it inserts them into a table. Then, that table is being looped to set all of 30000 parts parents into a folder that is inside a workspace.
We can make it even faster.
Right now it sets 30000 parts Parent inside a workspace.Folder, which means we are going back to first point of this post again but a little bit different, it sets parent to workspace.Folder 30000 times. Folder is inside a workspace, that is the problem.
We can create a Folder in a different service and then set Folder.Parent to workspace, but where do we put the folder?
I was testing putting folder into every service and then changing that folder parent to workspace and checking how fast it performs, ReplicatedFirst won.
These are the full results
These differences are too big to say its just statistical error so where we place the folder really matters
These are the results that we can get now, but we can still go quicker
I believe game:GetService()
is slower than game.
When i changed it, the results were a little bit better but it might be just statistical error so take that with the grain of salt
When we create 2 new prints
we can see which part of code runs how fast
we can see that setting folder to workspace is the longest, second is 30000 parts loop and the lightest is setting them to folder.
This is where everything stands now, i dont know what else i can do, so here’s a challenge for you.
Make this run even faster than 0.244s and publish your code in the comments if you believe it is faster. I will post an update if i find a faster way. Thank you to anyone who read all of this