Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>First, you are assuming the <code>TStream</code> is the bottleneck. You need to profile your code, such as with AQTime, to determine where the bottleneck really is. Don't make assumptions.</p> <p>Second, what type of <code>TStream</code> are you actually using? <code>TMemoryStream</code>? <code>TFileStream</code>? Something else? Different stream types handle memory differently. TMemoryStream allocates a memory buffer and grows it by a pre-set amount of bytes whenever the buffer fills up. <code>TFileStream</code>, on the other hand, doesn't use any memory at all, it just writes directly to the file and lets the OS handle any buffering.</p> <p>Regardless of which type of stream you use, one thing you could try is implement your own custom <code>TStream</code> class that has an internal fixed-size buffer and a pointer to your real destination <code>TStream</code> object. You can then pass an instance of your custom class to your algorithm. Have your class override the <code>TStream::Write()</code> method to copy the input data into its buffer until it fills up, then you can <code>Write()</code> the buffer to the destination <code>TStream</code> and clear the buffer. Your algorithm will never know the difference. Both <code>TMemoryStream</code> and <code>TFileStream</code> would benefit from the extra buffering - fewer larger writes means more efficient memory allocations and file I/O. For example:</p> <pre><code>type TMyBufferedStreamWriter = class(TStream) private fDest: TStream; fBuffer: array[0..4095] of Byte; fOffset: Cardinal; public constructor Create(ADest: TStream); function Read(var Buffer; Count: Longint): Longint; override; function Write(const Buffer; Count: Longint): Longint; override; procedure FlushBuffer; end; </code></pre> <p>.</p> <pre><code>uses RTLConsts; constructor TMyBufferedStreamWriter.Create(ADest: TStream); begin fDest := ADest; end; function TMyBufferedStreamWriter.Read(var Buffer; Count: Longint): Longint; begin Result := 0; end; function TMyBufferedStreamWriter.Write(const Buffer; Count: Longint): Longint; var pBuffer: PByte; Num: Cardinal; begin Result := 0; pBuffer := PByte(@Buffer); while Count &gt; 0 do begin Num := Min(SizeOf(fBuffer) - fOffset, Cardinal(Count)); if Num = 0 then FlushBuffer; Move(pBuffer^, fBuffer[fOffset], Num); Inc(fOffset, Num); Inc(pBuffer, Num); Dec(Count, Num); Inc(Result, Num); end; end; procedure TMyBufferedStreamWriter.FlushBuffer; var Idx: Cardinal; Written: Longint; begin if fOffset = 0 then Exit; Idx := 0; repeat Written := fDest.Write(fBuffer[Idx], fOffset - Idx); if Written &lt; 1 then raise EWriteError.CreateRes(@SWriteError); Inc(Idx, Written); until Idx = fOffset; fOffset := 0; end; </code></pre> <p>.</p> <pre><code>Writer := TMyBufferedStreamWriter.Create(RealStreamHere); try ... write data to Writer normally as needed... Writer.FlushBuffer; finally Writer.Free; end; </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload