Script Optimization

I have a script for changing graphics. I noticed that it was over 20M in size and I was able to reduce it to around 6M after some changes.
I would like to know if there is a way to optimize it even further. I have tried everything I know, let me know how you would deal with this.

debug.setmemorycategory("Graphics Settings")

local LocalPlayer = game.Players.LocalPlayer
local SettingsData = LocalPlayer:WaitForChild("SettingsData",math.huge)
local Graphic = SettingsData:WaitForChild("Graphic")

local AllBasePartWorkspace = {}

local function NewBasepart (Obj:BasePart)
	if not Obj.Parent or not Obj:IsA("BasePart") then return end
	if AllBasePartWorkspace[Obj] then return end

	AllBasePartWorkspace[Obj] = {}

	Obj.Destroying:Once(function()
		if AllBasePartWorkspace[Obj].Connections then
			for _,ConnectionTab in pairs(AllBasePartWorkspace[Obj].Connections) do
				for _,v in pairs(ConnectionTab) do
					v:Disconnect()
				end
			end
		end
		table.clear(AllBasePartWorkspace[Obj])
		AllBasePartWorkspace[Obj] = nil
	end)
	if VerifyConfigObj then
		VerifyConfigObj(Obj)
	end
end

for i,v in pairs(workspace:GetDescendants()) do task.spawn(NewBasepart,v) end
workspace.DescendantAdded:Connect(NewBasepart)

-- Functions

function VerifyConfigObj (Obj)
	if not AllBasePartWorkspace[Obj] then return end
	if not Obj.Parent or not Obj:IsA("BasePart") then return end

	if not AllBasePartWorkspace[Obj].Properties then
		AllBasePartWorkspace[Obj].Properties = {}
	end
	if not AllBasePartWorkspace[Obj].Connections then
		AllBasePartWorkspace[Obj].Connections = {}
	end
	
	if Graphic:GetAttribute("BasicTextures") and not AllBasePartWorkspace[Obj].Properties["BasicTextures"] then
		if Obj.Material ~= Enum.Material.ForceField and Obj.Material ~= Enum.Material.Glass then
			AllBasePartWorkspace[Obj].Properties["BasicTextures"] = {}
			AllBasePartWorkspace[Obj].Connections["BasicTextures"] = {}

			AllBasePartWorkspace[Obj].Properties["BasicTextures"].Material = Obj.Material
			Obj.Material = Enum.Material.SmoothPlastic

			AllBasePartWorkspace[Obj].Connections["BasicTextures"][#AllBasePartWorkspace[Obj].Connections["BasicTextures"]+1] = Obj:GetPropertyChangedSignal("Material"):Connect(function()
				AllBasePartWorkspace[Obj].Properties["BasicTextures"].Material = Obj.Material
				Obj.Material = Enum.Material.SmoothPlastic
			end)
		end
	elseif not Graphic:GetAttribute("BasicTextures") and AllBasePartWorkspace[Obj].Properties["BasicTextures"] then

		for i,v in pairs(AllBasePartWorkspace[Obj].Connections["BasicTextures"]) do
			v:Disconnect()
		end
		
		for Pro,Value in pairs(AllBasePartWorkspace[Obj].Properties["BasicTextures"]) do
			pcall(function() Obj[Pro] = Value end)
		end
		
		table.clear(AllBasePartWorkspace[Obj].Properties["BasicTextures"])
		table.clear(AllBasePartWorkspace[Obj].Connections["BasicTextures"])
		AllBasePartWorkspace[Obj].Properties["BasicTextures"] = nil
		AllBasePartWorkspace[Obj].Connections["BasicTextures"] = nil
	end

	if Graphic:GetAttribute("DisableShadows") and not AllBasePartWorkspace[Obj].Properties["DisableShadows"] then
		AllBasePartWorkspace[Obj].Properties["DisableShadows"] = {}
		AllBasePartWorkspace[Obj].Connections["DisableShadows"] = {}

		AllBasePartWorkspace[Obj].Properties["DisableShadows"].CastShadow = Obj.CastShadow
		Obj.CastShadow = false

		AllBasePartWorkspace[Obj].Connections["DisableShadows"][#AllBasePartWorkspace[Obj].Connections["DisableShadows"]+1] = Obj:GetPropertyChangedSignal("CastShadow"):Connect(function()
			AllBasePartWorkspace[Obj].Properties["DisableShadows"].CastShadow = Obj.CastShadow
			Obj.CastShadow = false
		end)
	elseif not Graphic:GetAttribute("DisableShadows") and AllBasePartWorkspace[Obj].Properties["DisableShadows"] then

		for i,v in pairs(AllBasePartWorkspace[Obj].Connections["DisableShadows"]) do
			v:Disconnect()
		end
		
		for Pro,Value in pairs(AllBasePartWorkspace[Obj].Properties["DisableShadows"]) do
			pcall(function() Obj[Pro] = Value end)
		end
		
		table.clear(AllBasePartWorkspace[Obj].Properties["DisableShadows"])
		table.clear(AllBasePartWorkspace[Obj].Connections["DisableShadows"])
		AllBasePartWorkspace[Obj].Properties["DisableShadows"] = nil
		AllBasePartWorkspace[Obj].Connections["DisableShadows"] = nil
	end

end

function VerifyAll ()
	for Obj,_ in pairs(AllBasePartWorkspace) do
		VerifyConfigObj(Obj)
	end
end

VerifyAll()

Graphic.AttributeChanged:Connect(VerifyAll)

You can disable Shadows by turning off GlobalShadows in Lighting Service.

I also wouldn’t really recommend keeping track of every part in workspace, it use close to no memory if you just looped through each descendant of workspace or if you used CollectionService

I am pretty sure tags don’t clean up/GC’d automatically when instance is destroyed, don’t they?

Never nesters (me) is dying from amount of nesting

I think when an instance is gc’d after being destroyed it frees up all of its memory

I do this to avoid freezing and possible crash on lighter devices

I think tags are exception to this? Or has this been fixed?

Yes but at the same time you’re also keeping track of every part in workspace, going through each descendant of the workspace with some throttle (e.g; RunService.RenderStepped) would be much better in this case. Using collection service would be an even better fit