#dart #file-io #dart-io
Вопрос:
Я занимаюсь проектом, который включает в себя генерацию 1 миллиарда случайных чисел 0/1 и хранение их в файле. Это мой код:
import 'dart:io';
import 'dart:math';
final int COUNT = 1000000000;
final Random randomizer = new Random();
final File file = new File('./dart/dart.txt');
void main() {
if (file.existsSync()) {
file.deleteSync();
}
file.createSync();
DateTime before = new DateTime.now();
IOSink sink = file.openWrite(mode: FileMode.append);
for (int i = 0; i < COUNT; i ) {
sink.write(nextNumber().toString());
}
sink.close();
DateTime after = new DateTime.now();
print(after.millisecondsSinceEpoch - before.millisecondsSinceEpoch);
}
int nextNumber() {
return randomizer.nextInt(2);
}
Это прекрасно работает COUNT=10000
, если для генерации 10000 случайных чисел требуется дюжина миллисекунд. Однако, когда я собрал COUNT
1 миллиард, это заняло около 25 ГБ моей оперативной памяти и продолжалось более 40 минут без остановок. Мне пришлось убить процесс, вместо того чтобы позволить ему продолжать работать.
Как я могу это исправить?
P.S. Я не могу изменить язык программирования, так как использование разных языков программирования для генерации таких чисел является одним из аспектов моего проекта. Я также использую C , Java, Javascript, PS, Python и т.д. Для создания таких больших данных, и ни один из них не сталкивался с этой проблемой. Конечный файл, в котором хранятся данные, составляет менее 1 ГБ.
Комментарии:
1. Обратите внимание, что вы измеряете время для вычисления
COUNT
случайных чисел, но не время для их записи на диск (поскольку вы пренебрегаете этимawait sink.flush(); await sink.close();
в первую очередь). Поэтому кажущееся затраченное время не будет масштабироваться так, как ожидалось. Я также подозреваю, чтоIOSink
это не приводит к автоматической очистке буфера, когда он становится слишком полным, поэтому вы в конечном итоге буферизуете всеCOUNT
значения. Возможно, вам следуетawait sink.flush();
периодически звонить (например, каждые 10000 итераций), что, надеюсь, исправит использование оперативной памяти (и, возможно, поможет с продолжительностью, если использование оперативной памяти вызвало подкачку).2. Я понял, что дело не в том , что
IOSink
буфер не очищается автоматически (и вы можете наблюдать, чтоdart.txt
он растет без явной очистки), а в том, что без случайногоawait sink.flush();
цикла ваши данные генерируются намного быстрее, чем они могут быть записаны на диск, поэтомуIOSink
в конечном итоге буферизуются почти все.