Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 6538217
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 25, 20262026-05-25T10:42:38+00:00 2026-05-25T10:42:38+00:00

I am looking into generating a file ( 750 MB ) full of random

  • 0

I am looking into generating a file ( 750 MB ) full of random bytes. The code I am using in a separate thread looks like this:

I allocated a buffer of that size since writing on the disk consumes more time:

function Generate(buf:Pointer):DWORD;stdcall;
var
i:DWORD;
begin
      for i := 0 to keysize -1 do
            PByte(DWORD(buf) + i)^ := Random(256);
      Result:=0;
end;

The problem is that it takes ages until the process completes. Any ideas for a faster method? I will try to implement it in assembly if there isn’t any alternative.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-25T10:42:38+00:00Added an answer on May 25, 2026 at 10:42 am

    This sounded like a nice practice problem so I went ahead and implemented a parallel solution. It uses slightly over 3 seconds to generate 750 MB file and uses over 90% CPU during its work. (SSD disk helps, too. 3,5 seconds were needed to generate the file on a RAID0 disk pair and 4 seconds to generate a file on a slower 512 GB disk.)

    All reused code is available with the OpenBSD license (which is almost “use however you wish”): DSiWin32, GpStuff, GpRandomGen, Otl*.

    uses
      DSiWin32,
      GpStuff,
      GpRandomGen,
      OtlCommon,
      OtlCollections,
      OtlParallel;
    
    {$R *.dfm}
    
    procedure FillBuffer(buf: pointer; bufSize: integer; randomGen: TGpRandom);
    var
      buf64: PInt64;
      buf8 : PByte;
      i    : integer;
      rnd  : int64;
    begin
      buf64 := buf;
      for i := 1 to bufSize div SizeOf(int64) do begin
        buf64^ := randomGen.Rnd64;
        Inc(buf64);
      end;
      rnd := randomGen.Rnd64;
      buf8 := PByte(buf64);
      for i := 1 to bufSize mod SizeOf(int64) do begin
        buf8^ := rnd AND $FF;
        rnd := rnd SHR 8;
        Inc(buf8);
      end;
    end; { FillBuffer }
    
    procedure CreateRandomFile(fileSize: integer; output: TStream);
    const
      CBlockSize = 1 * 1024 * 1024 {1 MB};
    var
      buffer        : TOmniValue;
      lastBufferSize: integer;
      memStr        : TMemoryStream;
      numBuffers    : integer;
      outQueue      : IOmniBlockingCollection;
    begin
      outQueue := TOmniBlockingCollection.Create;
      numBuffers := (fileSize - 1) div CBlockSize + 1;
      lastBufferSize := (fileSize - 1) mod CBlockSize + 1;
      Parallel.ForEach(1, numBuffers).NoWait
        .NumTasks(Environment.Process.Affinity.Count)
        .OnStop(
          procedure
          begin
            outQueue.CompleteAdding;
          end)
        .Initialize(
          procedure(var taskState: TOmniValue)
          begin
            taskState := TGpRandom.Create;
          end)
        .Finalize(
          procedure(const taskState: TOmniValue)
          begin
            taskState.AsObject.Free;
          end)
        .Execute(
          procedure(const value: integer; var taskState: TOmniValue)
          var
            buffer      : TMemoryStream;
            bytesToWrite: integer;
          begin
            if value = numBuffers then
              bytesToWrite := lastBufferSize
            else
              bytesToWrite := CBlockSize;
            buffer := TMemoryStream.Create;
            buffer.Size := bytesToWrite;
            FillBuffer(buffer.Memory, bytesToWrite, taskState.AsObject as TGpRandom);
            outQueue.Add(buffer);
          end);
      for buffer in outQueue do begin
        memStr := buffer.AsObject as TMemoryStream;
        output.CopyFrom(memStr, 0);
        FreeAndNil(memStr);
      end;
    end;
    
    procedure TForm43.btnRandomClick(Sender: TObject);
    var
      fileStr: TFileStream;
      time   : int64;
    begin
      time := DSiTimeGetTime64;
      try
        fileStr := TFileStream.Create('e:\0\random.dat', fmCreate);
        try
          CreateRandomFile(750*1024*1024, fileStr);
        finally FreeAndNil(fileStr); end;
      finally Caption := Format('Completed in %d ms', [DSiElapsedTime64(time)]); end;
    end;
    

    EDIT: Using ForEach in this case was not really elegant solution so I enhanced OmniThreadLibrary with Parallel.ParallelTask and with better IOmniCounter. Using release 993 (or newer) from the SVN you can solve this multiple-producer-single-consumer problem as follows.

    procedure CreateRandomFile(fileSize: integer; output: TStream);
    const
      CBlockSize = 1 * 1024 * 1024 {1 MB};
    var
      buffer   : TOmniValue;
      memStr   : TMemoryStream;
      outQueue : IOmniBlockingCollection;
      unwritten: IOmniCounter;
    begin
      outQueue := TOmniBlockingCollection.Create;
      unwritten := CreateCounter(fileSize);
      Parallel.ParallelTask.NoWait
        .NumTasks(Environment.Process.Affinity.Count)
        .OnStop(Parallel.CompleteQueue(outQueue))
        .Execute(
          procedure
          var
            buffer      : TMemoryStream;
            bytesToWrite: integer;
            randomGen   : TGpRandom;
          begin
            randomGen := TGpRandom.Create;
            try
              while unwritten.Take(CBlockSize, bytesToWrite) do begin
                buffer := TMemoryStream.Create;
                buffer.Size := bytesToWrite;
                FillBuffer(buffer.Memory, bytesToWrite, randomGen);
                outQueue.Add(buffer);
              end;
            finally FreeAndNil(randomGen); end;
          end
        );
      for buffer in outQueue do begin
        memStr := buffer.AsObject as TMemoryStream;
        output.CopyFrom(memStr, 0);
        FreeAndNil(memStr);
      end;
    end;
    

    EDIT2: A longer blog post about this problem: Life after 2.1: Parallel data production (Introducing Parallel.Task)

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

Am looking into developing an iPhone native app using Titanium Developer Since this is
Program I'm making has a simple configuration file looking something like this. @overlays =
I've been looking into using EasyMock 3's IMockBuilder as a means of generating partial
I'm looking into playing around with procedurally generating music. I'm hoping to find a
I looking into making a kind of robot testing browser. Like Selenium, but one
I'm looking into using Visual Studio 2008's built in unit test projects instead of
Just been looking at a code golf question about generating a sorted list of
I'm looking at some existing code that is generating a salt which is used
I'm looking into generating types dynamically, ie. TypeBuilder , Reflection.Emit .. Is it ever
Looking into selector performance between $('#ID1, #ID2, #ID3') vs $('1X CLASS'). Which is faster?

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.