SOLUTION: Sometimes you just need to do something a whole bunch of times… and verify that something was done, or exists, or whatever…
A trick can be to use HASH tables… these are extremely fast memory based lookup tables.
I have used HASH tables twice in the past 2 days… the second use proved to be the best, improving my verification that I was doing by so much that it was worth the effort.
Since Epicor doesn’t have a public calendar scheduling method yet (one that allows you to schedule based on MFG Calendar + Holiday table), I had to write a new solution that romped through a loop to examine and skip holidays if found as the schedule is calculated… The Holiday table was small enough that I could put the entire table into memory, which increased performance… but it was still taking too long (15.6+ seconds per 10,000 days scheduled into the future)…
I remembered that I could create the hash… So… I simply loaded the holiday listing into a new hash table. Then I used the hash to verify if the date was a holiday.
Result: calling the same method, returning same data: 10,000 hits only took 0.125 - REDUCED by 15.5+ seconds. Yes, you read that correctly… it virtually eliminated the amount of time to calculate. I even checked it with 1 Million hits… still only took 0.2 seconds (Every second counts)…
(by the way… 1 million workdays into the future = 02/20/5852… i know someone will ask)…
For those that want to know… here is what the code looks like to populate a hashtable with holidays:
//first we get the holiday schedule locally
string MyCalendarID = "Shop";
var holidays = (from h in Db.ProdCalDay where h.Company == callContextClient.CurrentCompany && h.CalendarID == MyCalendarID select h);
System.Collections.Hashtable holidayHash = new System.Collections.Hashtable ();
foreach (var holiday in holidays)
{
holidayHash.Add (holiday.ModifiedDay, holiday.WorkingDay);
}
//now... to determine if a calendar date is a work day:
DateTime shipDate = DateTime.Today; //set this to any date you want
// WorkDay will be TRUE if it didn't find an override for the date passed.
bool WorkDay = (holidayHash.ContainsKey(shipDate)) ? (bool)holidayHash[shipDate] : true;
For further discussion, you may stand to gain slightly better performance from a Dictionary type. It is essentially the same, however, the Dictionary is a typed variant. This means, the collection is aware of the type of data stored and doesnt suffer in boxing\unboxing penalties. Also you get type safety to help potential avoid runtime errors.
One potential pitfall, that I dont believe affects us in this context is that HashTables are thread safe, while Dictionaries are not.
A final thing which I believe is of no consequence in our specific case is that a Dictionary will keep the order of your items you add, while there is no guarantee of that in a hash.
To use a ditionary, you just need to define the type of the key (1) and value (2) like:
var dic = new Dictionary<int, string>();
dic.Add(1,“One”);
dic.Add(2,“Two”);
Since they are similar, you still have access to ContainsKey and ContainsValue.
also dont forget to include:
using System.Collections.Generic;
Thanks Chris… I am still learning about C#… I did some testing and in MY case, changing to a dictionary only shaved 10-20 ms off of 1 million cycles… Seems that there are many way to shave off time!