To get something every frame you can use RunService.
Here is a quick description of it and its uses.
By connecting to one of the RunService events (ex. heartbeat) you can also receive the amount of seconds it took for that heartbeat. This will give you an approximation every heartbeat for what the current fps is.
Your current code will more or less halt the thread for X time. If your code takes exactly 1 second to execute that is pure luck, and will be different depending on the hardware that is running it.
Your current script does not actually show you the FPS, instead it shows you what integer * 16 is greater than or equal to or larger than 1000, which will be the same every time.
Instead you could do this:
local fps = 0
local number = 0
repeat
fps += 1
number += task.wait() -- This returns the time it took in seconds (decimals)
until number >= 1
print(fps) -- Prints the amount of loops able to be completed within 1s
However, I would still not recommend this as it is not linked to the frame rendering, which RunService is.
local runService = game:GetService("RunService")
local CurrentFPS = 1/runService.RenderStepped:Wait()
RenderStepped:Wait() returns a number equal to how long it’s been between the current frame and the last frame. Divide 1 by this number and you should get the FPS
For the server’s FPS, you can do this:
local FPS = 1/task.wait()
Same concept as using RenderStepped:Wait(), since task.wait() returns a number equal to how long it’s been between the current frame and the last frame