[squeak-dev] CustomHelpToOrg dev question.

Levente Uzonyi leves at caesar.elte.hu
Fri Sep 3 21:38:40 UTC 2021


Hi Chris,

On Fri, 3 Sep 2021, Chris Muller wrote:

> Hi Levente,
>
>       An easy way to avoid that would be to write directly into the file stream,
>       but Squeak's file streams are not write-buffered
> 
> 
> Hm, I always thought they were.  A quick script I used to verify:
> 
> | ws rs |
> nil assert: (FileDirectory default fileExists: 'writebuffered') not.
> FileDirectory default deleteFileNamed: 'writebuffered'.
> [ws := FileStream fileNamed: 'writebuffered'.
> rs := FileStream readOnlyFileNamed: 'writebuffered'.
> ws nextPutAll: '12345678901'.
> "Assert only buffered, not written"
>    nil assert: (rs next: 10) isEmpty.
> "Force physical write"
>    ws flush.
> "Assert written"
>    nil assert: (rs next: 10) = '1234567890' ] ensure:
> [ ws ifNotNil: [ws close].
> rs ifNotNil: [rs close] ]

What I meant was actual write buffering at the image level.
Without that, each write operation (e.g. #nextPut:) will invoke a 
primitive to write the contents to the file.
Here's an example which also demonstrates the effect of read buffering as 
a reference:

| filename n |
filename := UUID new asString36.
n := 1000000.
[ {
 	StandardFileStream newFileNamed: filename do: [ :file |
 		[ n timesRepeat: [ file nextPut: $x ] ] timeToRun ].
 	StandardFileStream forceNewFileNamed: filename do: [ :file |
 		[ n timesRepeat: [ file nextPutAll: 'x' ] ] timeToRun ].
 	StandardFileStream forceNewFileNamed: filename do: [ :file |
 		[ file nextPutAll: (String new: n streamContents: [ :s |
 			n timesRepeat: [ s nextPut: $x ] ]) ] timeToRun ].
 	StandardFileStream forceNewFileNamed: filename do: [ :file |
 		[ file nextPutAll: (String new: n withAll: $x) ] timeToRun ].
 	StandardFileStream readOnlyFileNamed: filename do: [ :file |
 		[ n timesRepeat: [ file next ] ] timeToRun ].
 	StandardFileStream readOnlyFileNamed: filename do: [ :file |
 		file disableReadBuffering.
 		[ n timesRepeat: [ file next ] ] timeToRun ].
 	StandardFileStream readOnlyFileNamed: filename do: [ :file |
 		[ file next: n ] timeToRun ].} ]
 	ensure: [ FileDirectory default deleteFileNamed: filename ]
"==> #(137 116 16 1 20 135 1)"

The first two blocks write directly to the file, one character a time with 
#nextPut: and #nextPutAll:, respectively.
The third one writes to an in-memory stream first, one character a time, 
then writes the whole string in a single operation to the file.
The fourth one is the same as the third but creates the string directly 
without streaming the characters one-by-one.
The fifth block reads back the file, one character a time using read 
buffering which is enabled by default.
The sixth block does the same but without read buffering.
The seventh block reads the contents of the file in a single read 
operation.


Levente


More information about the Squeak-dev mailing list