On the LeetCode question Two Sum, I noticed that when I initialized the returned Array in one line with the return statement, as so: return new int[2] {i, o};
, the code was significantly slower than when written like this:
int[] returnArr = new int[2] {i, o}; return returnArr;
. The one line return used less memory for obvious reasons, but it was extremely slow. Why?
response time: 275ms
public class Solution {
public int[] TwoSum(int[] nums, int target) {
for (int i = 0; i < nums.Length; i ) {
for (int o = i 1; o < nums.Length; o ) {
if (nums[i] nums[o] == target) {
return new int[2] {i, o};
}
}
}
return new int[0];
}}
response time: 181ms
public class Solution {
public int[] TwoSum(int[] nums, int target) {
for (int i = 0; i < nums.Length; i ) {
for (int o = i 1; o < nums.Length; o ) {
if (nums[i] nums[o] == target) {
int[] returnArr = new int[2] {i, o};
return returnArr;
}
}
}
return new int[0];
}}
CodePudding user response:
In Release mode, IL body of the both TwoSum methods are the same;
IL_0014: ldc.i4.2
IL_0015: newarr [System.Runtime]System.Int32
IL_001a: dup
IL_001b: ldc.i4.0
IL_001c: ldloc.0
IL_001d: stelem.i4
IL_001e: dup
IL_001f: ldc.i4.1
IL_0020: ldloc.1
IL_0021: stelem.i4
IL_0022: ret
In Debug mode, there are only 2 more opcodes. For first example, IL body of the method;
IL_001c: ldc.i4.2
IL_001d: newarr [System.Runtime]System.Int32
IL_0022: dup
IL_0023: ldc.i4.0
IL_0024: ldloc.0
IL_0025: stelem.i4
IL_0026: dup
IL_0027: ldc.i4.1
IL_0028: ldloc.1
IL_0029: stelem.i4
IL_002a: stloc.3
IL_002b: br.s IL_0058
Second example;
IL_001c: ldc.i4.2
IL_001d: newarr [System.Runtime]System.Int32
IL_0022: dup
IL_0023: ldc.i4.0
IL_0024: ldloc.0
IL_0025: stelem.i4
IL_0026: dup
IL_0027: ldc.i4.1
IL_0028: ldloc.1
IL_0029: stelem.i4
IL_002a: stloc.3
IL_002b: ldloc.3 // Pushes local variable, returnArr to the 3rd index of the evaluation stack.
IL_002c: stloc.s 4 // Pops latest pushed value from evaluation stack
IL_002e: br.s IL_005c
In Release mode, there are no difference because of compiler optimizations, so there shouldn't be any differences. In Debug mode, second code pushes variable to the stack, and then pops it again, so it should run slower anyways.
For more accurate results, you should use benchmark libraries like BenchmarkDotNet and should run the benchmark methods for millions or billions times and get the average/mean time.