- Home /
Understanding the cost of different functions
So this is something I've never been sure of, but since I have a concrete example right now, I figured I'd run it by you all so I can learn for the future.
Basically, I'm making a submarine game, and the submarine returns to a neutral position if no button is pressed. As it stands right now, I check every frame to see if a button is being pressed, and if it isn't, I Lerp between the current position and the neutral position, like so:
if (!Input.GetKey (KeyCode.UpArrow) && !Input.GetKey (KeyCode.DownArrow)) {
currentX = Mathf.Lerp (currentX, 0, Time.deltaTime);
}
However, this feels wasteful to me, as it will continue to Lerp even when it's returned to a neutral position. I was considering adding an if statement to check to see if it's at a neutral position, something like this:
if Mathf.Abs (currentX > .01f){
if (!Input.GetKey (KeyCode.UpArrow) && !Input.GetKey (KeyCode.DownArrow)) {
currentX = Mathf.Lerp (currentX, 0, Time.deltaTime);
}
}
Alternately, I could do it:
if (!Input.GetKey (KeyCode.UpArrow) && !Input.GetKey (KeyCode.DownArrow)) {
if Mathf.Abs (currentX > .01f){
currentX = Mathf.Lerp (currentX, 0, Time.deltaTime);
}
}
So I guess my question is, which of these 3 would be the fastest? Thanks!
Adam
Answer by Jessespike · Feb 27, 2015 at 10:53 PM
The difference is quite insignificant with modern technology. And since the calculation is only executed once per frame and not many times for many objects, you could probably just skip this thought. But since you asked, and I was curious myself, I decided to run a test. Like most technical problems, the answer will be... it depends. Depends on the hardware, what value currentX is, if you're pressing any keys, etc...
To run your own tests, get the profile script here: http://wiki.unity3d.com/index.php/Profiler
Now according to my super-scientific research, the results show that the 3rd method is the fastest on average.
no keys being pressed, currentX being greater than 0.01 for most of the time
Method 1 took 0.003008700 seconds to complete over 1000 iterations, averaging 0.000003009 seconds per call
Method 2 took 0.001624600 seconds to complete over 1000 iterations, averaging 0.000001625 seconds per call
Method 3 took 0.000533800 seconds to complete over 1000 iterations, averaging 0.000000534 seconds per call
Holding up arrow key
Method 1 took 0.003370300 seconds to complete over 1000 iterations, averaging 0.000003370 seconds per call
Method 2 took 0.002678900 seconds to complete over 1000 iterations, averaging 0.000002679 seconds per call
Method 3 took 0.001618500 seconds to complete over 1000 iterations, averaging 0.000001619 seconds per call
Now having said all that, I would personally choose the method that is easiest to read and maintain. Code readability is far superior than micro-optimizations. That doesn't mean I completely disregard performance, but something as trivial as this seems to be a waste of time and energy that could be focused on other tasks, or be optimizing something that would have a noticeable effect on performance.
Here's the test script I used:
using UnityEngine;
public class SomeProfileTest : MonoBehaviour {
float currentX = 1000f;
int iterations = 1000;
int elapsedIterations = 0;
// Update is called once per frame
void Update () {
float frameCurrentX = currentX;
Profile.StartProfile("Input Method 1");
if (!Input.GetKey (KeyCode.UpArrow) && !Input.GetKey (KeyCode.DownArrow)) {
currentX = Mathf.Lerp (currentX, 0, Time.deltaTime);
}
Profile.EndProfile("Input Method 1");
currentX = frameCurrentX;
Profile.StartProfile("Input Method 2");
if (Mathf.Abs (currentX) > .01f){
if (!Input.GetKey (KeyCode.UpArrow) && !Input.GetKey (KeyCode.DownArrow)) {
currentX = Mathf.Lerp (currentX, 0, Time.deltaTime);
}
}
Profile.EndProfile("Input Method 2");
currentX = frameCurrentX;
Profile.StartProfile("Input Method 3");
if (!Input.GetKey (KeyCode.UpArrow) && !Input.GetKey (KeyCode.DownArrow)) {
if (Mathf.Abs (currentX) > .01f){
currentX = Mathf.Lerp (currentX, 0, Time.deltaTime);
}
}
Profile.EndProfile("Input Method 3");
elapsedIterations++;
if (elapsedIterations >= iterations)
{
Application.Quit();
Debug.Break();
}
}
void OnApplicationQuit () {
Profile.PrintResults();
}
void OnGUI() {
GUI.Label(new Rect(0f, 0f, 100f, 100f), currentX.ToString());
}
}
Wow, thanks for doing all that. I'll definitely start using that profiler thing, that seems very useful. I guess the time difference seems pretty $$anonymous$$uscule, I just remember in program$$anonymous$$g class in high school, even something as simple as counting took a noticeable amount of time, so I was paranoid that something more complex like calculating averages or absolute values every frame might make a real difference. But apparently not!
Answer by siaran · Feb 27, 2015 at 10:30 PM
I don't think the difference between those would really be noticable, so I wouldn't bother with trying to figure out the most optimized method. Instead write the code in the way that you think makes the most sense.
If you want to check for a neutral position, then, imo, that's the last one - I also suspect checking Mathf.Abs() takes a little more to check than 2 input booleans and that way lets you get out of the if statment before you check Mathf.Abs() - I'm not sure about that but I would be surprised if it was different.
I don't think checking for it makes any real difference performance-wise though, Lerp should be a fairly cheap method.
In fact, not checking may be the best way performance-wise. I don't know how Lerp compares to (x > Math.Abs), but in cases where you need to Lerp you'll have to evaluate both. If you only very rarely DONT Lerp (wether this is the case depends on your game), constantly checking for a neutral position might be a net decrease in performance.
Not a definitive answer to your question as to what is fastest I suppose, but some things worth considering in any case.
That makes a lot of sense. Thanks for your perspective!
Your answer
Follow this Question
Related Questions
Multiple Cars not working 1 Answer
Distribute terrain in zones 3 Answers
Use Lerp Position and Slerp Rotation together 0 Answers
[Editor Scripting] Call Function in other GameObjects Editor Script? 0 Answers
3D Grapher - Function input problem 1 Answer