Re[8]: Асинхронные стримы (IAsyncEnumerable)
От: VladCore  
Дата: 24.09.21 12:19
Оценка: 8 (1)
Здравствуйте, Sharov, Вы писали:

S>>>А классический sql бд не могут батчами данные гнать, ну т.е. данных до фига, канал не резиновый, загнали 1Гб,

S>>>получили все возможные Person, прочитали, подогнали еще 1Гб данных и т.д. Это как раз про то, что выше говорилось --
S>>>IEnumerable<Task<IEnumerable<T>>>. Т.е. сценарий NoSql понятен, но вот когда реально много данных и все сразу в память
S>>>не прочитаешь тоже сюда относится.

VC>>Классический SQL клиент никогда не грузит в память весь 1Гб и на сервере иногда "грузит" весь возвращаемый набор иногда нет.


VC>>
VC>>SqlConnection con = ;
VC>>var persons = await con.QueryAsync<Person>("Select * From Person Order By Surname");
VC>>foreach(Person p in persons) {
VC>>}
VC>>


VC>>вот тут весь 1 гигабайт на клиенте всегда НЕ грузится целиком в озу.


S>А почему нет, если памяти хватает. Речь о случае, когда у нас памяти мало и мы не можем целиком все загрузить.

S>А когда памяти хватат, почему бы все сразу не загрузить?

есть Managed объекты в памяти, есть память в ОС процесса, её еще называют кучей. это разные вещи. я не понимаю о какой памяты ты сейчас говориш в контексте того что мой пример съест в куче 1 гиг озу и сразу пометит её для сборки мусора если ОЗУ достаточно.

S>В любом случае, речь о том, где будут данные между


S>var persons = await con.QueryAsync<Person>("Select * From Person Order By Surname");

S>и
S>foreach(Person p in persons)

нигде. здесь persons это запрос, а не то что он возвращает.

S>Как я понимаю, когда мы уже итерируемся по persons, то мы получили все данные от сервера, где

S>бы на клиенте они не находились. Я же говорил, про возможность итерироваться по полученным
S>persons, когда мы получаем только часть данных. Т.е. что-то получили, десериализовали, прошлись циклом,
S>читаем сл. порцию и т.д.

S>Т.е. в одном случае (как в примере выше) foreach начнет работу после окончания работы сервера,

S>а возможен ли случай, когда foreach начнет работу параллельно с работой сервера?

это оно и есть. Полностью загрузить это persons.ToList();
Re[5]: Асинхронные стримы (IAsyncEnumerable)
От: Sinclair Россия https://github.com/evilguest/
Дата: 24.09.21 12:49
Оценка: +1
Здравствуйте, VladCore, Вы писали:
VC>это издержки горизонтально масштабируемего NoSQL хранилища. клиенское API подогнано под тот факт что одним запросом всё нельзя получить что попадает под фильтр.
Как по мне — так это попытка объяснить через объясняемое. Ну, то есть звучит убедительно, но внезапно поддержка постраничного доступа является не только популярной модой, но и частью, к примеру, стандарта OData.
Независимо от того, лежит ли под источником NoSQL или SQL.
С т.з. номенклатуры типов дотнет, ODATA выглядит как IEnumerable<IList<T>>.
А если мы выгребаем его асинхронно — то как IEnumerable<Task<IList<T>>>.

Вот я как раз и размышляю над тем, что нужно выставлять наружу из источника потенциально больших данных. IEnumerable<Task<IList<T>>> — ну, такое себе решение.
IAsyncEnumerable<T> выглядит эстетичной альтернативой.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[9]: Асинхронные стримы (IAsyncEnumerable)
От: Sharov Россия  
Дата: 24.09.21 13:15
Оценка:
Здравствуйте, VladCore, Вы писали:


S>>А почему нет, если памяти хватает. Речь о случае, когда у нас памяти мало и мы не можем целиком все загрузить.

S>>А когда памяти хватат, почему бы все сразу не загрузить?
VC>есть Managed объекты в памяти, есть память в ОС процесса, её еще называют кучей. это разные вещи. я не понимаю о какой памяты ты сейчас говориш в контексте того что мой пример съест в куче 1 гиг озу и сразу пометит её для сборки мусора если ОЗУ достаточно.

Я про память процесса.

S>>В любом случае, речь о том, где будут данные между

S>>var persons = await con.QueryAsync<Person>("Select * From Person Order By Surname");
S>>и
S>>foreach(Person p in persons)
VC>нигде. здесь persons это запрос, а не то что он возвращает.

Чет я потерялся: я понимаю про eager\lazy loading (ienumarable\iquarable в контексте бд), но зачем
тогда await, если это будет просто установка соединения с бд? Т.к. времени на получение и обработку
persons явно будет затрачено больше(continuation). Ну с др. стороны установка соединения тоже io, так что скорее
всего имеет смысл. Тогда все более менее понятно, за остальными деталями к драйверу бд.

S>>Т.е. в одном случае (как в примере выше) foreach начнет работу после окончания работы сервера,

S>>а возможен ли случай, когда foreach начнет работу параллельно с работой сервера?
VC>это оно и есть. Полностью загрузить это persons.ToList();

Ага, точно, благодарю.
Кодом людям нужно помогать!
Re[6]: Асинхронные стримы (IAsyncEnumerable)
От: samius Япония http://sams-tricks.blogspot.com
Дата: 24.09.21 14:17
Оценка: +1
Здравствуйте, Sinclair, Вы писали:

S>С т.з. номенклатуры типов дотнет, ODATA выглядит как IEnumerable<IList<T>>.

S>А если мы выгребаем его асинхронно — то как IEnumerable<Task<IList<T>>>.

S>Вот я как раз и размышляю над тем, что нужно выставлять наружу из источника потенциально больших данных. IEnumerable<Task<IList<T>>> — ну, такое себе решение.

S>IAsyncEnumerable<T> выглядит эстетичной альтернативой.

Мне кажется, что постраничный доступ хорошо бы смотрелся через IAsyncEnumerable<IList<T>>, потому как у нас уже есть возможность обращаться к MoveNext асинхронно. Мы не знаем, будет ли еще страница в результате. А IEnumerable<Task<IList<T>>> говорит о том, что ответ на вопрос будет ли еще страница мы можем получить лишь синхронно.
Re[7]: Асинхронные стримы (IAsyncEnumerable)
От: Sinclair Россия https://github.com/evilguest/
Дата: 24.09.21 15:31
Оценка:
Здравствуйте, samius, Вы писали:
S>Мне кажется, что постраничный доступ хорошо бы смотрелся через IAsyncEnumerable<IList<T>>, потому как у нас уже есть возможность обращаться к MoveNext асинхронно. Мы не знаем, будет ли еще страница в результате. А IEnumerable<Task<IList<T>>> говорит о том, что ответ на вопрос будет ли еще страница мы можем получить лишь синхронно.
Да, верно. А не завернуть ли нам чтение из такого источника в хелпер?
Типа вместо
await foreach(var page in db.GetPages<Product>(...))
  foreach(var p in pages)
    this.Writer.Write(p);

вызывать
await db.GetPages<Product>.ForEach(p=>{this.Writer.Write(p)});

? Хотя, в целом даже и первый вариант выглядит не слишком отвратительно.

В общем, я себе в план работ поставил напиливание бенчмарка IAsyncEnumerable<T> супротив IEnumerable<T> и IAsyncEnumerable<IList<T>> супротив IAsyncEnumerable<T>.
Пока что настораживает https://github.com/JoshClose/CsvHelper/issues/1560.
Хотя статья в MSDN описывает подкапотность async yield return довольно позитивненько.
Вроде бы приложен максимум усилий к тому, чтобы код не тормозил.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[4]: json
От: Sinclair Россия https://github.com/evilguest/
Дата: 24.09.21 15:36
Оценка:
Здравствуйте, Sharov, Вы писали:
S>Никогда не задумывался, а json может работать потоково? Т.е. когда сериализумемая структура имеется не полностью?
Внезапно обнаружил вот такой вот сниппет:
private async IAsync Enumerable<Data> Generate(int maxItems)
{
    var random = new Random();
    for (int i = 0; i < maxItems; i++)
    {
        yield return new Data
        {
            Id = i,
            Value = random.Next().ToString()
        };
    }
}
 
public async Task SerializeStream()
{
    using var stream = Console.OpenStandardOutput();
    var data = new { Data = Generate(30) };
    await JsonSerializer.SerializeAsync(stream, data);
}

То есть да — внезапно, System.Text.Json из коробки cможет работать потоково, начиная с .Net 6. В том числе и асинхронно сериализовывать данные, готовые не полностью. Безо всяких приседаний вроде тех, что я привёл в предыдущем ответе.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Отредактировано 24.09.2021 16:46 Sinclair . Предыдущая версия .
Re[8]: Асинхронные стримы (IAsyncEnumerable)
От: samius Япония http://sams-tricks.blogspot.com
Дата: 26.09.21 07:48
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Да, верно. А не завернуть ли нам чтение из такого источника в хелпер?

S>Типа вместо
S>
S>await foreach(var page in db.GetPages<Product>(...))
S>  foreach(var p in pages)
S>    this.Writer.Write(p);
S>

S>вызывать
S>
S>await db.GetPages<Product>.ForEach(p=>{this.Writer.Write(p)});
S>

S>? Хотя, в целом даже и первый вариант выглядит не слишком отвратительно.
я бы предпочел этакий SelectMany, который берет элемент их асинхронного источника, клеит его с проекцией элемента в синхронную коллекцию, и возвращает, по всей видимости, IAsyncEnumerable<TResult>.
Re[9]: Асинхронные стримы (IAsyncEnumerable)
От: Sinclair Россия https://github.com/evilguest/
Дата: 26.09.21 12:27
Оценка:
Здравствуйте, samius, Вы писали:

S>Здравствуйте, Sinclair, Вы писали:


S>>Да, верно. А не завернуть ли нам чтение из такого источника в хелпер?

S>>Типа вместо
S>>
S>>await foreach(var page in db.GetPages<Product>(...))
S>>  foreach(var p in page)
S>>    this.Writer.Write(p);
S>>

S>>вызывать
S>>
S>>await db.GetPages<Product>.ForEach(p=>{this.Writer.Write(p)});
S>>

S>>? Хотя, в целом даже и первый вариант выглядит не слишком отвратительно.
S>я бы предпочел этакий SelectMany, который берет элемент их асинхронного источника, клеит его с проекцией элемента в синхронную коллекцию, и возвращает, по всей видимости, IAsyncEnumerable<TResult>.
хм. Типа
await foreach(var p in from page in db.GetPages<Product>()  
                       from p in page select p)
               await this.Writer.Write(p);

?
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[10]: Асинхронные стримы (IAsyncEnumerable)
От: samius Япония http://sams-tricks.blogspot.com
Дата: 26.09.21 12:48
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>хм. Типа

S>
S>await foreach(var p in from page in db.GetPages<Product>()  
S>                       from p in page select p)
S>               await this.Writer.Write(p);
S>

S>?

Да, как-то так. Но вот последний await this.Writer.Write(p) мне не нравится. Он выглядит синхронным.
Re[8]: Асинхронные стримы (IAsyncEnumerable)
От: Ночной Смотрящий Россия  
Дата: 30.09.21 07:06
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Да, верно. А не завернуть ли нам чтение из такого источника в хелпер?

S>Типа вместо
S>
S>await foreach(var page in db.GetPages<Product>(...))
S>  foreach(var p in pages)
S>    this.Writer.Write(p);
S>

S>вызывать
S>
S>await db.GetPages<Product>.ForEach(p=>{this.Writer.Write(p)});
S>


Твой любимый автор — https://ericlippert.com/2009/05/18/foreach-vs-foreach/
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.