Reputation: 48402
I have a class that is defined as follows:
public class AlarmViolation
{
public string ObjectId { get; set; }
public int ChartType { get; set; }
public string AlarmInternalId { get; set; }
public short PositionInSequence { get; set; }
public short SequenceCount { get; set; }
public string TagValue { get; set; }
public DateTime PurgeDate { get; set; }
}
Then I create a List of this class as follows:
List<AlarmViolation> alarmViolationList;
I currently execute a Linq query as follows:
return alarmViolationList
.Where(row => row.ObjectId == objectId)
.Where(row => row.ChartType == this.ChartType)
.Where(row => row.AlarmInternalId == this.InternalId)
.Where(row => row.PositionInSequence == positionInSequence)
.Where(row => row.SequenceCount == sequenceCount)
.Any();
I am getting pretty bad performance with my current implementation. The list will typically contain somewhere between 150K and 300K entries. This query is executed hundreds of times on a regular schedule (roughly every 3 minutes).
If I could somehow index this list, or if this were a database table, I would create an index on ObjectId + ChartType.
Could someone suggest a more efficient implementation. If you need more information, I would be glad to provide it.
Upvotes: 2
Views: 134
Reputation: 361302
Why don't you write this:
return alarmViolationList
.Any(row => row.ChartType == this.ChartType && //int
row.PositionInSequence == positionInSequence && //short
row.SequenceCount == sequenceCount && //short
row.AlarmInternalId == this.InternalId && //string
row.ObjectId == objectId); //string
This should improve the performance by some amount, in my opinion. Note that I'm doing string
comparison after int
and short
comparisons, taking advantage of short-circuits.
Upvotes: 0
Reputation: 171178
As you only search for equality, I suggest you use a hashtable. Create a class that will hold all members which you equality-search on (in your case: ObjectId, ChartType, AlarmInternalId, ...). Implement Equals
and GetHashCode
.
Next, put all your objects into a lookup table using either Enumerable.ToDictionary
or Enumerable.ToLookup
. You can use that newly created "key" class to add the items and to search for items.
This will give you constant time lookup, even for multiple results.
Upvotes: 1
Reputation: 1499860
If I could somehow index this list, or if this were a database table, I would create an index on ObjectId + ChartType.
That suggests you should create a key type (AlarmViolationKey
?) consisting of the ObjectId and ChartType, then use a Dictionary<AlarmViolationKey, AlarmViolation>
. That will radically enhance the search time. If you have more than one violation per key, and you've created the list up-front in a way where it won't be changing, you could use a Lookup
instead.
Whatever you do, basically you don't want to do the linear scan you're currently doing - you want a hash-based lookup.
(Depending on your exact situation, you may still need a list, or you may be able to use a dictionary instead of the list completely. It's hard to say without any more context.)
Upvotes: 3