Ability to Instance:ClearAllTags()

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
5 Likes

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?

Thank you!

1 Like

Even I see it as insanely useless.
The engine bloat would outweigh the benefits.

2 Likes

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.