
Vladimir
10.10.2018
14:28:10

Ayrat
10.10.2018
14:30:50
@neftedollar @fvnever @auduchinok
https://twitter.com/kskrygan/status/1049912749524967426
хотя я думаю двое последних уже в курсе)))

Grigoriy
10.10.2018
14:31:12
[офф-топикъ] где ж только время найти на то, чтобы всё попробовать. Надо докладик что ли про это на следующий дев дэй нашкрябать... про акку уже делал пару лет назад

Google

Roman
10.10.2018
14:38:44

Vladimir
10.10.2018
14:48:25

Grigoriy
10.10.2018
16:00:33
Ayrat я тут набрёл на такоэ - https://github.com/fsprojects/FSharp.Collections.ParallelSeq
4 строки и всё запараллелилось донельзя

アレクセイ
10.10.2018
16:02:07
это как PLinq?

Ayrat
10.10.2018
16:02:10

Grigoriy
10.10.2018
16:02:30
let res =
Directory.GetFiles("***")
|> PSeq.ordered
|> PSeq.withDegreeOfParallelism 10
|> PSeq.map (fun f ->
async {
use file = File.OpenRead(f)
return! graphClient.UploadFile(drive, Path.Combine( "***", Path.GetFileName(f)), file)
} |> Async.RunSynchronously)
|> PSeq.toList

Ayrat
10.10.2018
16:02:36

アレクセイ
10.10.2018
16:02:46
а

Grigoriy
10.10.2018
16:03:54
RunSync внутри что-то беспокоит

Ayrat
10.10.2018
16:04:17
А сигнатура у map не асинхронная чтоль? В утиль либу
Может там mapAsync есть?

Google

Grigoriy
10.10.2018
16:05:43
а как мне асинки внутре стартовать?

Ayrat
10.10.2018
16:06:27
Ну таким способом ты конечно добиваешься того что тебе надо но с блокировкой N тредов

Grigoriy
10.10.2018
16:07:07
да - вот я и говорю - RunSync беспокоит
как бы это вот всё с AsyncSeq поженить )

Ayrat
10.10.2018
16:08:44

Grigoriy
10.10.2018
16:09:19
за счёт ожидания конца чанка?

Ayrat
10.10.2018
16:09:28
Ааа

Grigoriy
10.10.2018
16:09:33
85 сек вс 50

Ayrat
10.10.2018
16:10:02
Так да. Но ты можешь в асинк сек сделать без чанков

Grigoriy
10.10.2018
16:10:45

Ayrat
10.10.2018
16:11:22
Индексируешь сиквенс, группируешь по признаку деления индекса - чтобы получить N групп, кидаешь в Async.Parallel
Тут будет тормозить группа) но это лучше чанков

Grigoriy
10.10.2018
16:13:14
...
|> AsyncSeq.ofSeq
|> AsyncSeq.bufferByCount filesChunk
|> AsyncSeq.mapAsync (fun c -> c |> Async.Parallel)

Ayrat
10.10.2018
16:14:01
чем?
Ты разбиваешь на Н групп и сразу скармливаешь их Н потокам

Grigoriy
10.10.2018
16:14:38
а.... наизнаку вывернуть

Ayrat
10.10.2018
16:14:46
Если есть тормозящие работы, они будут тормозить группу над которой трудится один поток, а не весь чанк над которым трудятся Н потоков
То есть не будет семеро одного ждут
Но если случайно в одну группу попадут только тормозные джобы, то другие потоки не помогут

Google

Ayrat
10.10.2018
16:16:25
И гопак всё ещё молодец
)

Grigoriy
10.10.2018
16:16:41

Friedrich
10.10.2018
16:37:03

Grigoriy
10.10.2018
16:46:06
берём список файлов, сортируем по убыванию размера - "размазываем" по N группам
ваще задача высосана из яйца, конечно... последовательный аплоад минуты 4 работает... АсинкСек с чанками - 1.5 минуты, PSeq 50 сек... надо, конечно, гопак попробовать для сравнения :)
Но пока меня не погдоняют - можно поэкспериментировать :)

Vasily
10.10.2018
16:50:46
Гопак ещё быстрее

Grigoriy
10.10.2018
16:51:05

Friedrich
10.10.2018
16:51:27

Grigoriy
10.10.2018
16:51:42
но, повторюсь, выше моего уровня компетенции

Vasily
10.10.2018
16:55:34

Grigoriy
10.10.2018
16:56:31
я неделю назад про AsyncSeq ничего не знал
так что может и до гопака дорасту

Vasily
10.10.2018
16:57:47
Дорастешь, конечно

Ayrat
10.10.2018
16:59:32

Google

Ayrat
10.10.2018
16:59:44
Но да, будет быстрее!!1
Просто, как мы выяснили, только гопак из коробки умеет в одну строчку обрабатывать с постоянным уровнем параллелизма

Friedrich
10.10.2018
17:19:46

Ayrat
10.10.2018
17:19:59

Friedrich
10.10.2018
17:20:03
Да, там дыбильное API, но, вроде, примерно в одну строчку можно записать

Ayrat
10.10.2018
17:21:03
обмажешься как следует
var source = new SourceFromSequence( sequence);
var block = new ParallelBlock(new ParallelBlockOptions( .... ))
block.Subscribe(new Subscription(source,block))
и уже ничего не хочется
только застрелиться
и с собой создателя прихватить

Ilya
10.10.2018
17:21:54
Вообще на тасках эту задачу можно решить как-то так.
let parallel degree (tasks: Task<'a> seq) = task {
let results = ResizeArray<'a>()
let executingTasks = ResizeArray<Task<'a>>()
for task in tasks do
if executingTasks.Count > degree then
let! oneResult = Task.WhenAny(executingTasks)
let! unwrapped = oneResult
results.Add(unwrapped)
executingTasks.Remove(oneResult) |> ignore
executingTasks.Add(task)
let! rest = Task.WhenAll(executingTasks)
results.AddRange(rest)
return results;
}


Ayrat
10.10.2018
17:23:36
https://docs.microsoft.com/en-us/dotnet/standard/parallel-programming/how-to-specify-the-degree-of-parallelism-in-a-dataflow-block
var workerBlock = new ActionBlock<int>(
// Simulate work by suspending the current thread.
millisecondsTimeout => Thread.Sleep(millisecondsTimeout),
// Specify a maximum degree of parallelism.
new ExecutionDataflowBlockOptions
{
MaxDegreeOfParallelism = maxDegreeOfParallelism
});
for (int i = 0; i < messageCount; i++)
{
workerBlock.Post(1000);
}
workerBlock.Complete();
// Wait for all messages to propagate through the network.
workerBlock.Completion.Wait();
Кошмарная либа для упоротых

Friedrich
10.10.2018
17:24:48
Да, она отвратительная.

Ayrat
10.10.2018
17:25:37

Grigoriy
10.10.2018
17:25:40
да Polly в сравненьи с этим - образец простоты
а говорили, что и оно отвратительное :)

Vasily
10.10.2018
17:27:27
Polly редкостное говно в сравнении с f#

Google

Ilya
10.10.2018
17:27:27

Ayrat
10.10.2018
17:27:37

Grigoriy
10.10.2018
17:27:54
да... я понял - буду курить. сам :)

Andrew
10.10.2018
17:36:24
Всем здравствуйте.
Имею такой интерфейс:
type IService =
abstract member StartDownload:
uri: string ->
dest: string ->
progressCb: (int64 -> int64 -> unit) ->
completeCb: (unit -> unit) ->
unit
Как добавить аннотацию к параметрам функции progressCb? Чтобы было например (bytesDownloaded: int64 -> totalBytes: int64 -> unit). На это компилятор ругается.

Grigoriy
10.10.2018
17:39:03
type BytesDownloaded = int64 ...
...
progressCb: (BytesDownloaded -> ...
ну или если совсем упороться type BytesDownloaded = BytesDownloaded of int64
но придётся анврапать

Andrew
10.10.2018
17:41:26
ндэ... интересно почему у F# нет нормального, человеческого способа это сделать. Очень обидно.

Grigoriy
10.10.2018
17:42:03
потому, что имя параметра к сигнатуре отношения не имеет кмк

Andrew
10.10.2018
17:43:02
это понятно. но упрощает чтение сигнатур. оно не для машин, а для людей должно было быть

Igor
10.10.2018
17:43:46
Ну так ты заведи typealias

Ayrat
10.10.2018
17:43:50
Через тайп алиас я только вижу

Andrew
10.10.2018
17:44:16
на каждый параметр каждой функции? расточительство имен. неудобно.

Ayrat
10.10.2018
17:44:48
type ProgressCbFunc = param1: int64 -> param2: int64 -> unit
type IServie =
...
progressCb: ProgressCbFunc

Igor
10.10.2018
17:44:59

Andrew
10.10.2018
17:45:04
пока вижу только в виде комментариев писать progressCb: ( (*байтов скачано*) int64 -> int64 -> unit)

Ayrat
10.10.2018
17:45:06

Friedrich
10.10.2018
17:45:25
Щас я тебе роскожу

Andrew
10.10.2018
17:45:34
буду рад ))

Friedrich
10.10.2018
17:46:07
Мне это как-то раз рил было нужно, потому что я юзал генератор коннекторов для WCF, а он в обяз требует имена у аргументов.