-
Notifications
You must be signed in to change notification settings - Fork 232
Concurrency scenarios and PLINQ
Ical.net does not have any parallelism built in. Instead, it's best for application developers to use the Task Parallel Library to achieve parallelism at the application level. Some examples are below.
public void GetOccurrencesConcurrently()
{
var calendars = new List<string>
{
IcsFiles.DailyCount2,
IcsFiles.DailyInterval2,
IcsFiles.DailyByDay1,
IcsFiles.RecurrenceDates1,
IcsFiles.DailyByHourMinute1,
};
var eventOccurrences = calendars
.AsParallel()
.SelectMany(c =>
{
var calendar = Calendar.Load(c);
// ...you could do something like computing some recurrences...
var occurrences = calendar.GetOccurrences(searchStart, searchEnd);
return occurrences;
});
var materialized = eventOccurrences.ToList();
}
Where concurrency is used matters for application performance. In the example above, the events will be deserialized concurrently, but that's probably not the performance bottleneck. Calling GetOccurrences()
is usually the most expensive part of a data processing pipeline, because evaluating RRULE
s isn't cheap. You want to use your available CPU cores on each child CalendarEvent
's GetOccurrences()
invocation instead of at the top-level Calendar
.
If I were going to use AsParallel()
in a production scenario, I would rewrite the example above as follows:
public void GetOccurrencesConcurrently()
{
var calendars = new List<string>
{
IcsFiles.DailyCount2,
IcsFiles.DailyInterval2,
IcsFiles.DailyByDay1,
IcsFiles.RecurrenceDates1,
IcsFiles.DailyByHourMinute1,
};
var eventOccurrences = calendars
.Select(Calendar.Load)
.SelectMany(=> c.Events)
.AsParallel()
.SelectMany(e => e.GetOccurrences(searchStart, searchEnd))
.ToList();
}
Or if you want to get really fancy, you could use parallelism in both places, though it's probably overkill. Deserializing a typical calendar takes about 0.5ms on a mobile, 2012 Core i5, and it's likely that the task partitioning costs will wash out any gains. But you could try it:
public void GetOccurrencesConcurrently()
{
var calendars = new List<string>
{
IcsFiles.DailyCount2,
IcsFiles.DailyInterval2,
IcsFiles.DailyByDay1,
IcsFiles.RecurrenceDates1,
IcsFiles.DailyByHourMinute1,
};
var eventOccurrences = calendars
.AsParallel()
.Select(Calendar.Load)
.AsSequential()
.SelectMany(=> c.Events)
.AsParallel()
.SelectMany(e => e.GetOccurrences(searchStart, searchEnd))
.ToList();
}