Параллельная десериализация Json из базы данных - PullRequest
1 голос
/ 11 января 2012

Это сценарий: в отдельной задаче я читаю из устройства чтения данных, которое представляет собой результирующий набор из одного столбца со строкой, JSON.В этой задаче я добавляю строку JSON в коллекцию BlockingCollection, которая оборачивает ConcurrentQueue.В то же время в основном потоке я пытаюсь / удаляю строку JSON из коллекции, а затем возвращаю ее возвращаемую десериализованной.

Чтение из базы данных и десериализация примерно с одинаковой скоростью, поэтому не будетслишком большое потребление памяти, вызванное большой коллекцией BlockingCollection.

Когда чтение из базы данных завершено, задача закрывается, и я затем десериализую все не десериализованные строки JSON.

Вопросы/ мысли:

1) Блокирует ли TryTake, чтобы невозможно было добавить?

2) Не делайте этого.Просто сделайте это серийно и верните доходность.

using (var q = new BlockingCollection<string>())
{
Task task = null;

try
{
    task = new Task(() =>
    {
        foreach (var json in sourceData)
            q.Add(json);
    });

    task.Start();

    while (!task.IsCompleted)
    {
        string json;
        if (q.TryTake(out json))
            yield return Deserialize<T>(json);
    }

    Task.WaitAll(task);
}
finally 
{
    if (task != null)
    {
        task.Dispose();
    }

    q.CompleteAdding();
}

foreach (var e in q.GetConsumingEnumerable())
    yield return Deserialize<T>(e);
}

1 Ответ

1 голос
/ 11 января 2012

Вопрос 1

Блокирует ли TryTake так, что добавление невозможно,

Будет очень короткий период, в течение которого добавление не может быть выполнено, однако этовремя будет незначительным.From http://msdn.microsoft.com/en-us/library/dd997305.aspx

Некоторые из одновременных типов коллекций используют легкие механизмы синхронизации, такие как SpinLock, SpinWait, SemaphoreSlim и CountdownEvent, которые являются новыми в .NET Framework 4. Эти типы синхронизацииобычно используют вращение в течение коротких периодов, прежде чем перевести нить в состояние ожидания.Когда ожидается, что время ожидания будет очень коротким, вращение будет гораздо менее затратным в вычислительном отношении, чем ожидание, что влечет за собой дорогостоящий переход ядра.Для классов коллекций, которые используют вращение, эта эффективность означает, что несколько потоков могут добавлять и удалять элементы с очень высокой скоростью.Для получения дополнительной информации о вращении и блокировке см. Разделы SpinLock и SpinWait.

Классы ConcurrentQueue и ConcurrentStack вообще не используют блокировки.Вместо этого они используют операции с блокировкой для обеспечения безопасности потоков.

Вопрос 2:

Не делайте этого.Просто сделайте это серийно и верните доходность.

Это похоже на путь.Как и в любой работе по оптимизации - делайте то, что проще, а затем измеряйте!Если здесь есть узкое место, подумайте об оптимизации, но, по крайней мере, вы будете знать, действительно ли ваши «оптимизации» помогают благодаря наличию показателей для сравнения.

...