フラットファイルを列挙する複数の列挙子があります。私は元々、Parallel Invokeに各列挙子を持っていて、各アクションがに追加され、BlockingCollection<Entity>
そのコレクションはConsumingEnumerable()を返していました。
public interface IFlatFileQuery
{
IEnumerable<Entity> Run();
}
public class FlatFile1 : IFlatFileQuery
{
public IEnumerable<Entity> Run()
{
// loop over a flat file and yield each result
yield return Entity;
}
}
public class Main
{
public IEnumerable<Entity> DoLongTask(ICollection<IFlatFileQuery> _flatFileQueries)
{
// do some other stuff that needs to be returned first:
yield return Entity;
// then enumerate and return the flat file data
foreach (var entity in GetData(_flatFileQueries))
{
yield return entity;
}
}
private IEnumerable<Entity> GetData(_flatFileQueries)
{
var buffer = new BlockingCollection<Entity>(100);
var actions = _flatFileQueries.Select(fundFileQuery => (Action)(() =>
{
foreach (var entity in fundFileQuery.Run())
{
buffer.TryAdd(entity, Timeout.Infinite);
}
})).ToArray();
Task.Factory.StartNew(() =>
{
Parallel.Invoke(actions);
buffer.CompleteAdding();
});
return buffer.GetConsumingEnumerable();
}
}
ただし、少しテストした結果、以下のコード変更は約20〜25%高速であることがわかりました。
private IEnumerable<Entity> GetData(_flatFileQueries)
{
return _flatFileQueries.AsParallel().SelectMany(ffq => ffq.Run());
}
コード変更の問題は、すべてのフラットファイルクエリが列挙されるまで待機してから、列挙して生成できるロット全体を返すことです。
どういうわけかそれをさらに速くするために上記のコードのビットを生み出すことは可能でしょうか?
すべてのフラットファイルクエリの合計結果は、せいぜい1000程度のエンティティにすぎない可能性があることを付け加えておきます。
編集:以下に変更しても、実行時間に違いはありません。(R#は、以前の状態に戻すことも提案しています)
private IEnumerable<Entity> GetData(_flatFileQueries)
{
foreach (var entity in _flatFileQueries.AsParallel().SelectMany(ffq => ffq.Run()))
{
yield return entity;
}
}