Why is my Time algorithm so slow - Can anyone tell me why?

R

Roy Gourgi

Hi,

I am new to C#. I have the same time scheduling program written in C++ and
it is 5 times faster than my version in C#.
Why is it so slow as I thought that C# was only a little slower than C++?
What am I doing wrong?

Here is my code:

using System;

class cMain

{

public static int Main()

{



int[,] TimeSchedule = new int[GlobalValues.kNoDays+1,7]

{

{ 0, 0, 0, 0, 0, 0, 0},

{ 1, 1, 2, 3, 4, 5,49},

{ 2, 23,27,36,38,45,47},

{ 3, 23,33,35,42,44,48},

{ 4, 24,29,35,39,40,46},

{ 5, 22,28,34,40,44,45},

{ 6, 1, 2, 6,11,17,20},

{ 7, 1, 2, 7,10,16,21},

{ 8, 1, 2, 8,13,15,18},

{ 9, 23,26,34,36,41,47},

{ 10, 1, 2, 9,12,14,19},

{ 11, 23,28,31,35,37,42},

{ 12, 25,34,37,40,45,48},

{ 13, 32,33,44,46,47,48},

{ 14, 24,25,26,27,37,48},

{ 15, 24,29,30,32,40,42},

{ 16, 1, 3, 6,10,15,19},

{ 17, 1, 3, 7,11,14,18},

{ 18, 22,23,25,35,42,43},

{ 19, 1, 3, 8,12,17,21},

{ 20, 31,33,34,40,43,45},

{ 21, 30,33,36,39,44,48},

{ 22, 25,29,37,38,41,48},

{ 23, 1, 3, 9,13,16,20},

{ 24, 1, 4, 6,13,14,21},

{ 25, 24,25,28,33,41,45},

{ 26, 22,26,31,38,40,48},

{ 27, 1, 4, 7,12,15,20},

{ 28, 24,26,27,31,33,43},

{ 29, 23,27,32,39,40,41},

{ 30, 1, 4, 8,11,16,19},

{ 31, 22,25,32,43,46,47},

{ 32, 22,33,37,39,42,47},

{ 33, 1, 4, 9,10,17,18},

{ 34, 27,35,38,39,45,46},

{ 35, 1, 5, 6,12,16,18},

{ 36, 1, 5, 7,13,17,19},

{ 37, 1, 5, 8,10,14,20},

{ 38, 1, 5, 9,11,15,21},

{ 39, 1, 6, 7, 8, 9,49},

{ 40, 26,29,36,42,45,46},

{ 41, 1,10,11,12,13,49},

{ 42, 1,14,15,16,17,49},

{ 43, 1,18,19,20,21,49},

{ 44, 28,31,32,37,46,47},

{ 45, 22,25,30,36,39,43},

{ 46, 24,37,41,43,44,45},

{ 47, 26,34,35,39,41,46},

{ 48, 27,30,32,38,42,45},

{ 49, 22,24,26,27,28,44},

{ 50, 23,24,32,34,38,39},

{ 51, 22,32,33,35,36,37},

{ 52, 22,28,29,38,41,44},

{ 53, 28,39,42,43,47,48},

{ 54, 27,30,35,40,41,47},

{ 55, 2, 3, 6, 7,12,13},

{ 56, 27,36,40,41,42,46},

{ 57, 2, 3, 8, 9,10,11},

{ 58, 28,30,31,36,37,39},

{ 59, 2, 3,14,15,20,21},

{ 60, 23,24,29,36,40,47},

{ 61, 29,31,33,38,41,43},

{ 62, 2, 3,16,17,18,19},

{ 63, 26,29,30,35,45,47},

{ 64, 22,25,27,29,34,43},

{ 65, 2, 4, 6, 9,15,16},

{ 66, 26,37,38,40,43,44},

{ 67, 26,30,32,34,41,42},

{ 68, 23,30,31,33,43,46},

{ 69, 25,31,35,39,44,47},

{ 70, 2, 4, 7, 8,14,17},

{ 71, 2, 4,10,13,19,20},

{ 72, 2, 4,11,12,18,21},

{ 73, 24,34,36,38,42,46},

{ 74, 2, 5, 6, 8,19,21},

{ 75, 2, 5, 7, 9,18,20},

{ 76, 22,24,31,41,45,48},

{ 77, 25,26,28,33,38,40},

{ 78, 2, 5,10,12,15,17},

{ 79, 2, 5,11,13,14,16},

{ 80, 2, 6,10,14,18,49},

{ 81, 2, 7,11,15,19,49},

{ 82, 2, 8,12,16,20,49},

{ 83, 2, 9,13,17,21,49},

{ 84, 23,26,29,32,39,45},

{ 85, 24,30,34,35,38,47},

{ 86, 3, 4, 6, 8,18,20},

{ 87, 3, 4, 7, 9,19,21},

{ 88, 3, 4,10,12,14,16},

{ 89, 3, 4,11,13,15,17},

{ 90, 3, 5, 6, 9,14,17},

{ 91, 3, 5, 7, 8,15,16},

{ 92, 27,28,29,31,34,37},

{ 93, 23,25,30,37,46,48},

{ 94, 3, 5,10,13,18,21},

{ 95, 3, 5,11,12,19,20},

{ 96, 3, 6,11,16,21,49},

{ 97, 3, 7,10,17,20,49},

{ 98, 6, 7,14,16,19,20},

{ 99, 3, 8,13,14,19,49},

{100, 3, 9,12,15,18,49},

{101, 6, 7,15,17,18,21},

{102, 6, 8,10,13,16,17},

{103, 6, 8,11,12,14,15},

{104, 6, 9,10,12,20,21},

{105, 6, 9,11,13,18,19},

{106, 25,31,32,35,36,44},

{107, 4, 5, 8, 9,12,13},

{108, 4, 5,14,15,18,19},

{109, 4, 5,16,17,20,21},

{110, 4, 6,12,17,19,49},

{111, 4, 7,13,16,18,49},

{112, 7, 8,10,12,18,19},

{113, 7, 8,11,13,20,21},

{114, 7, 9,10,13,14,15},

{115, 7, 9,11,12,16,17},

{116, 8, 9,14,16,18,21},

{117, 8, 9,15,17,19,20},

{118, 10,11,14,17,19,21},

{119, 10,11,15,16,18,20},

{120, 12,13,14,17,18,20},

{121, 12,13,15,16,19,21},

{122, 4, 8,10,15,21,49},

{123, 4, 9,11,14,20,49},

{124, 5, 6,13,15,20,49},

{125, 5, 7,12,14,21,49},

{126, 5, 8,11,17,18,49},

{127, 5, 9,10,16,19,49},

{128, 4, 5, 6, 7,10,11},

{129, 22,23,28,30,44,46},

{130, 27,29,33,34,44,48},

{131, 28,32,36,42,43,48},

{132, 25,26,31,40,41,44},

{133, 24,28,38,40,43,48},

{134, 28,35,36,43,47,48},

{135, 24,25,31,38,44,45},

{136, 26,28,41,43,45,48},

{137, 25,28,29,33,44,46},

{138, 27,30,31,37,43,44},

{139, 22,23,25,31,34,48},

{140, 23,25,27,28,33,37},

{141, 22,29,30,31,33,48},

{142, 22,34,37,43,44,46},

{143, 25,31,36,42,44,47},

{144, 38,39,40,41,42,47},

{145, 22,26,33,37,38,45},

{146, 24,27,34,39,42,47},

{147, 23,26,32,35,42,45},

{148, 28,32,35,39,43,48},

{149, 23,29,37,43,44,48},

{150, 22,27,28,31,46,48},

{151, 22,24,33,37,40,41},

{152, 25,28,30,33,34,43},

{153, 23,30,34,38,40,46},

{154, 26,30,32,36,39,45},

{155, 27,29,34,35,38,41},

{156, 26,29,32,45,46,47},

{157, 23,24,27,30,41,46},

{158, 23,29,30,36,39,42},

{159, 25,31,32,39,42,44},

{160, 24,32,35,36,38,41},

{161, 24,26,27,29,40,45},

{162, 27,32,34,35,36,40},

{163, 23,30,35,36,46,47}};

for (int lpcnt=1; lpcnt<=GlobalValues.kNoSeconds; lpcnt++)
GlobalValues.gaSumWorkDays[lpcnt]=0;

for (int mm=1 ; mm<=GlobalValues.kNoDays ; mm++)

{

GlobalValues.gaWorkDays[1]=TimeSchedule[mm,1];

GlobalValues.gaWorkDays[2]=TimeSchedule[mm,2];

GlobalValues.gaWorkDays[3]=TimeSchedule[mm,3];

GlobalValues.gaWorkDays[4]=TimeSchedule[mm,4];

GlobalValues.gaWorkDays[5]=TimeSchedule[mm,5];

GlobalValues.gaWorkDays[6]=TimeSchedule[mm,6];

CWeekTime.WeekTime();

}


int lnTotMissingTime=0;

int t = DateTime.Now.Minute*60+DateTime.Now.Second;

Console.WriteLine("TimeStarted "+t);

lnTotMissingTime=CVerifyMissingTime.VerifyMissingTime();


Console.WriteLine("Total No of Missing Time {0} ",lnTotMissingTime);

t = DateTime.Now.Minute*60+DateTime.Now.Second;

Console.WriteLine("Time Ended "+t);

Console.ReadLine();

return 0;

}

}



public class GlobalValues

{

public const int kNoWeeks=49;

public const int kNoDays=163;

public const int kNoSeconds=18424;

public static int gnSumSeconds = 0;

public static int[] gaWorkDays= new int [7];

public static int[] gaSumWorkDays = new int[kNoSeconds+1];





public static int[,] gaSeconds = new int [kNoWeeks+1,4]

{

{0, 0, 0, 0},

{1, 0, 0, 0},

{2, 1081, 0, 0},

{3, 2116, 46, 1},

{4, 3106, 91, 2},

{5, 4052, 135, 3},

{6, 4955, 178, 4},

{7, 5816, 220, 5},

{8, 6636, 261, 6},

{9, 7416, 301, 7},

{10, 8157, 340, 8},

{11, 8860, 378, 9},

{12, 9526, 415, 10},

{13, 10156, 451, 11},

{14, 10751, 486, 12},

{15, 11312, 520, 13},

{16, 11840, 553, 14},

{17, 12336, 585, 15},

{18, 12801, 616, 16},

{19, 13236, 646, 17},

{20, 13642, 675, 18},

{21, 14020, 703, 19},

{22, 14371, 730, 20},

{23, 14696, 756, 21},

{24, 14996, 781, 22},

{25, 15272, 805, 23},

{26, 15525, 828, 24},

{27, 15756, 850, 25},

{28, 15966, 871, 26},

{29, 16156, 891, 27},

{30, 16327, 910, 28},

{31, 16480, 928, 29},

{32, 16616, 945, 30},

{33, 16736, 961, 31},

{34, 16841, 976, 32},

{35, 16932, 990, 33},

{36, 17010, 1003, 34},

{37, 17076, 1015, 35},

{38, 17131, 1026, 36},

{39, 17176, 1036, 37},

{40, 17212, 1045, 38},

{41, 17240, 1053, 39},

{42, 17261, 1060, 40},

{43, 17276, 1066, 41},

{44, 17286, 1071, 42},

{45, 17292, 1075, 43},

{46, 17295, 1078, 44},

{47, 17296, 1080, 45},

{48, 0, 1081, 46},

{49, 0, 0, 47}};

}



class CWeekTime

{

public static int WeekTime()

{

for (int s1=1 ; s1<=4 ; s1++)

{

for (int s2=s1+1 ; s2<=5 ; s2++)

{

for (int s3=s2+1 ; s3<=6 ; s3++)

{

GlobalValues.gnSumSeconds=GlobalValues.gaSeconds[GlobalValues.gaWorkDays[s1],1]+GlobalValues.gaSeconds[GlobalValues.gaWorkDays[s2],2]+GlobalValues.gaSeconds[GlobalValues.gaWorkDays[s3],3];

GlobalValues.gaSumWorkDays[GlobalValues.gnSumSeconds]=1;

}

}

}

return (0);

}

}

class CVerifyMissingTime

{

public static int VerifyMissingTime()

{

int lnSumMissingTime=0;

for (int xxxLoop=1 ; xxxLoop<=10; xxxLoop++)

{

lnSumMissingTime=0;

for (int lp1=1 ; lp1<=GlobalValues.kNoWeeks-5 ; lp1++)

{

for (int lp2=lp1+1 ; lp2<=GlobalValues.kNoWeeks-4 ; lp2++)

{

for (int lp3=lp2+1 ; lp3<=GlobalValues.kNoWeeks-3 ; lp3++)

{

for (int lp4=lp3+1 ; lp4<=GlobalValues.kNoWeeks-2 ; lp4++)

{

for (int lp5=lp4+1 ; lp5<=GlobalValues.kNoWeeks-1 ; lp5++)

{

for (int lp6=lp5+1 ; lp6<=GlobalValues.kNoWeeks ; lp6++)

{



if
(GlobalValues.gaSumWorkDays[GlobalValues.gaSeconds[lp1,1]+GlobalValues.gaSeconds[lp2,2]+GlobalValues.gaSeconds[lp3,3]]>0)

{

lp6=lp5=lp4=100;

continue;

}

if
(GlobalValues.gaSumWorkDays[GlobalValues.gaSeconds[lp1,1]+GlobalValues.gaSeconds[lp2,2]+GlobalValues.gaSeconds[lp4,3]]>0)

{

lp6=lp5=100;

continue;

}

if
(GlobalValues.gaSumWorkDays[GlobalValues.gaSeconds[lp1,1]+GlobalValues.gaSeconds[lp3,2]+GlobalValues.gaSeconds[lp4,3]]>0)

{

lp6=lp5=100;

continue;

}

if
(GlobalValues.gaSumWorkDays[GlobalValues.gaSeconds[lp2,1]+GlobalValues.gaSeconds[lp3,2]+GlobalValues.gaSeconds[lp4,3]]>0)

{

lp6=lp5=100;

continue;

}

if
(GlobalValues.gaSumWorkDays[GlobalValues.gaSeconds[lp1,1]+GlobalValues.gaSeconds[lp2,2]+GlobalValues.gaSeconds[lp5,3]]>0)

{

lp6=100;

continue;

}

if
(GlobalValues.gaSumWorkDays[GlobalValues.gaSeconds[lp1,1]+GlobalValues.gaSeconds[lp3,2]+GlobalValues.gaSeconds[lp5,3]]>0)

{

lp6=100;

continue;

}

if
(GlobalValues.gaSumWorkDays[GlobalValues.gaSeconds[lp1,1]+GlobalValues.gaSeconds[lp4,2]+GlobalValues.gaSeconds[lp5,3]]>0)

{

lp6=100;

continue;

}

if
(GlobalValues.gaSumWorkDays[GlobalValues.gaSeconds[lp2,1]+GlobalValues.gaSeconds[lp3,2]+GlobalValues.gaSeconds[lp5,3]]>0)

{

lp6=100;

continue;

}

if
(GlobalValues.gaSumWorkDays[GlobalValues.gaSeconds[lp2,1]+GlobalValues.gaSeconds[lp4,2]+GlobalValues.gaSeconds[lp5,3]]>0)

{

lp6=100;

continue;

}

if
(GlobalValues.gaSumWorkDays[GlobalValues.gaSeconds[lp3,1]+GlobalValues.gaSeconds[lp4,2]+GlobalValues.gaSeconds[lp5,3]]>0)

{

lp6=100;

continue;

}

if
(GlobalValues.gaSumWorkDays[GlobalValues.gaSeconds[lp1,1]+GlobalValues.gaSeconds[lp2,2]+GlobalValues.gaSeconds[lp6,3]]>0)

{

continue;

}

if
(GlobalValues.gaSumWorkDays[GlobalValues.gaSeconds[lp1,1]+GlobalValues.gaSeconds[lp3,2]+GlobalValues.gaSeconds[lp6,3]]>0)

{

continue;

}

if
(GlobalValues.gaSumWorkDays[GlobalValues.gaSeconds[lp1,1]+GlobalValues.gaSeconds[lp4,2]+GlobalValues.gaSeconds[lp6,3]]>0)

{

continue;

}

if
(GlobalValues.gaSumWorkDays[GlobalValues.gaSeconds[lp1,1]+GlobalValues.gaSeconds[lp5,2]+GlobalValues.gaSeconds[lp6,3]]>0)

{

continue;

}

if
(GlobalValues.gaSumWorkDays[GlobalValues.gaSeconds[lp2,1]+GlobalValues.gaSeconds[lp3,2]+GlobalValues.gaSeconds[lp6,3]]>0)

{

continue;

}

if
(GlobalValues.gaSumWorkDays[GlobalValues.gaSeconds[lp2,1]+GlobalValues.gaSeconds[lp4,2]+GlobalValues.gaSeconds[lp6,3]]>0)

{

continue;

}

if
(GlobalValues.gaSumWorkDays[GlobalValues.gaSeconds[lp2,1]+GlobalValues.gaSeconds[lp5,2]+GlobalValues.gaSeconds[lp6,3]]>0)

{

continue;

}

if
(GlobalValues.gaSumWorkDays[GlobalValues.gaSeconds[lp3,1]+GlobalValues.gaSeconds[lp4,2]+GlobalValues.gaSeconds[lp6,3]]>0)

{

continue;

}

if
(GlobalValues.gaSumWorkDays[GlobalValues.gaSeconds[lp3,1]+GlobalValues.gaSeconds[lp5,2]+GlobalValues.gaSeconds[lp6,3]]>0)

{

continue;

}

if
(GlobalValues.gaSumWorkDays[GlobalValues.gaSeconds[lp4,1]+GlobalValues.gaSeconds[lp5,2]+GlobalValues.gaSeconds[lp6,3]]>0)

{

continue;

}

lnSumMissingTime++;

}

}

}

}

}

}

}

Console.WriteLine("Missing Time {0}",lnSumMissingTime);

return lnSumMissingTime;

}



}

TIA

Roy
 
R

Roy Gourgi

Hi,

Basically, for all intensive purposes all I have is 2 arrays (gaSeconds &
TimeSchedule). The array gaSeconds as you can see, has to be accessed many,
many times and for this application, it cannot absolutely be a jagged array.
The values in the gaSeconds in the real application change, but I kept them
constant for the sake of simplicity, so although it looks that I am
aimlessly accessing the same information many times in the
CVerifyMissingTime, I am not.

All I wanted to know if there is a way to make this faster. I am not that
worried about wheter it is in classic object oriented programming form as
speed is of the essence.

So basically this is the program in a more intuitive way:


I have to create 2 arrays (that can be seen throughout the whole program)
and one of which will be accessed many times.


Thanks
Roy
 
J

Jon Skeet [C# MVP]

Roy Gourgi said:
I am new to C#. I have the same time scheduling program written in C++ and
it is 5 times faster than my version in C#.
Why is it so slow as I thought that C# was only a little slower than C++?
What am I doing wrong?

Well, you haven't shown your C++ code, you haven't said what the
program is meant to be doing, and the code is frighteningly difficult
to understand (partly due to not being object-oriented at all, as far
as I can see), which doesn't really help.

I would start by refactoring it into a much easier to understand form,
and *then* look at the efficiency of it.

You could also try using jagged arrays instead of rectangular ones -
that's more efficient in .NET, and as the majority of your time seems
to be spent in that rather large set of if statements which do very
little other than array access, that could make a significant
difference.
 
R

Roy Gourgi

Hi Marcus,

WOW that is good indeed. That is even faster than the time I was getting in
C++. :) I am not that good at C++ either, mind you. :)

But I do not understand how you got it to be so much faster, as it is now
about 6 times faster than before. Where is most of the time gain coming
from? I will try to disect what you did and also try to apply it to my C++
program.

Finally, I don't understand what you mean by making gaSeconds jagged at the
beginning and then changing it to multidimensional in the rest of the
program. How would that be done?

Thanks a lot, I appreciate it.

Roy


Marcus Andrén said:
Hi,

I am new to C#. I have the same time scheduling program written in C++ and
it is 5 times faster than my version in C#.
Why is it so slow as I thought that C# was only a little slower than C++?
What am I doing wrong?

First of all, in my experience c# isn't very good at handling multi
level loops so don't expect to ever get C++ performance with an
algorithm like that with the current c# compiler.

I can see a few ways of optimizing the code. The big winner as Jon
Skeet already suggested is to used make gaSeconsds jagged instead of
multidimensional. Even if it has to be multidimensional in the rest of
the program it will still pay off to convert it to jagged formet
before doing the calculations. This is the best way to increase
performance and will almost half the running time.

You recalculate quite a few of the array accesses multiple times. They
could be calculated and stored in local variables in the outer for
loops.

Finally replacing lp6=100; continue; with break; will give a small
performance boost.


Here is a rewrite of your code that runs a lot faster:


using System;

class cMain
{
public static int Main()
{
int[,] TimeSchedule = new int[GlobalValues.kNoDays + 1, 7]
{
{ 0, 0, 0, 0, 0, 0, 0},
{ 1, 1, 2, 3, 4, 5,49},
{ 2, 23,27,36,38,45,47},
{ 3, 23,33,35,42,44,48},
{ 4, 24,29,35,39,40,46},
{ 5, 22,28,34,40,44,45},
{ 6, 1, 2, 6,11,17,20},
{ 7, 1, 2, 7,10,16,21},
{ 8, 1, 2, 8,13,15,18},
{ 9, 23,26,34,36,41,47},
{ 10, 1, 2, 9,12,14,19},
{ 11, 23,28,31,35,37,42},
{ 12, 25,34,37,40,45,48},
{ 13, 32,33,44,46,47,48},
{ 14, 24,25,26,27,37,48},
{ 15, 24,29,30,32,40,42},
{ 16, 1, 3, 6,10,15,19},
{ 17, 1, 3, 7,11,14,18},
{ 18, 22,23,25,35,42,43},
{ 19, 1, 3, 8,12,17,21},
{ 20, 31,33,34,40,43,45},
{ 21, 30,33,36,39,44,48},
{ 22, 25,29,37,38,41,48},
{ 23, 1, 3, 9,13,16,20},
{ 24, 1, 4, 6,13,14,21},
{ 25, 24,25,28,33,41,45},
{ 26, 22,26,31,38,40,48},
{ 27, 1, 4, 7,12,15,20},
{ 28, 24,26,27,31,33,43},
{ 29, 23,27,32,39,40,41},
{ 30, 1, 4, 8,11,16,19},
{ 31, 22,25,32,43,46,47},
{ 32, 22,33,37,39,42,47},
{ 33, 1, 4, 9,10,17,18},
{ 34, 27,35,38,39,45,46},
{ 35, 1, 5, 6,12,16,18},
{ 36, 1, 5, 7,13,17,19},
{ 37, 1, 5, 8,10,14,20},
{ 38, 1, 5, 9,11,15,21},
{ 39, 1, 6, 7, 8, 9,49},
{ 40, 26,29,36,42,45,46},
{ 41, 1,10,11,12,13,49},
{ 42, 1,14,15,16,17,49},
{ 43, 1,18,19,20,21,49},
{ 44, 28,31,32,37,46,47},
{ 45, 22,25,30,36,39,43},
{ 46, 24,37,41,43,44,45},
{ 47, 26,34,35,39,41,46},
{ 48, 27,30,32,38,42,45},
{ 49, 22,24,26,27,28,44},
{ 50, 23,24,32,34,38,39},
{ 51, 22,32,33,35,36,37},
{ 52, 22,28,29,38,41,44},
{ 53, 28,39,42,43,47,48},
{ 54, 27,30,35,40,41,47},
{ 55, 2, 3, 6, 7,12,13},
{ 56, 27,36,40,41,42,46},
{ 57, 2, 3, 8, 9,10,11},
{ 58, 28,30,31,36,37,39},
{ 59, 2, 3,14,15,20,21},
{ 60, 23,24,29,36,40,47},
{ 61, 29,31,33,38,41,43},
{ 62, 2, 3,16,17,18,19},
{ 63, 26,29,30,35,45,47},
{ 64, 22,25,27,29,34,43},
{ 65, 2, 4, 6, 9,15,16},
{ 66, 26,37,38,40,43,44},
{ 67, 26,30,32,34,41,42},
{ 68, 23,30,31,33,43,46},
{ 69, 25,31,35,39,44,47},
{ 70, 2, 4, 7, 8,14,17},
{ 71, 2, 4,10,13,19,20},
{ 72, 2, 4,11,12,18,21},
{ 73, 24,34,36,38,42,46},
{ 74, 2, 5, 6, 8,19,21},
{ 75, 2, 5, 7, 9,18,20},
{ 76, 22,24,31,41,45,48},
{ 77, 25,26,28,33,38,40},
{ 78, 2, 5,10,12,15,17},
{ 79, 2, 5,11,13,14,16},
{ 80, 2, 6,10,14,18,49},
{ 81, 2, 7,11,15,19,49},
{ 82, 2, 8,12,16,20,49},
{ 83, 2, 9,13,17,21,49},
{ 84, 23,26,29,32,39,45},
{ 85, 24,30,34,35,38,47},
{ 86, 3, 4, 6, 8,18,20},
{ 87, 3, 4, 7, 9,19,21},
{ 88, 3, 4,10,12,14,16},
{ 89, 3, 4,11,13,15,17},
{ 90, 3, 5, 6, 9,14,17},
{ 91, 3, 5, 7, 8,15,16},
{ 92, 27,28,29,31,34,37},
{ 93, 23,25,30,37,46,48},
{ 94, 3, 5,10,13,18,21},
{ 95, 3, 5,11,12,19,20},
{ 96, 3, 6,11,16,21,49},
{ 97, 3, 7,10,17,20,49},
{ 98, 6, 7,14,16,19,20},
{ 99, 3, 8,13,14,19,49},
{100, 3, 9,12,15,18,49},
{101, 6, 7,15,17,18,21},
{102, 6, 8,10,13,16,17},
{103, 6, 8,11,12,14,15},
{104, 6, 9,10,12,20,21},
{105, 6, 9,11,13,18,19},
{106, 25,31,32,35,36,44},
{107, 4, 5, 8, 9,12,13},
{108, 4, 5,14,15,18,19},
{109, 4, 5,16,17,20,21},
{110, 4, 6,12,17,19,49},
{111, 4, 7,13,16,18,49},
{112, 7, 8,10,12,18,19},
{113, 7, 8,11,13,20,21},
{114, 7, 9,10,13,14,15},
{115, 7, 9,11,12,16,17},
{116, 8, 9,14,16,18,21},
{117, 8, 9,15,17,19,20},
{118, 10,11,14,17,19,21},
{119, 10,11,15,16,18,20},
{120, 12,13,14,17,18,20},
{121, 12,13,15,16,19,21},
{122, 4, 8,10,15,21,49},
{123, 4, 9,11,14,20,49},
{124, 5, 6,13,15,20,49},
{125, 5, 7,12,14,21,49},
{126, 5, 8,11,17,18,49},
{127, 5, 9,10,16,19,49},
{128, 4, 5, 6, 7,10,11},
{129, 22,23,28,30,44,46},
{130, 27,29,33,34,44,48},
{131, 28,32,36,42,43,48},
{132, 25,26,31,40,41,44},
{133, 24,28,38,40,43,48},
{134, 28,35,36,43,47,48},
{135, 24,25,31,38,44,45},
{136, 26,28,41,43,45,48},
{137, 25,28,29,33,44,46},
{138, 27,30,31,37,43,44},
{139, 22,23,25,31,34,48},
{140, 23,25,27,28,33,37},
{141, 22,29,30,31,33,48},
{142, 22,34,37,43,44,46},
{143, 25,31,36,42,44,47},
{144, 38,39,40,41,42,47},
{145, 22,26,33,37,38,45},
{146, 24,27,34,39,42,47},
{147, 23,26,32,35,42,45},
{148, 28,32,35,39,43,48},
{149, 23,29,37,43,44,48},
{150, 22,27,28,31,46,48},
{151, 22,24,33,37,40,41},
{152, 25,28,30,33,34,43},
{153, 23,30,34,38,40,46},
{154, 26,30,32,36,39,45},
{155, 27,29,34,35,38,41},
{156, 26,29,32,45,46,47},
{157, 23,24,27,30,41,46},
{158, 23,29,30,36,39,42},
{159, 25,31,32,39,42,44},
{160, 24,32,35,36,38,41},
{161, 24,26,27,29,40,45},
{162, 27,32,34,35,36,40},
{163, 23,30,35,36,46,47}};

for (int lpcnt = 1; lpcnt <= GlobalValues.kNoSeconds; lpcnt++)
GlobalValues.gaSumWorkDays[lpcnt] = 0;

for (int mm = 1; mm <= GlobalValues.kNoDays; mm++)
{
GlobalValues.gaWorkDays[1] = TimeSchedule[mm, 1];
GlobalValues.gaWorkDays[2] = TimeSchedule[mm, 2];
GlobalValues.gaWorkDays[3] = TimeSchedule[mm, 3];
GlobalValues.gaWorkDays[4] = TimeSchedule[mm, 4];
GlobalValues.gaWorkDays[5] = TimeSchedule[mm, 5];
GlobalValues.gaWorkDays[6] = TimeSchedule[mm, 6];
CWeekTime.WeekTime();
}


int lnTotMissingTime = 0;



DateTime start = DateTime.Now;

//Create gaSeconds2 from gaSeconds
for (int i = 0; i < GlobalValues.gaSeconds2.Length; i++)
{
GlobalValues.gaSeconds2 = new int[4];
for (int j = 0; j < 4; j++)
GlobalValues.gaSeconds2[j] =
GlobalValues.gaSeconds[i, j];
}

lnTotMissingTime = CVerifyMissingTime.VerifyMissingTime();
Console.WriteLine("Total No of Missing Time {0} ",
lnTotMissingTime);

Console.WriteLine(DateTime.Now-start);

Console.ReadLine();

return 0;

}
}

public class GlobalValues
{
public static int[][] gaSeconds2 = new int[kNoWeeks +1][];
public const int kNoWeeks = 49;
public const int kNoDays = 163;
public const int kNoSeconds = 18424;
public static int gnSumSeconds = 0;
public static int[] gaWorkDays = new int[7];
public static int[] gaSumWorkDays = new int[kNoSeconds + 1];

public static int[,] gaSeconds = new int[kNoWeeks + 1, 4]
{
{0, 0, 0, 0},
{1, 0, 0, 0},
{2, 1081, 0, 0},
{3, 2116, 46, 1},
{4, 3106, 91, 2},
{5, 4052, 135, 3},
{6, 4955, 178, 4},
{7, 5816, 220, 5},
{8, 6636, 261, 6},
{9, 7416, 301, 7},
{10, 8157, 340, 8},
{11, 8860, 378, 9},
{12, 9526, 415, 10},
{13, 10156, 451, 11},
{14, 10751, 486, 12},
{15, 11312, 520, 13},
{16, 11840, 553, 14},
{17, 12336, 585, 15},
{18, 12801, 616, 16},
{19, 13236, 646, 17},
{20, 13642, 675, 18},
{21, 14020, 703, 19},
{22, 14371, 730, 20},
{23, 14696, 756, 21},
{24, 14996, 781, 22},
{25, 15272, 805, 23},
{26, 15525, 828, 24},
{27, 15756, 850, 25},
{28, 15966, 871, 26},
{29, 16156, 891, 27},
{30, 16327, 910, 28},
{31, 16480, 928, 29},
{32, 16616, 945, 30},
{33, 16736, 961, 31},
{34, 16841, 976, 32},
{35, 16932, 990, 33},
{36, 17010, 1003, 34},
{37, 17076, 1015, 35},
{38, 17131, 1026, 36},
{39, 17176, 1036, 37},
{40, 17212, 1045, 38},
{41, 17240, 1053, 39},
{42, 17261, 1060, 40},
{43, 17276, 1066, 41},
{44, 17286, 1071, 42},
{45, 17292, 1075, 43},
{46, 17295, 1078, 44},
{47, 17296, 1080, 45},
{48, 0, 1081, 46},
{49, 0, 0, 47}};
}

class CWeekTime
{
public static int WeekTime()
{
for (int s1 = 1; s1 <= 4; s1++)
{
for (int s2 = s1 + 1; s2 <= 5; s2++)
{
for (int s3 = s2 + 1; s3 <= 6; s3++)
{
GlobalValues.gnSumSeconds =
GlobalValues.gaSeconds[GlobalValues.gaWorkDays[s1], 1] +
GlobalValues.gaSeconds[GlobalValues.gaWorkDays[s2], 2] +
GlobalValues.gaSeconds[GlobalValues.gaWorkDays[s3], 3];

GlobalValues.gaSumWorkDays[GlobalValues.gnSumSeconds] = 1;
}
}
}
return (0);
}
}

class CVerifyMissingTime
{


public static int VerifyMissingTime()
{
int lnSumMissingTime = 0;

for (int xxxLoop = 1; xxxLoop <= 10; xxxLoop++)
{
lnSumMissingTime = 0;

for (int lp1 = 1; lp1 <= GlobalValues.kNoWeeks - 5; lp1++)
{
int lp11 = GlobalValues.gaSeconds2[lp1][1];

for (int lp2 = lp1 + 1; lp2 <= GlobalValues.kNoWeeks -
4; lp2++)
{
int lp21 = GlobalValues.gaSeconds2[lp2][1];
int lp22 = GlobalValues.gaSeconds2[lp2][2];
//(lp2 <= 2 || lp2 == 49) ? 0 : (lp2 - 2) * (95 - lp2) / 2;
//Lookup is faster

for (int lp3 = lp2 + 1; lp3 <=
GlobalValues.kNoWeeks - 3; lp3++)
{
int lp31 = GlobalValues.gaSeconds2[lp3][1];
int lp32 = GlobalValues.gaSeconds2[lp3][2];
int lp33 = GlobalValues.gaSeconds2[lp3][3];

for (int lp4 = lp3 + 1; lp4 <=
GlobalValues.kNoWeeks - 2; lp4++)
{
int lp41 =
GlobalValues.gaSeconds2[lp4][1];
int lp42 =
GlobalValues.gaSeconds2[lp4][2];
int lp43 =
GlobalValues.gaSeconds2[lp4][3];

for (int lp5 = lp4 + 1; lp5 <=
GlobalValues.kNoWeeks - 1; lp5++)
{
int lp52 =
GlobalValues.gaSeconds2[lp5][2];
int lp53 =
GlobalValues.gaSeconds2[lp5][3];

for (int lp6 = lp5 + 1; lp6 <=
GlobalValues.kNoWeeks; lp6++)
{
if (

GlobalValues.gaSumWorkDays[lp11 + lp22 + lp33] > 0)
{
goto breakOut4;
}
else if (

(GlobalValues.gaSumWorkDays[lp11 + lp22 + lp43] > 0)
||

(GlobalValues.gaSumWorkDays[lp11 + lp32 + lp43] > 0)
||

(GlobalValues.gaSumWorkDays[lp21 + lp32 + lp43] > 0))
{
goto breakOut5;
}

if (

(GlobalValues.gaSumWorkDays[lp11 + lp22 + lp53] > 0)
||

(GlobalValues.gaSumWorkDays[lp11 + lp32 + lp53] > 0)
||

(GlobalValues.gaSumWorkDays[lp11 + lp42 + lp53] > 0)
||

(GlobalValues.gaSumWorkDays[lp21 + lp32 + lp53] > 0)
||

(GlobalValues.gaSumWorkDays[lp21 + lp42 + lp53] > 0)
||

(GlobalValues.gaSumWorkDays[lp31 + lp42 + lp53] > 0))
{
break;
}

int lp63 =
GlobalValues.gaSeconds2[lp6][3];

if (
(GlobalValues.gaSumWorkDays[lp11 +
lp22 + lp63] > 0)
||
(GlobalValues.gaSumWorkDays[lp11 +
lp32 + lp63] > 0)
||
(GlobalValues.gaSumWorkDays[lp11 +
lp42 + lp63] > 0)
||
(GlobalValues.gaSumWorkDays[lp11 +
lp52 + lp63] > 0)
||
(GlobalValues.gaSumWorkDays[lp21 +
lp32 + lp63] > 0)
||
(GlobalValues.gaSumWorkDays[lp21 +
lp42 + lp63] > 0)
||
(GlobalValues.gaSumWorkDays[lp21 +
lp52 + lp63] > 0)
||
(GlobalValues.gaSumWorkDays[lp31 +
lp42 + lp63] > 0)
||
(GlobalValues.gaSumWorkDays[lp31 +
lp52 + lp63] > 0)
||
(GlobalValues.gaSumWorkDays[lp41 +
lp52 + lp63] > 0))
{
continue;
}

lnSumMissingTime++;

}
}
breakOut5: ;
}
breakOut4: ;
}
}
}
}
Console.WriteLine("Missing Time {0}", lnSumMissingTime);

return lnSumMissingTime;

}
}
 
M

Marcus Andrén

Hi,

I am new to C#. I have the same time scheduling program written in C++ and
it is 5 times faster than my version in C#.
Why is it so slow as I thought that C# was only a little slower than C++?
What am I doing wrong?

First of all, in my experience c# isn't very good at handling multi
level loops so don't expect to ever get C++ performance with an
algorithm like that with the current c# compiler.

I can see a few ways of optimizing the code. The big winner as Jon
Skeet already suggested is to used make gaSeconsds jagged instead of
multidimensional. Even if it has to be multidimensional in the rest of
the program it will still pay off to convert it to jagged formet
before doing the calculations. This is the best way to increase
performance and will almost half the running time.

You recalculate quite a few of the array accesses multiple times. They
could be calculated and stored in local variables in the outer for
loops.

Finally replacing lp6=100; continue; with break; will give a small
performance boost.


Here is a rewrite of your code that runs a lot faster:


using System;

class cMain
{
public static int Main()
{
int[,] TimeSchedule = new int[GlobalValues.kNoDays + 1, 7]
{
{ 0, 0, 0, 0, 0, 0, 0},
{ 1, 1, 2, 3, 4, 5,49},
{ 2, 23,27,36,38,45,47},
{ 3, 23,33,35,42,44,48},
{ 4, 24,29,35,39,40,46},
{ 5, 22,28,34,40,44,45},
{ 6, 1, 2, 6,11,17,20},
{ 7, 1, 2, 7,10,16,21},
{ 8, 1, 2, 8,13,15,18},
{ 9, 23,26,34,36,41,47},
{ 10, 1, 2, 9,12,14,19},
{ 11, 23,28,31,35,37,42},
{ 12, 25,34,37,40,45,48},
{ 13, 32,33,44,46,47,48},
{ 14, 24,25,26,27,37,48},
{ 15, 24,29,30,32,40,42},
{ 16, 1, 3, 6,10,15,19},
{ 17, 1, 3, 7,11,14,18},
{ 18, 22,23,25,35,42,43},
{ 19, 1, 3, 8,12,17,21},
{ 20, 31,33,34,40,43,45},
{ 21, 30,33,36,39,44,48},
{ 22, 25,29,37,38,41,48},
{ 23, 1, 3, 9,13,16,20},
{ 24, 1, 4, 6,13,14,21},
{ 25, 24,25,28,33,41,45},
{ 26, 22,26,31,38,40,48},
{ 27, 1, 4, 7,12,15,20},
{ 28, 24,26,27,31,33,43},
{ 29, 23,27,32,39,40,41},
{ 30, 1, 4, 8,11,16,19},
{ 31, 22,25,32,43,46,47},
{ 32, 22,33,37,39,42,47},
{ 33, 1, 4, 9,10,17,18},
{ 34, 27,35,38,39,45,46},
{ 35, 1, 5, 6,12,16,18},
{ 36, 1, 5, 7,13,17,19},
{ 37, 1, 5, 8,10,14,20},
{ 38, 1, 5, 9,11,15,21},
{ 39, 1, 6, 7, 8, 9,49},
{ 40, 26,29,36,42,45,46},
{ 41, 1,10,11,12,13,49},
{ 42, 1,14,15,16,17,49},
{ 43, 1,18,19,20,21,49},
{ 44, 28,31,32,37,46,47},
{ 45, 22,25,30,36,39,43},
{ 46, 24,37,41,43,44,45},
{ 47, 26,34,35,39,41,46},
{ 48, 27,30,32,38,42,45},
{ 49, 22,24,26,27,28,44},
{ 50, 23,24,32,34,38,39},
{ 51, 22,32,33,35,36,37},
{ 52, 22,28,29,38,41,44},
{ 53, 28,39,42,43,47,48},
{ 54, 27,30,35,40,41,47},
{ 55, 2, 3, 6, 7,12,13},
{ 56, 27,36,40,41,42,46},
{ 57, 2, 3, 8, 9,10,11},
{ 58, 28,30,31,36,37,39},
{ 59, 2, 3,14,15,20,21},
{ 60, 23,24,29,36,40,47},
{ 61, 29,31,33,38,41,43},
{ 62, 2, 3,16,17,18,19},
{ 63, 26,29,30,35,45,47},
{ 64, 22,25,27,29,34,43},
{ 65, 2, 4, 6, 9,15,16},
{ 66, 26,37,38,40,43,44},
{ 67, 26,30,32,34,41,42},
{ 68, 23,30,31,33,43,46},
{ 69, 25,31,35,39,44,47},
{ 70, 2, 4, 7, 8,14,17},
{ 71, 2, 4,10,13,19,20},
{ 72, 2, 4,11,12,18,21},
{ 73, 24,34,36,38,42,46},
{ 74, 2, 5, 6, 8,19,21},
{ 75, 2, 5, 7, 9,18,20},
{ 76, 22,24,31,41,45,48},
{ 77, 25,26,28,33,38,40},
{ 78, 2, 5,10,12,15,17},
{ 79, 2, 5,11,13,14,16},
{ 80, 2, 6,10,14,18,49},
{ 81, 2, 7,11,15,19,49},
{ 82, 2, 8,12,16,20,49},
{ 83, 2, 9,13,17,21,49},
{ 84, 23,26,29,32,39,45},
{ 85, 24,30,34,35,38,47},
{ 86, 3, 4, 6, 8,18,20},
{ 87, 3, 4, 7, 9,19,21},
{ 88, 3, 4,10,12,14,16},
{ 89, 3, 4,11,13,15,17},
{ 90, 3, 5, 6, 9,14,17},
{ 91, 3, 5, 7, 8,15,16},
{ 92, 27,28,29,31,34,37},
{ 93, 23,25,30,37,46,48},
{ 94, 3, 5,10,13,18,21},
{ 95, 3, 5,11,12,19,20},
{ 96, 3, 6,11,16,21,49},
{ 97, 3, 7,10,17,20,49},
{ 98, 6, 7,14,16,19,20},
{ 99, 3, 8,13,14,19,49},
{100, 3, 9,12,15,18,49},
{101, 6, 7,15,17,18,21},
{102, 6, 8,10,13,16,17},
{103, 6, 8,11,12,14,15},
{104, 6, 9,10,12,20,21},
{105, 6, 9,11,13,18,19},
{106, 25,31,32,35,36,44},
{107, 4, 5, 8, 9,12,13},
{108, 4, 5,14,15,18,19},
{109, 4, 5,16,17,20,21},
{110, 4, 6,12,17,19,49},
{111, 4, 7,13,16,18,49},
{112, 7, 8,10,12,18,19},
{113, 7, 8,11,13,20,21},
{114, 7, 9,10,13,14,15},
{115, 7, 9,11,12,16,17},
{116, 8, 9,14,16,18,21},
{117, 8, 9,15,17,19,20},
{118, 10,11,14,17,19,21},
{119, 10,11,15,16,18,20},
{120, 12,13,14,17,18,20},
{121, 12,13,15,16,19,21},
{122, 4, 8,10,15,21,49},
{123, 4, 9,11,14,20,49},
{124, 5, 6,13,15,20,49},
{125, 5, 7,12,14,21,49},
{126, 5, 8,11,17,18,49},
{127, 5, 9,10,16,19,49},
{128, 4, 5, 6, 7,10,11},
{129, 22,23,28,30,44,46},
{130, 27,29,33,34,44,48},
{131, 28,32,36,42,43,48},
{132, 25,26,31,40,41,44},
{133, 24,28,38,40,43,48},
{134, 28,35,36,43,47,48},
{135, 24,25,31,38,44,45},
{136, 26,28,41,43,45,48},
{137, 25,28,29,33,44,46},
{138, 27,30,31,37,43,44},
{139, 22,23,25,31,34,48},
{140, 23,25,27,28,33,37},
{141, 22,29,30,31,33,48},
{142, 22,34,37,43,44,46},
{143, 25,31,36,42,44,47},
{144, 38,39,40,41,42,47},
{145, 22,26,33,37,38,45},
{146, 24,27,34,39,42,47},
{147, 23,26,32,35,42,45},
{148, 28,32,35,39,43,48},
{149, 23,29,37,43,44,48},
{150, 22,27,28,31,46,48},
{151, 22,24,33,37,40,41},
{152, 25,28,30,33,34,43},
{153, 23,30,34,38,40,46},
{154, 26,30,32,36,39,45},
{155, 27,29,34,35,38,41},
{156, 26,29,32,45,46,47},
{157, 23,24,27,30,41,46},
{158, 23,29,30,36,39,42},
{159, 25,31,32,39,42,44},
{160, 24,32,35,36,38,41},
{161, 24,26,27,29,40,45},
{162, 27,32,34,35,36,40},
{163, 23,30,35,36,46,47}};

for (int lpcnt = 1; lpcnt <= GlobalValues.kNoSeconds; lpcnt++)
GlobalValues.gaSumWorkDays[lpcnt] = 0;

for (int mm = 1; mm <= GlobalValues.kNoDays; mm++)
{
GlobalValues.gaWorkDays[1] = TimeSchedule[mm, 1];
GlobalValues.gaWorkDays[2] = TimeSchedule[mm, 2];
GlobalValues.gaWorkDays[3] = TimeSchedule[mm, 3];
GlobalValues.gaWorkDays[4] = TimeSchedule[mm, 4];
GlobalValues.gaWorkDays[5] = TimeSchedule[mm, 5];
GlobalValues.gaWorkDays[6] = TimeSchedule[mm, 6];
CWeekTime.WeekTime();
}


int lnTotMissingTime = 0;



DateTime start = DateTime.Now;

//Create gaSeconds2 from gaSeconds
for (int i = 0; i < GlobalValues.gaSeconds2.Length; i++)
{
GlobalValues.gaSeconds2 = new int[4];
for (int j = 0; j < 4; j++)
GlobalValues.gaSeconds2[j] =
GlobalValues.gaSeconds[i, j];
}

lnTotMissingTime = CVerifyMissingTime.VerifyMissingTime();
Console.WriteLine("Total No of Missing Time {0} ",
lnTotMissingTime);

Console.WriteLine(DateTime.Now-start);

Console.ReadLine();

return 0;

}
}

public class GlobalValues
{
public static int[][] gaSeconds2 = new int[kNoWeeks +1][];
public const int kNoWeeks = 49;
public const int kNoDays = 163;
public const int kNoSeconds = 18424;
public static int gnSumSeconds = 0;
public static int[] gaWorkDays = new int[7];
public static int[] gaSumWorkDays = new int[kNoSeconds + 1];

public static int[,] gaSeconds = new int[kNoWeeks + 1, 4]
{
{0, 0, 0, 0},
{1, 0, 0, 0},
{2, 1081, 0, 0},
{3, 2116, 46, 1},
{4, 3106, 91, 2},
{5, 4052, 135, 3},
{6, 4955, 178, 4},
{7, 5816, 220, 5},
{8, 6636, 261, 6},
{9, 7416, 301, 7},
{10, 8157, 340, 8},
{11, 8860, 378, 9},
{12, 9526, 415, 10},
{13, 10156, 451, 11},
{14, 10751, 486, 12},
{15, 11312, 520, 13},
{16, 11840, 553, 14},
{17, 12336, 585, 15},
{18, 12801, 616, 16},
{19, 13236, 646, 17},
{20, 13642, 675, 18},
{21, 14020, 703, 19},
{22, 14371, 730, 20},
{23, 14696, 756, 21},
{24, 14996, 781, 22},
{25, 15272, 805, 23},
{26, 15525, 828, 24},
{27, 15756, 850, 25},
{28, 15966, 871, 26},
{29, 16156, 891, 27},
{30, 16327, 910, 28},
{31, 16480, 928, 29},
{32, 16616, 945, 30},
{33, 16736, 961, 31},
{34, 16841, 976, 32},
{35, 16932, 990, 33},
{36, 17010, 1003, 34},
{37, 17076, 1015, 35},
{38, 17131, 1026, 36},
{39, 17176, 1036, 37},
{40, 17212, 1045, 38},
{41, 17240, 1053, 39},
{42, 17261, 1060, 40},
{43, 17276, 1066, 41},
{44, 17286, 1071, 42},
{45, 17292, 1075, 43},
{46, 17295, 1078, 44},
{47, 17296, 1080, 45},
{48, 0, 1081, 46},
{49, 0, 0, 47}};
}

class CWeekTime
{
public static int WeekTime()
{
for (int s1 = 1; s1 <= 4; s1++)
{
for (int s2 = s1 + 1; s2 <= 5; s2++)
{
for (int s3 = s2 + 1; s3 <= 6; s3++)
{
GlobalValues.gnSumSeconds =
GlobalValues.gaSeconds[GlobalValues.gaWorkDays[s1], 1] +
GlobalValues.gaSeconds[GlobalValues.gaWorkDays[s2], 2] +
GlobalValues.gaSeconds[GlobalValues.gaWorkDays[s3], 3];

GlobalValues.gaSumWorkDays[GlobalValues.gnSumSeconds] = 1;
}
}
}
return (0);
}
}

class CVerifyMissingTime
{


public static int VerifyMissingTime()
{
int lnSumMissingTime = 0;

for (int xxxLoop = 1; xxxLoop <= 10; xxxLoop++)
{
lnSumMissingTime = 0;

for (int lp1 = 1; lp1 <= GlobalValues.kNoWeeks - 5; lp1++)
{
int lp11 = GlobalValues.gaSeconds2[lp1][1];

for (int lp2 = lp1 + 1; lp2 <= GlobalValues.kNoWeeks -
4; lp2++)
{
int lp21 = GlobalValues.gaSeconds2[lp2][1];
int lp22 = GlobalValues.gaSeconds2[lp2][2];
//(lp2 <= 2 || lp2 == 49) ? 0 : (lp2 - 2) * (95 - lp2) / 2;
//Lookup is faster

for (int lp3 = lp2 + 1; lp3 <=
GlobalValues.kNoWeeks - 3; lp3++)
{
int lp31 = GlobalValues.gaSeconds2[lp3][1];
int lp32 = GlobalValues.gaSeconds2[lp3][2];
int lp33 = GlobalValues.gaSeconds2[lp3][3];

for (int lp4 = lp3 + 1; lp4 <=
GlobalValues.kNoWeeks - 2; lp4++)
{
int lp41 =
GlobalValues.gaSeconds2[lp4][1];
int lp42 =
GlobalValues.gaSeconds2[lp4][2];
int lp43 =
GlobalValues.gaSeconds2[lp4][3];

for (int lp5 = lp4 + 1; lp5 <=
GlobalValues.kNoWeeks - 1; lp5++)
{
int lp52 =
GlobalValues.gaSeconds2[lp5][2];
int lp53 =
GlobalValues.gaSeconds2[lp5][3];

for (int lp6 = lp5 + 1; lp6 <=
GlobalValues.kNoWeeks; lp6++)
{
if (

GlobalValues.gaSumWorkDays[lp11 + lp22 + lp33] > 0)
{
goto breakOut4;
}
else if (

(GlobalValues.gaSumWorkDays[lp11 + lp22 + lp43] > 0)
||

(GlobalValues.gaSumWorkDays[lp11 + lp32 + lp43] > 0)
||

(GlobalValues.gaSumWorkDays[lp21 + lp32 + lp43] > 0))
{
goto breakOut5;
}

if (

(GlobalValues.gaSumWorkDays[lp11 + lp22 + lp53] > 0)
||

(GlobalValues.gaSumWorkDays[lp11 + lp32 + lp53] > 0)
||

(GlobalValues.gaSumWorkDays[lp11 + lp42 + lp53] > 0)
||

(GlobalValues.gaSumWorkDays[lp21 + lp32 + lp53] > 0)
||

(GlobalValues.gaSumWorkDays[lp21 + lp42 + lp53] > 0)
||

(GlobalValues.gaSumWorkDays[lp31 + lp42 + lp53] > 0))
{
break;
}

int lp63 =
GlobalValues.gaSeconds2[lp6][3];

if (
(GlobalValues.gaSumWorkDays[lp11 +
lp22 + lp63] > 0)
||
(GlobalValues.gaSumWorkDays[lp11 +
lp32 + lp63] > 0)
||
(GlobalValues.gaSumWorkDays[lp11 +
lp42 + lp63] > 0)
||
(GlobalValues.gaSumWorkDays[lp11 +
lp52 + lp63] > 0)
||
(GlobalValues.gaSumWorkDays[lp21 +
lp32 + lp63] > 0)
||
(GlobalValues.gaSumWorkDays[lp21 +
lp42 + lp63] > 0)
||
(GlobalValues.gaSumWorkDays[lp21 +
lp52 + lp63] > 0)
||
(GlobalValues.gaSumWorkDays[lp31 +
lp42 + lp63] > 0)
||
(GlobalValues.gaSumWorkDays[lp31 +
lp52 + lp63] > 0)
||
(GlobalValues.gaSumWorkDays[lp41 +
lp52 + lp63] > 0))
{
continue;
}

lnSumMissingTime++;

}
}
breakOut5: ;
}
breakOut4: ;
}
}
}
}
Console.WriteLine("Missing Time {0}", lnSumMissingTime);

return lnSumMissingTime;

}
}
 
J

Jon Skeet [C# MVP]

Roy Gourgi said:
Basically, for all intensive purposes all I have is 2 arrays (gaSeconds &
TimeSchedule). The array gaSeconds as you can see, has to be accessed many,
many times and for this application, it cannot absolutely be a jagged array.

Why not, out of interest?
The values in the gaSeconds in the real application change, but I kept them
constant for the sake of simplicity, so although it looks that I am
aimlessly accessing the same information many times in the
CVerifyMissingTime, I am not.

All I wanted to know if there is a way to make this faster. I am not that
worried about wheter it is in classic object oriented programming form as
speed is of the essence.

In my experience, it's much easier to change something to be faster
when it's clear what it's doing.

I'm glad Marcus has managed to improve the speed for you, but I really
would try re-writing it in an OO way and looking at it after that.
 
M

Marcus Andrén

Hi Marcus,

WOW that is good indeed. That is even faster than the time I was getting in
C++. :) I am not that good at C++ either, mind you. :)

But I do not understand how you got it to be so much faster, as it is now
about 6 times faster than before. Where is most of the time gain coming
from? I will try to disect what you did and also try to apply it to my C++
program.

I only getting about a 2-3 times gain on my computer.The gain comes
from three sources. The biggest being to used a jagged array instead
of a multidimensional one. The second biggest is to move array access
to the outer for loops like this.

int lp31 = GlobalValues.gaSeconds2[lp3][1];

No need to recalculate the values each loop and the compiler is
unfortunally not smart enough to realize by itself that it doesn't
have to. The third improvement was minor. It was to replace
lp6=100;continue; with just break;.

I also replaced lp5=lp6=100;continue; with goto breakOut5; and
lp4=lp5=lp6=100;continue; with goto breakOut4; because even though
goto is a statement to be avoided in most cases it is in my opinion
much worse to change loop indexes to break out of a loop.

I also combined a bunch of comparisons into a single if statement if
they had the same outcome. It didn't give any performance boost, but
it makes the look much code more structured.

Ok, I just came up with an idea and looked at your code again. goto
and break aren't needed at all. A lot of the comparisons can be moved
to outer loops and use continue; instead. It will speed up the code
considerably. After this modification I don't think there is much more
that can be done. Here is the modified version of VerifyMissingTime():

public static int VerifyMissingTime()
{
int lnSumMissingTime = 0;

for (int xxxLoop = 1; xxxLoop <= 10; xxxLoop++)
{
lnSumMissingTime = 0;

for (int lp1 = 1; lp1 <= GlobalValues.kNoWeeks - 5; lp1++)
{
int lp11 = GlobalValues.gaSeconds2[lp1][1];

for (int lp2 = lp1 + 1; lp2 <= GlobalValues.kNoWeeks -
4; lp2++)
{
int lp21 = GlobalValues.gaSeconds2[lp2][1];
int lp22 = GlobalValues.gaSeconds2[lp2][2];
//(lp2 <= 2 || lp2 == 49) ? 0 : (lp2 - 2) * (95 - lp2) / 2;
//Lookup is faster

for (int lp3 = lp2 + 1; lp3 <=
GlobalValues.kNoWeeks - 3; lp3++)
{
int lp31 = GlobalValues.gaSeconds2[lp3][1];
int lp32 = GlobalValues.gaSeconds2[lp3][2];
int lp33 = GlobalValues.gaSeconds2[lp3][3];

if (GlobalValues.gaSumWorkDays[lp11 + lp22 +
lp33] > 0)
continue;

for (int lp4 = lp3 + 1; lp4 <=
GlobalValues.kNoWeeks - 2; lp4++)
{
int lp41 =
GlobalValues.gaSeconds2[lp4][1];
int lp42 =
GlobalValues.gaSeconds2[lp4][2];
int lp43 =
GlobalValues.gaSeconds2[lp4][3];

if ((GlobalValues.gaSumWorkDays[lp11 +
lp22 + lp43] > 0)
||
(GlobalValues.gaSumWorkDays[lp11 +
lp32 + lp43] > 0)
||
(GlobalValues.gaSumWorkDays[lp21 +
lp32 + lp43] > 0))
{
continue;
}


for (int lp5 = lp4 + 1; lp5 <=
GlobalValues.kNoWeeks - 1; lp5++)
{
int lp52 =
GlobalValues.gaSeconds2[lp5][2];
int lp53 =
GlobalValues.gaSeconds2[lp5][3];

if (
(GlobalValues.gaSumWorkDays[lp11 +
lp22 + lp53] > 0)
||
(GlobalValues.gaSumWorkDays[lp11 +
lp32 + lp53] > 0)
||
(GlobalValues.gaSumWorkDays[lp11 +
lp42 + lp53] > 0)
||
(GlobalValues.gaSumWorkDays[lp21 +
lp32 + lp53] > 0)
||
(GlobalValues.gaSumWorkDays[lp21 +
lp42 + lp53] > 0)
||
(GlobalValues.gaSumWorkDays[lp31 +
lp42 + lp53] > 0))
{
continue;
}

for (int lp6 = lp5 + 1; lp6 <=
GlobalValues.kNoWeeks; lp6++)
{

int lp63 =
GlobalValues.gaSeconds2[lp6][3];

if (

(GlobalValues.gaSumWorkDays[lp11 + lp22 + lp63] > 0)
||

(GlobalValues.gaSumWorkDays[lp11 + lp32 + lp63] > 0)
||

(GlobalValues.gaSumWorkDays[lp11 + lp42 + lp63] > 0)
||

(GlobalValues.gaSumWorkDays[lp11 + lp52 + lp63] > 0)
||

(GlobalValues.gaSumWorkDays[lp21 + lp32 + lp63] > 0)
||

(GlobalValues.gaSumWorkDays[lp21 + lp42 + lp63] > 0)
||

(GlobalValues.gaSumWorkDays[lp21 + lp52 + lp63] > 0)
||

(GlobalValues.gaSumWorkDays[lp31 + lp42 + lp63] > 0)
||

(GlobalValues.gaSumWorkDays[lp31 + lp52 + lp63] > 0)
||

(GlobalValues.gaSumWorkDays[lp41 + lp52 + lp63] > 0))
{
continue;
}

lnSumMissingTime++;
}
}
}
}
}
}
}
Console.WriteLine("Missing Time {0}", lnSumMissingTime);

return lnSumMissingTime;
}
 
R

Roy Gourgi

Hi Bill,

Marcus has already solved my problem. He is pretty good let me tell you as
there are not many people that actually understand it in a vacuum, but he
did.
It is kind of esoteric, but he just understood what I wanted to do face
value and did a great job.

I will try to be a little bit more explicit next time.

Thanks anyways Bill

Roy
 
R

Roy Gourgi

Bill,

Well believe it or not, you are right in the sense that it is a lot like
FORTRAN because that is the nature of the problem at hand. I am sure that
Markus will tell you himself that OOP in this case, it would be futile and
in fact would hinder the performance, I believe. I am not a seasoned
programmer by any means like you or Markus, but I do conceptualize things
quite well and come up with some pretty good ideas.

BTW Markus I tried to email you but I get an error. My program in C# was a
watered down version of my C++ program (which believe it or not is almost
identical to your final version but you did give me a couple of good ideas).
The main difference between our programs is that I did not used a jagged
array as I don't believe C++ supports them (I do not know C++ nor any
language for that matter very well). For your information, I used 3 x 1
dimensional arrays which make the program much simpler and intuitive. My
main reason was to see why my loops were executing so slow in C# and I think
that you answered that question when you said that the for looping in C# is
not that good, actually it stinks. I am not very knowledgeable when it comes
to programming, but I am a good problem solver.

My actual program in C++ is 30,000 lines and growing and I wanted to see if
it would be worth it to transport it to C# especially because I have to use
some very large databases. Do you think it would be?

I am very curious Markus, if you understand the nature of the problem
yourself and the context in which it is used as you came up with some
brilliant answers. Are you a mathematician, because there are not many
people that understand this problem as it is quite complex.

Roy
 
B

Bill Butler

Roy,

I have looked at your program and I cannot truly figure out what you are doing.
I see names like weeks, seconds, days and so on, but none of it is clicking.

You have :
kNoWeeks = 49 (3 weeks vacation????)
You have kNoDays=163 (Days worked in a year????)
kNoSeconds=18424; (I have no clue)

Your TimeSchedule array has 164 rows of data. (you obviously don't like 0 based arrays)
Each row consists of 7 values with the first one never used.

What does this data represent and where did the values come from?

The entire TimeSchedule array is a key into the gaSeconds Array.
What is the relationship?

What exactly is the problem that you are trying to solve?
If I understand the question I can help you with the answer.

Bill Butler
 
B

Bill Butler

Roy Gourgi said:
Hi Bill,

Marcus has already solved my problem. He is pretty good let me tell you as there are not many
people that actually understand it in a vacuum, but he did.
It is kind of esoteric, but he just understood what I wanted to do face value and did a great job.

I will try to be a little bit more explicit next time.

Thanks anyways Bill

Roy

Hi Roy,

Markus may have helped improve the efficiency of your program, but that does nothing for it's
maintainability.

The reason I am asking you to describe the problem you are trying to solve in more detail is because
the logic in your program is VERY difficult to follow. I can't imagine that the problem cannot be
solved in a simpler fashion. (I could be wrong). Your program flow feels more like a FORTRAN or
COBOL program than a C# program.

I am semi fascinated by what you are trying to do and would still like to know more.

Jon has suggested applying more Object orientation to the problem.
This is not a bad idea, but even some simpler concepts can help.

-- Passing data as parameters to a function instead of making it Global
-- If you don't need to return a value from a function use a return type of void
-- Verify that you REALLY need 6 levels of nested looping to solve your problem (perhaps you do, but
I am not yet convinced)
-- Many more

So, while I am glad that Markus improved the behavior of the program,
I am not convinced that it is going about it in the most efficient way.

Often, at my job, I come across a massively complex program that I can't seem to wrap my brain
around.
After days of banging my head against the wall I get a revelation:
OOOHHHHH, That's what he was trying to do!!!!!!!!!
Often it could be done in a substantially clearer fashion.

So, if you give us a detailed description of the problem I think we can make this program
faster and much more maintainable

Bill
 
J

Jon Skeet [C# MVP]

Roy Gourgi said:
Well believe it or not, you are right in the sense that it is a lot like
FORTRAN because that is the nature of the problem at hand. I am sure that
Markus will tell you himself that OOP in this case, it would be futile and
in fact would hinder the performance, I believe.

I think that's making a bit of an assumption about Markus's
viewpoints...

As for it being futile and hindering performance - you can't know until
you've tried. One thing I know is that optimising code which is easily
understood is *much* easier than optimising code which is obscure.

My main reason was to see why my loops were executing so slow in C#
and I think that you answered that question when you said that the
for looping in C# is not that good, actually it stinks.

I think you don't have nearly enough evidence on which to base that
viewpoint - especially as you've now said that Markus's C# version runs
faster than the C++ version!
I am not very knowledgeable when it comes to programming, but I am a
good problem solver.

I think the main thing you need to apply that to is how to make it
clear what the code is meant to do. Readability is very, very important
- if your code isn't readable, chances are it has bugs.
My actual program in C++ is 30,000 lines and growing and I wanted to see if
it would be worth it to transport it to C# especially because I have to use
some very large databases. Do you think it would be?

Using very large databases doesn't depend on using C#. However, if you
don't have readable code, you're likely to run into all kinds of
problems, whatever language you write the code in.
 
R

Roy Gourgi

Hi Bill,

Unfortunately I do not share that thought, that OOP is always the panacea to
all programming. I have dabbled in OOP with Visual FoxPro (the language that
I know best) even though I know that the OOP in VFP is not the classic OOP
paradigm like C#. Nonetheless, sometimes we tend to use something just
because it is available and not necessarily because it is the best
alternative. I certainly believe that OOP is clearly superior to procedure
driven programming, but by the same token I do think that it has to be used
properly. For example I think that when you use inheritance and override
many functions and create too many child classes, that it could become
unwieldly and complex.

To satisfy your curiosity, this is a combinatorial problem. I am a
combinatorist and a pretty good one at that I may say. I am not sure if
Markus knows anything about combinatorics or it's uses, though, by the way
that he solved that problem I would tend to believe he must have some
background in mathematics or logistics. Unbeknownst to him I think, is that
he just re-created the fastest timing checker ever made (actually he even
taught me a couple of things). :)

So you see in this case I cannot see how OOP can help as all the processing
has to be done in the same function.

I hope that I can make the transition to C# as I have to create databases
that are incredibly huge (numbers that are surreal). The reason why I want
to move to C# is that I think that C# and VS.Net are where everything is
headed and it seems to be more intuitive than C++ and there will probably be
a lot of support.

Hope this helps

Roy
 
R

Roy Gourgi

Hi Jon,

If you read my previous email it will shed some light on the matter at hand.

Yes, that is right gaSumWorkDays is just treated to check if it is true or
false, but as I mentioned earlier this is a watered down version of my
program and you do not see why those values are true or false. Yes indeed it
is more complicated than that, but everything is done methodically in an
orderly fashion and although it seems that there is some redundancy, it is
unavoidable.

This is a combinatorial timing problem and believe it or not, this is the
fastest algorithm in the world. If you look at the order in which the loops
are actually tested to see if they are true or false, you might understand
it. They are purposely done in that order to maximize speed by avoiding as
much redundancy as possible, even though it might not seem intuitive.

Hope this helps

Roy




Jon Skeet said:
Roy Gourgi said:
I am new to C#. I have the same time scheduling program written in C++
and
it is 5 times faster than my version in C#.
Why is it so slow as I thought that C# was only a little slower than C++?
What am I doing wrong?

<snip>

Okay, I've had another look, and really tried hard to understand what's
going on. Here's what I've worked out so far:

You really only treat gaSumWorkDays as being true or false, right?
Using a bool array makes this clearer. Then each condition just changes
to:

if (GlobalValues.gaSumWorkDays[GlobalValues.gaSeconds[x,1]+
GlobalValues.gaSeconds[y,2]+
GlobalValues.gaSeconds[z,3]])

for some x, y and z, where 0 < x < y < z < 50. And you're counting all
the possibilities of x, y and z where that's not true - is that right?

Unfortunately, the way I see it, it must be more complicated than that
- because you're counting the case where (say) x=2, y=3, z=4 twice -
once when lp1=2, lp2=3, lp3=4, and once when lp2=2, lp3=3, lp4=4. Is
that deliberate? What does it signify, compared with the case of x=1,
y=2, z=3 which is only counted once?

It would really help if you'd explain what the code is meant to
actually do, because I strongly suspect there are much faster ways of
calculating the same answer - once we know what the question is.
 
D

Danny Tuppeny

Bill Butler said:
Roy,

I have looked at your program and I cannot truly figure out what you are
doing.

That's one way to make sure you don't get fired - make finding a replacement
impossible ;o)
 
J

Jon Skeet [C# MVP]

Roy Gourgi said:
I am new to C#. I have the same time scheduling program written in C++ and
it is 5 times faster than my version in C#.
Why is it so slow as I thought that C# was only a little slower than C++?
What am I doing wrong?

<snip>

Okay, I've had another look, and really tried hard to understand what's
going on. Here's what I've worked out so far:

You really only treat gaSumWorkDays as being true or false, right?
Using a bool array makes this clearer. Then each condition just changes
to:

if (GlobalValues.gaSumWorkDays[GlobalValues.gaSeconds[x,1]+
GlobalValues.gaSeconds[y,2]+
GlobalValues.gaSeconds[z,3]])

for some x, y and z, where 0 < x < y < z < 50. And you're counting all
the possibilities of x, y and z where that's not true - is that right?

Unfortunately, the way I see it, it must be more complicated than that
- because you're counting the case where (say) x=2, y=3, z=4 twice -
once when lp1=2, lp2=3, lp3=4, and once when lp2=2, lp3=3, lp4=4. Is
that deliberate? What does it signify, compared with the case of x=1,
y=2, z=3 which is only counted once?

It would really help if you'd explain what the code is meant to
actually do, because I strongly suspect there are much faster ways of
calculating the same answer - once we know what the question is.
 
R

Roy Gourgi

Jon,
Unavoidable redundancy usually sounds like it's just not be solved
*yet* to me :)

Believe it or not, in most combinatorial problems there is some *unavoidable
redundancy* as most combinatorial covering designs are not perfect (i.e.
they contain some unavoidable redundancy). There are instances of perfect
combinatorial designs such as this design C(22,6,3)=77 and when they are
perfect they are call t-designs. But most designs do not fall under this
perfect category and they are thus much harder to find than their
counterparts.

If you are interested I can shed some more light, but it gets more complex.
:)

You haven't answered my question as to whether you are actually
intending to count some combinations (eg 2,3,4) multiple times. Even if
you are, I would have thought it would be easier to only try each
combination once (i.e. using a triple loop rather than six) and then if
you hit a "missing" time, work out how many times you would have hit it
if you'd used your original algorithm.

No, I am not counting the instances of a particular combination such as
2,3,4 because if you look at the code carefully, any combination is never
checked more than once in any of the 6 columns in the gaSeconds. That is why
as I mentioned in my other posts, the way the search is conducted is of the
essence. If 3 points such as 2,3,4 appear in any one of 6 numbers, it would
be better if they appear in the first 3 of the 6 because that would speed up
the search. Do you follow?
You've praised Markus's understanding of the problem several times, but
as he said, the fastest gain was just from using jagged arrays rather
than rectangular arrays. As far as I've seen, you've still not said why
you couldn't use rectangular arrays to start with.

First of all, I don't think that C++ supports jagged arrays (correct me if I
am wrong). Furthermore, as I reiterated a few times, my knowledge in
programming is not as extensive as yours and I thought jagged arrays are to
be used only when the arrays are not rectangular and in my case they always
are. I was not aware that jagged arrays would speed up the search process
(one of the new things that I learnt). In my original program I use 3 one
dimensional arrays (i.e. gaSeconds1,gaSeconds2,gaSeconds3) which I guess is
analogous to a jagged array. I think it may even be faster than a jagged
array as you are only accessing a one dimension array at a time (correct me
if I am wrong) but I was too lazy to try to see which one is faster. Also,
to me it seems more natural and intuitive to have several one dimensional
arrays, but this might just be a matter of preference. BTW do you know which
would be faster a jagged array, or multiple one dimensional arrays?

Hope this helps

Roy
 
J

Jon Skeet [C# MVP]

Roy Gourgi said:
If you read my previous email it will shed some light on the matter at hand.

I thought I'd read all the articles you'd posted, but I haven't seen
any explanation for what it's actually trying to do.
Yes, that is right gaSumWorkDays is just treated to check if it is true or
false, but as I mentioned earlier this is a watered down version of my
program and you do not see why those values are true or false. Yes indeed it
is more complicated than that, but everything is done methodically in an
orderly fashion and although it seems that there is some redundancy, it is
unavoidable.

Unavoidable redundancy usually sounds like it's just not be solved
*yet* to me :)
This is a combinatorial timing problem and believe it or not, this is the
fastest algorithm in the world. If you look at the order in which the loops
are actually tested to see if they are true or false, you might understand
it. They are purposely done in that order to maximize speed by avoiding as
much redundancy as possible, even though it might not seem intuitive.

You haven't answered my question as to whether you are actually
intending to count some combinations (eg 2,3,4) multiple times. Even if
you are, I would have thought it would be easier to only try each
combination once (i.e. using a triple loop rather than six) and then if
you hit a "missing" time, work out how many times you would have hit it
if you'd used your original algorithm.

You've praised Markus's understanding of the problem several times, but
as he said, the fastest gain was just from using jagged arrays rather
than rectangular arrays. As far as I've seen, you've still not said why
you couldn't use rectangular arrays to start with.
 
J

Jon Skeet [C# MVP]

Roy Gourgi said:
If you read my previous email it will shed some light on the matter at hand.

I thought I'd read all the articles you'd posted, but I haven't seen
any explanation for what it's actually trying to do.
Yes, that is right gaSumWorkDays is just treated to check if it is true or
false, but as I mentioned earlier this is a watered down version of my
program and you do not see why those values are true or false. Yes indeed it
is more complicated than that, but everything is done methodically in an
orderly fashion and although it seems that there is some redundancy, it is
unavoidable.

Unavoidable redundancy usually sounds like it's just not be solved
*yet* to me :)
This is a combinatorial timing problem and believe it or not, this is the
fastest algorithm in the world. If you look at the order in which the loops
are actually tested to see if they are true or false, you might understand
it. They are purposely done in that order to maximize speed by avoiding as
much redundancy as possible, even though it might not seem intuitive.

You haven't answered my question as to whether you are actually
intending to count some combinations (eg 2,3,4) multiple times. Even if
you are, I would have thought it would be easier to only try each
combination once (i.e. using a triple loop rather than six) and then if
you hit a "missing" time, work out how many times you would have hit it
if you'd used your original algorithm.

You've praised Markus's understanding of the problem several times, but
as he said, the fastest gain was just from using jagged arrays rather
than rectangular arrays. As far as I've seen, you've still not said why
you couldn't use jagged arrays to start with.
 
J

Jon Skeet [C# MVP]

<snip>

Ignore the post this is a reply to - I tried to cancel it before it was
posted, but apparently I just missed... the last paragraph had
"rectangular" where I meant "jagged", hence the repost.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top