Optimization issues with custom scrollbar implementation

So I designed a basic system to essentially “shadow” a ScrollingFrame’s slider. I made this because of the limitations with the default slider ScrollingFrames have, and also due to the fact they’re sized in offset and not scale, which makes it look super ugly on lower screen resolutions.

Unfortunately I came to find out it does not run well when you constantly scroll in the scrolling frame. Script activity spikes up to about 4-5%, and there does seem to be a little noticeable lag in doing so.

The way it stands currently I’m at a loss at how I can optimize this. The only thing I can think of is the mass use of vectors might be the culprit, and for that I tried referencing the needed vector types only once within the function body and yet it still spikes poorly.

This is pretty frustrating, because I don’t see how this can be optimized any further, unless I’m totally oblivious to something.

local function getScrollerSize(canvasSizeHeight, windowSizeHeight)
		local scalar = windowSizeHeight / canvasSizeHeight
		local YSize = windowSizeHeight * scalar

		return YSize
	end

	local function updateScroller()
		
		local canvasSize, windowSize = scrollerFrame.AbsoluteCanvasSize, scrollerFrame.AbsoluteWindowSize
		
		local size = getScrollerSize(canvasSize.Y, windowSize.Y)
		slider.Size = UDim2.new(slider.Size.X.Scale, 0, 0, size)

		local maxPosition = 1 - (size / backbar.AbsoluteSize.Y)
		
		local maxScalar = canvasSize.Y - windowSize.Y
		local scalar = scrollerFrame.CanvasPosition.Y / maxScalar
		
		slider.Position = UDim2.new(slider.Position.X.Scale, 0, maxPosition * scalar, 0)
		
		--//Hide/show the backbar if scrolling is active
		
		local isScrollingActive = canvasSize.Y > windowSize.Y
		
		if scrollingActiveState ~= isScrollingActive then
			scrollingActiveState = isScrollingActive
			
			local scrollerBackbarTransparency = (isScrollingActive and 0) or 1
			
			backbar.Parent.ImageTransparency = scrollerBackbarTransparency
			backbar.Parent:SetAttribute("OriginalTransparency", scrollerBackbarTransparency)
		end
	end
	
	--//Event bindings
	scrollerFrame:GetPropertyChangedSignal("AbsoluteCanvasSize"):Connect(updateScroller)
	scrollerFrame:GetPropertyChangedSignal("CanvasPosition"):Connect(updateScroller)
	updateScroller()

EDIT:
I can’t determine if there’s much FPS loss after testing again, but the activity can get absurdly high. (8-9%)

Thanks for any ideas.

1 Like

I don’t really see how that relates to my situation.

Thanks though, I guess.

How often is updateScroller being called? I see it’s only on absoluteCanvasSize change/canvasPosition change, but could you see if it’s stacking up over time, or if it’s being called a large number of times per frame?

I’m mainly asking to see if there’s something in here that would make either the absoluteCanvasSize and/or the canvasPosition change recursively, or if you are creating duplicate connections somehow. There isn’t much here that looks like it would be indicative of any performance problems

1 Like

So it should just be those two connections at the bottom. Each time either the canvas size or the window itself changes, the custom scrollbar needs to update, so there really isn’t a way to optimize that, nor should it be costly to such code?

I also wanted to note I have animations on my UI screens for them to fade out and scale out as well (UIScale tweening) which causes the custom scrollbar to rapidly update as the scrolling frame changes during this animation.

However, the high activity spikes were still there regardless of the animation playing. That occurred just from me scrolling in the scrolling frame.

Thanks for your reply

1 Like

Okay, I made a basic repro of your script and my script activity won’t go up past roughly 0.15% with a single scrolling frame, it goes up to about 1.5% with 77 scrolling frames being updated at a time. How many scrolling frames do you have, and could you double check that each scrolling frame isn’t being initialized more than once?

Also, what does your hierarchy for the slider look like, does it have a bunch of descendants?

1 Like

Wow that’s odd.

I can almost assure the source of the activity spike is coming from this. I disable the update functionality for the custom scrollbars, and the activity goes back to normal levels.

Here’s a screenshot of the entire hierarchy, the 'Products frame is what is being shown:

EDIT:

It seems to be caused from the elements held inside the scroller frame. But they’re not being manipulated by code, let alone this system? Very strange

EDIT 2:

Yeah that’s absolutely bizarre. I just confirmed the more elements that are contained within the scrolling frame, the higher the script activity will spike from the custom scrollbar system.

Makes absolutely no sense at all. Would love to get some insight from one of the engineers on this one.

Sorry, went to sleep after sending my last message. I’m going to look and see if I can repro

Are you constantly adding to/removing from the scrolling frame and do you have automatic canvas size or something else that is adjusting the canvas size?

1 Like

Nothing out of the ordinary. I do have it set to use automatic canvas size however. I did also try turning it off as well, but that made no difference.

I’m gonna try it in a different place with just the scrollbar module and nothing else. If it yields the same activity usage I might turn this into an engine bug report.

EDIT:

I tried it in a different place as a repro, and to my surprise the activity stems at a much more reasonable range.

This is utterly confusing, because the activity spike is coming from this module. As soon as I disable it, the activity is fine as I scroll in the scrolling frame. But, the module works just fine in its own repro.

EDIT 2:

I also just tried doing exactly as I did from the repro (using a different script to initialize the custom scrollbar within the module) and I’m getting the same high activity spikes .

This seems increasingly like an engine bug in my opinion. If you have any further ideas I’d love to hear your insight

I’m a bit stumped as well, especially if you know the update function isn’t being called more than once per frame or so. I’m probably being pedantic but you know for sure it isn’t being called more than that right (ie you’ve added a print or something?)

I would file a bug report if that’s the case, because from what I see here, there isn’t much that’s indicative of anything like that

1 Like