You need to find where the problem really is.
First, you need to make sure that those 4 minutes (which is a lot!) are spent in OnBeforeCellRender.
Ideally, you move all processing out of the OnBeforeCellRender to have better control over the processing. The output of the preprocessing could be a hash map (Dictionary) with keys something like datetime + resource id (to uniquely identify each cell). Use the desired background color as the value.
Your OnBeforeCellRender would then look like this:
protected override void OnBeforeCellRender(BeforeCellRenderArgs e)
{
string key = e.Start.ToString("s") + "_" + e.ResourceId;
e.BackgroundColor = map[key];
}
When creating the hash map try to avoid inefficient operations like converting a DateTime to string and parsing it again, splitting the same string over and over again, etc. Especially inside loops.