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
IEquatable
interface is used by generic collection objects such asDictionary
,List
, andLinkedList
when 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