Неупорядоченный
У Raku нет упорядоченной очереди сообщений. В нем есть неупорядоченный список того, что нужно сделать.
# schedule them to run at the same second
# just to make it more likely that they will be out of order
my $wait = now + 1;
my @run;
for 1..20 -> $n {
push @run, Promise.at($wait).then: {say $n}
}
await @run;
Это могло напечатать числа в любом порядке.
1
2
3
4
5
6
7
8
11
12
13
14
15
16
17
18
9
10
19
20
Raku на самом деле многопоточен. Если вы приложите достаточно усилий, он будет использовать все ядра вашего процессора.
Это означает, что никогда не может быть способа сказать запустить это после того, как все, что в данный момент в очереди завершится.
Даже если бы я просто использовал start
, он иногда мог запускать что-то не по порядку.
my @run;
for 1..20 -> $n {
push @run, start {say $n}
};
await @run;
Вы можете запустить это сотни раз, прежде чем он начнет печатать что-то не в порядке, но в конечном итоге это произойдет.
Даже если вы перешли на низкий уровень и использовали $*SCHEDULER.cue
, нет гарантии, что он будет работать после всего остального.
my @nums;
for 1..100 -> $n {
$*SCHEDULER.cue: {push @nums, $n; say $n}
}
say @nums;
Мало того, что он может выйти из строя, массив @nums
, вероятно, не будет иметь всех значений, потому что каждый поток может сбивать с толку то, что делает другой поток.
Под капотом методы Promise, которые планируют выполнение чего-либо, в конечном итоге каким-то образом вызывают $*SCHEDULER.cue
.
Запланируйте что-нибудь еще
Вы можете сказать Raku запустить ваш код после чего-то еще.
my $p = Promise.in(1);
my $p2 = $p.then: {say 'first'}
my $p3 = $p.then: {say 'second'}
react {
whenever start say('first') {
whenever start say('second') {
}
}
}
Однако вам нужно иметь ссылку на эту вещь.
Медленный
Если бы у Raku был способ запускать что-то после текущих запланированных событий, то ему пришлось бы отслеживать, что выполняется, и следить за тем, чтобы ваш код не запускался до тех пор, пока они не будут завершены.
my $a = start {
# pointless busy-work that takes two seconds
my $wait = now + 2;
my $n = 0;
while now ≤ $wait {
$n++
}
say $n; # make sure the loop doesn't get optimized away
say 'first';
}
my $b = start say 'second';
await $a, $b;
second
1427387
first
Если это обеспечит запуск $b
после $a
, то на $b
в течение двух целых секунд не будет выполняться никакая работа.
Вместо этого он просто заставляет $b
работать в другом потоке, потому что тот, который имеет дело с $a
, в настоящее время занят.
Это хорошо, потому что что, если $b
тоже будет медленным. Мы бы запланировали две медленные вещи, которые будут выполняться последовательно, а не параллельно.
Javascript
Я думаю, что единственная причина, по которой он в настоящее время работает в Javascript, заключается в том, что он, похоже, не использует преимущества нескольких ядер процессора. Или в нем что-то вроде GIL.
Я написал код Raku, в котором мой 4-ядерный процессор загружен на 500%. (Гиперпоточный процессор Intel, где одно ядро выглядит как 2 ядра)
Я не уверен, что вы можете сделать то же самое с одной программой Javascript.
person
Brad Gilbert
schedule
25.05.2021