It would be interesting to have an Instance:ClearAllTags() as it would shorten the code required to clean up things and improve overall speed/performance, just like Instance:ClearAllChildren()
Instance:ClearAllTags()
-- vs
for _, Tag in Instance:GetTags() do
Instance:RemoveTag(Tag)
end
I, personally, adore when it comes to optimizations.
Do you mind thinking about what can be optimized here against the luau method you’ve provided?
RemoveTag barely can be optimized, because it already jumps to native c implementation.
The thing which remains is tags iteration, probably iteration in c can be faster.
Ok, let’s measure how much time it takes now in luau.
To do that I wrote following snippet:
Remove 10000 tags
--!strict
local CollectionService = game:GetService("CollectionService")
local tagsCount = 10000
local part = Instance.new("Part")
for i = 1, tagsCount do
CollectionService:AddTag(part, "tag_" .. i)
end
local tags = part:GetTags()
print("tags", #tags)
local iterationStart = tick()
local iterationEnd
local iterationTime = 0
local removalTime = 0
for _, tag in tags do
iterationEnd = tick()
iterationTime += iterationEnd - iterationStart
local removalStart = tick()
part:RemoveTag(tag)
local removalEnd = tick()
removalTime += removalEnd - removalStart
iterationStart = tick()
end
iterationEnd = tick()
iterationTime += iterationEnd - iterationStart
print("iterationTime", iterationTime)
print("removalTime", removalTime)
print(iterationTime * 100 / removalTime)
It creates 10000 tags and removes them measuring time spent iterating and removing them.
I have ran it several times.
It says that iteration takes from 0.05% to 0.06% of tag removal.
Please correct me if I made a mistake.
So… do you think it’s worth any efforts in speed/performance improvements?
One way to see the potential of how much it can be optimized is using ClearAllChildren() as example vs Destroy(). I know it’s not the same thing, but it can give an idea!
ClearAllChildren vs Destroy Example
do
local Folder = Instance.new("Folder")
local ClearAllChildrenFolder = Instance.new("Folder")
for i = 1, 100000 do
local Part = Instance.new("Part")
Part.Name = i
Part.Parent = Folder
local ClearAllChild = Instance.new("Part")
ClearAllChild.Name = i
ClearAllChild.Parent = ClearAllChildrenFolder
end
Folder.Parent = workspace
ClearAllChildrenFolder.Parent = workspace
print(`Total children before clear: {#Folder:GetChildren()}`)
local StartDestroy = os.clock()
for _, Child in Folder:GetChildren() do
Child:Destroy()
end
local EndDestroy = os.clock()
print(`Total time to destroy children: {(EndDestroy - StartDestroy) * 1000} milliseconds`)
print(`Total children before clear: {#ClearAllChildrenFolder:GetChildren()}`)
local StartClearAll = os.clock()
ClearAllChildrenFolder:ClearAllChildren()
local EndClearAll = os.clock()
print(`Total time to clear all children: {(EndClearAll - StartClearAll) * 1000} milliseconds`)
Folder:Destroy()
ClearAllChildrenFolder:Destroy()
end
The result:
Total children before clear: 100000
Total time to destroy children: 820.1714999995602 milliseconds
Total children before clear: 100000
Total time to clear all children: 506.36459999805083 milliseconds
So here we’re talking of a ~314ms difference, or about 38% speed improvements. This is without mentioning that without proper yielding (task.wait, which would slow down the loop even more) it can cause freezes if we exceed the time per frame
For tags it’s a different for sure, there won’t be as many, but since you need to “GetTags” before Removing them it adds more time.
But my proposed solution is mostly for readability (which I forgot to mention) as the final speed difference might be small unless you have a lot of tags
EDIT: Taking a real world experience, here’s my game script profiler for cleaning up a bot after it dies,
the settings: Freq 10KHz, Time 5m, Average 1s
RemoveTag is called on 3 tags only and GetTags once. I know the times there are small and negligible, but removing 3 tags is 2.5x more expensive than stopping and destroying a dozen animation
I’ve got your point: instead or removing tags one by one, ClearAllTage could just purge whole container. And it makes sense.
But, I can imagine an instance with a lot of children in workspace, that could a folder with bullets or swarm of generated objects and so on, but I have hard times imagining use case of an instance with such amount of tags so bunch removal could make a difference.