4

I'm creating and translating a few algorithms when I'm wondering which is faster?

a) (int)float

or

b) Mathf.FloorToInt(float)

Thanks in advance.

EDIT: If there is a faster way than either of those, that would be helpful too.

Dmitry
  • 6,716
  • 14
  • 37
  • 39
sfbea
  • 159
  • 1
  • 11
  • 4
    Do the measurement yourself. It's [not](https://stackoverflow.com/questions/457605/how-to-measure-code-performance-in-net) hard. – Programmer Oct 03 '17 at 08:56
  • 1
    While it might be interesting theoretical question, one should not hope that choosing the currently faster approach will be noticeable. – Gedrox Oct 03 '17 at 08:56
  • I'll try to run some tests, see if anything noticeable happens – sfbea Oct 03 '17 at 08:59
  • The difference in execution times, if any, will be negligible unless running in a tight loop. Also, it might very in different environments, even on the same machine. [race your horses.](https://ericlippert.com/2012/12/17/performance-rant/) – Zohar Peled Oct 03 '17 at 09:00
  • The algorithm involves many loops, among others of mine, that is mainly why I wanted to know – sfbea Oct 03 '17 at 09:03
  • 4
    `FloorToInt(float)` does `return (int)Math.Floor((double)f);` Just looking at that, my guess is it will be slower. Also note that `(int)float` does a truncate instead of floor, so the results will be different for negative numbers. – Dennis_E Oct 03 '17 at 09:04

2 Answers2

5

Do a test with Stopwatch like I mentioned. This answer is here because I believe that the result in your answer is wrong.

Below is a simple performance test script that uses loop since your algorithm involves many loops:

void Start()
{

    int iterations = 10000000;

    //TEST 1
    Stopwatch stopwatch1 = Stopwatch.StartNew();
    for (int i = 0; i < iterations; i++)
    {
        int test1 = (int)0.5f;
    }
    stopwatch1.Stop();

    //TEST 2
    Stopwatch stopwatch2 = Stopwatch.StartNew();
    for (int i = 0; i < iterations; i++)
    {
        int test2 = Mathf.FloorToInt(0.5f);
    }
    stopwatch2.Stop();

    //SHOW RESULT
    WriteLog(String.Format("(int)float: {0}", stopwatch1.ElapsedMilliseconds));
    WriteLog(String.Format("Mathf.FloorToInt: {0}", stopwatch2.ElapsedMilliseconds));
}

void WriteLog(string log)
{
    UnityEngine.Debug.Log(log);
}

Output:

(int)float: 73

Mathf.FloorToInt: 521

(int)float is clearly faster than Mathf.FloorToInt. For stuff like this, it is really bad to use the FPS from the Editor Stats to make the judgement. You do a test with the Stopwatch. The FPS should be used when writing shader code.

Programmer
  • 121,791
  • 22
  • 236
  • 328
  • Numbers you get from the Editor may be very different from numbers you get in release builds, due to compiler optimization - particularly when transpiling to C++ with IL2CPP – user45623 Jun 11 '20 at 00:41
4

It depends on your target platform.

In the Editor, where you're running .NET code that hasn't been optimized, (int) is much faster than Mathf.Floor() because the latter includes the extra expense of function calls.

However, when you compile a build, your code may be optimized differently depending on your target platform and build settings. Many build targets use IL2CPP to transpile your code. With IL2CPP, your C# code is compiled to .NET intermediate language (IL), which is then translated to C++ (CPP), which is then compiled into a binary for your target platform (or compiled to WebAssembly for WebGL builds).

The compilers are not stupid. They will optimize or even inline function calls where practical. In other words, the compiler may end up replacing Mathf.Floor() with something that works very similarly to (int).

For example, in my own testing, I've found that (int) can be 20x faster than Mathf.Floor() in the Editor, but in a WebGL build there's no difference in speed.

Never make decisions about code performance based only on testing in the Editor. You should always test performance-critical code on your target platform. That said, it's rare for your game code to bottleneck on this kind of thing. Usually performance bottlenecks come from graphics, algorithms, or abusing Unity APIs (e.g. constantly calling GameObject.Find()).

user45623
  • 621
  • 4
  • 18