Я сейчас пишу программу, которая генерирует файл. Я задавался вопросом, каковы лучшие практики в Стриме (ах), особенно когда речь идет о размере? Я могу себе представить, что если поток становится слишком большим, это может привести к замедлению или другим проблемам с производительностью.
У меня есть следующий код, который можно вызывать много-много раз, так как коллекция может быть огромной. Я предполагаю, что для разных размеров нужно вести себя по-разному, например, <1 МБ <=> 10 МБ <=> 100 МБ <=> до 1-10 ГБ <=>> 10 ГБ
writeIntoStream: anInputStringCollection
aWriteStream := WriteStream on: '' asUnicode16String.
anInputStringCollection do: [ :string |
aWriteStream nextPutAllUnicode: string asUnicode16String.
].
^ aWriteStream
Каковы лучшие практики? Например, нужно ли заботиться, подходит ли он куче или стеку?
На данный момент я пришел к выводу, что если я использую максимум 5 КБ для потока (или коллекции), он достаточно быстрый и работает (для Smalltalk / X).
Я хотел бы знать пределы и внутренности для различных вкусов Smalltalk. (Я не выполнил ни одного теста и не смог найти ни одной статьи о нем)
Редактировать: Первое спасибо всем (@LeandroCaniglia, @JayK, @ aka.nice).
Самая первая версия была - замедления были вызваны многими операциями: открыть, записать, закрыть. Написано построчно:
write: newString to: aFile
"Writes keyName, keyValue to a file"
"/ aFile is UTF16-LE (Little Endian) Without Signature (BOM)
aFile appendingFileDo: [ :stream |
stream nextPutAllUtf16Bytes: newString MSB: false
]
Вторая версия, намного быстрее, но все еще не верна. Это был
промежуточный поток, который был написан кусками, был:
write: aWriteStream to: aFile
"Writes everything written to the stream"
"/ aFile is UTF16-LE Without Signature
aFile appendingFileDo: [ :stream | "/ withoutTrailingSeparators must be there as Stream puts spaces at the end
stream nextPutAllUtf16Bytes: (aWriteStream contents withoutTrailingSeparators) MSB: false
]
Третья версия после ответа Леандро и вашего совета (я посмотрел на буфер - размер определяется как __stringSize(aCollection)
, когда доступный буфер / память исчерпан, затем записывается в файл. Я удалил #write:to:
все вместе и Теперь поток определяется как:
anAppendFileStream := aFile appendingWriteStream.
Каждый метод, который принимает воспроизведение в потоке, теперь использует:
anAppendFileStream nextPutUtf16Bytes: aCharacter MSB: false.
или
anAppendFileStream nextPutAllUtf16Bytes: string MSB: false
Что касается самого размера буфера:
Существует логика размера буфера, в которой происходит угадание длины буфера, например, #nextPutAll:
- bufLen = (sepLen == 1) ? len : (len + ((len/4) + 1) * sepLen);)
, где sepLen
определяется на основе размера разделителя (EOF, cr, crlf).
Там могут быть разные размеры буфера для разных методов, например #copyToEndFrom:
- для окон: bufferSize := 1 * 1024
или * nix bufferSize := 8 * 1024
[кБ].