I\'m running AQTime on this piece of code, I found that .IndexOf takes 16% of the time vs close to 80% for the other piece... They appear to use the same IsEqual and other rout
I made the following assumptions:
PointD is a structIndexOf is indeed slower than manually iterating the listYou can speed up IndexOf by implementing the IEquatable interface:
struct PointD : IEquatable
{
public int X;
public int Y;
public int Z;
public bool Equals(PointD other)
{
return (this.X == other.X) &&
(this.Y == other.Y) &&
(this.Z == other.Z);
}
}
Without implementing the IEquatable interface, IndexOf will compare the two PointD elements using ValueType.Equals(object other) which involves expensive boxing operations.
The documentation of the IEquatable interface states:
The
IEquatableinterface is used by generic collection objects such asDictionary,List, andLinkedListwhen testing for equality in such methods asContains,IndexOf,LastIndexOf, andRemove. It should be implemented for any object that might be stored in a generic collection.
Here is my complete benchmark code:
using System;
using System.Collections.Generic;
using System.Diagnostics;
struct PointD
{
public int X;
public int Y;
public int Z;
}
class PerfTest
{
List _pCoord3Points = new List();
int checkPointIndexOf(PointD pt)
{
return _pCoord3Points.IndexOf(pt);
}
int checkPointForBreak(PointD pt)
{
int retIndex = -1;
for (int i = 0; i < _pCoord3Points.Count; i++)
{
PointD otherPt = _pCoord3Points[i];
if ((pt.X == otherPt.X) &&
(pt.Y == otherPt.Y) &&
(pt.Z == otherPt.Z))
retIndex = i;
break;
}
return retIndex;
}
void init()
{
for (int x = 0; x < 100; x++)
{
for (int y = 0; y < 10; y++)
{
for (int z = 0; z < 10; z++)
{
PointD pt = new PointD() { X = x, Y = y, Z = z };
_pCoord3Points.Add(pt);
}
}
}
}
static void Main(string[] args)
{
PerfTest test = new PerfTest();
test.init();
Stopwatch sw = Stopwatch.StartNew();
for (int x = 0; x < 100; x++)
{
for (int y = 0; y < 10; y++)
{
for (int z = 0; z < 10; z++)
{
PointD pt = new PointD() { X = x, Y = y, Z = z };
test.checkPointIndexOf(pt);
}
}
}
sw.Stop();
Console.WriteLine(sw.Elapsed);
sw = Stopwatch.StartNew();
for (int x = 0; x < 100; x++)
{
for (int y = 0; y < 10; y++)
{
for (int z = 0; z < 10; z++)
{
PointD pt = new PointD() { X = x, Y = y, Z = z };
test.checkPointForBreak(pt);
}
}
}
sw.Stop();
Console.WriteLine(sw.Elapsed);
}
}
On Windows 7, x64, .NET 4.0 x64 build I get the following timings (approx):
IndexOf: 00:00:04.8096623 For Loop: 00:00:00.0014203
When turning PointD into a class the timings change to
IndexOf: 00:00:01.0703627 For Loop: 00:00:00.0014190
When using a struct PointD implementing IEquatable I get more "similar" results, but IndexOf is still slower (there is no significant difference when using a class now):
IndexOf: 00:00:00.3904615 For Loop: 00:00:00.0015218