I wrote two programs. One in Java, the other in C # with exactly the same content, just to compare performance. The results were amazing. After that, I turned to the teacher to find out what was the matter (the Sharp code was executed 8 (!!!) times longer). On his machine (VS 2008) he switched from Debug to Release in the studio, after which the program execution time was reduced by 3 times. I came home and the same trick did not work (VS 2013).

In general, looking for advice on profiles in Visual Studio. How to "enable optimization"?

Sharpe code:

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace BoxingTest { public abstract class BoxedVal { public abstract BoxedVal Add(BoxedVal other); public abstract bool LessThan(BoxedVal other); public abstract bool GreaterThan(BoxedVal other); } public class BoxedInt : BoxedVal { public int Value; public BoxedInt(int value) { Value = value; } public override BoxedVal Add(BoxedVal other) { BoxedInt i = other as BoxedInt; return new BoxedInt(Value + i.Value); } public override bool LessThan(BoxedVal other) { BoxedInt i = other as BoxedInt; return Value < i.Value; } public override bool GreaterThan(BoxedVal other) { BoxedInt i = other as BoxedInt; return Value > i.Value; } } class Program { private static int Fib(int nn) { BoxedVal one = new BoxedInt(1); BoxedVal a = one; BoxedVal b = one; BoxedVal n = new BoxedInt(nn); BoxedVal thousand = new BoxedInt(1000); for (BoxedVal i = new BoxedInt(2); i.LessThan(n); i = i.Add(one)) { BoxedVal c = a.Add(b); a = b; b = c; if (b.GreaterThan(thousand)) { a = one; b = one; } } return (b as BoxedInt).Value; } static void Main(string[] args) { int times = 5; int n = 20000000; int total = 0; for (int i = 0; i < times; i++) { var start = DateTime.Now; int val = Fib(n); int dt = (DateTime.Now - start).Milliseconds; total += dt; Console.WriteLine(val); Console.WriteLine("Elapsed: {0} ms", dt); } Console.WriteLine("Average: {0} ms", total / times); Console.ReadLine(); } } } 

Java code:

 abstract class BoxedVal { public abstract BoxedVal Add(BoxedVal other); public abstract boolean LessThan(BoxedVal other); public abstract boolean GreaterThan(BoxedVal other); } class BoxedInt extends BoxedVal { public int Value; public BoxedInt(int value) { Value = value; } @Override public BoxedVal Add(BoxedVal other) { BoxedInt i = (BoxedInt)other; return new BoxedInt(Value + i.Value); } @Override public boolean LessThan(BoxedVal other) { BoxedInt i = (BoxedInt)other; return Value < i.Value; } @Override public boolean GreaterThan(BoxedVal other) { BoxedInt i = (BoxedInt)other; return Value > i.Value; } } public class BoxingTest { private static int Fib(int nn) { BoxedVal one = new BoxedInt(1); BoxedVal a = one; BoxedVal b = one; BoxedVal n = new BoxedInt(nn); BoxedVal thousand = new BoxedInt(1000); for (BoxedVal i = new BoxedInt(2); i.LessThan(n); i = i.Add(one)) { BoxedVal c = a.Add(b); a = b; b = c; if (b.GreaterThan(thousand)) { a = one; b = one; } } return ((BoxedInt)b).Value; } public static void main(String[] args) { int times = 5; int n = 20000000; long total = 0; for (int i = 0; i<times;i++){ long start = System.currentTimeMillis(); int val = Fib(n); long dt = System.currentTimeMillis() - start; total+= dt; System.out.println(val); System.out.println("Elapsed: "+dt+" ms"); } System.out.println("Average: "+(total/times)+" ms"); } } 
  • Let's code, then you can still talk about something. - Drac5
  • I added the code, but I very much doubt that the matter is in it :) - Toisen
  • Try using Stopwatch instead of DateTime. Well and in C # instead of as try direct castes. BoxedInt i = other as BoxedInt; -> var i = (BoxedInt) other; - Veikedo
  • the profiler opaquely hints that the matter is not at all with DateTime. Most of the time clr.dll works (99.2%), but I will try ^ _ ^ - Toisen
  • In fact, using DateTime.Now in C # and most likely System.currentTimeMillis() gives completely left-handed results. In C #, Stopwatch.StartNew() should be used (this significantly changes the measurement results in this example). And it is worth looking for its counterpart in Java. - PashaPash

1 answer 1

Most likely, you start your application with the F5 button - Start Debugging, and your teacher Ctrl + F5 - Start Without Debugging.

I have a C # code executed next time

  • Debug, with debugger: 756ms
  • Debug, without debugger: 989ms
  • Release, with debugger: 844ms
  • Release, without debugger: 388ms

Java code is running

  • Release (Run): 159ms
  • Debug: 174ms

UPDATE : Funny, increased the constant to 200 million (10 times).

Now C # overtakes: Average: 863 ms

Java: Average: 1296 ms

  • I wonder what the result will be if you remove the strict typing and poke var'ov ...? - Walter Nuss
  • And you can also try using (xxx) {} to poke ... It was also interesting ... - Walter Nuss
  • I ran with different configs (including configs with debug disabled). And it turned out about the same result as you, so I asked this question. I am plagued by vague doubts ... I also tried to increase the constant 10 times and taught the INCREMENT in performance on C # O_o 328 ms initial, against 214 ms after increasing the constant 10 times. It feels like I wrote something wrong, although the programs are mirrored ... As for Java, an increase in the constant leads to a logical increase in the running time. - Toisen
  • @Sharbag, just not var , but dynamic . var simply prints the type as auto in С++ . And using most likely will throw out the optimizer. There are no resources, no exceptions. - atwice
  • @Toisen, I think, to understand why speed is so different, you need to understand the settings of the Runtime environment. How garbage collection is configured, how results caching is configured. How is JIT configured. In general, runtime is still a deep hole. - atwice