Quellcode durchsuchen

* dynamically grow the size of oschunks allocated for use by the memory
pools for small blocks (fixedfreelists) when lots of such oschunks
are allocated successively, in order to reduce the overhead of
allocating such chunks from the OS (and of freeing them afterwards)

git-svn-id: trunk@15618 -

Jonas Maebe vor 15 Jahren
Ursprung
Commit
e150c2c521
1 geänderte Dateien mit 45 neuen und 4 gelöschten Zeilen
  1. 45 4
      rtl/inc/heap.inc

+ 45 - 4
rtl/inc/heap.inc

@@ -55,8 +55,16 @@ const
   ocrecycleflag  = 1;
   ocrecycleflag  = 1;
   { above flags stored in size field }
   { above flags stored in size field }
   sizemask = not(blocksize-1);
   sizemask = not(blocksize-1);
-  fixedoffsetshift = 16;
+  fixedoffsetshift = 12;
   fixedsizemask = sizemask and ((1 shl fixedoffsetshift) - 1);
   fixedsizemask = sizemask and ((1 shl fixedoffsetshift) - 1);
+  { After how many successive allocations of oschunks for fixed freelist
+    purposes should we double the size of locgrowheapsizesmall for the
+    current thread. Since the allocations of oschunks are added together for
+    all blocksizes, this is only a fuzzy indication of when the size will be
+    doubled rather than a hard and fast boundary. }
+  fixedallocthreshold = (maxblocksize shr blockshift) * 2;
+  { maximum size to which locgrowheapsizesmall can grow }
+  maxgrowheapsizesmall = 256*1024;
 
 
 {****************************************************************************}
 {****************************************************************************}
 
 
@@ -167,9 +175,23 @@ type
 
 
   tfreelists = record
   tfreelists = record
     oslist : poschunk;      { os chunks free, available for use }
     oslist : poschunk;      { os chunks free, available for use }
+    fixedlists : tfixedfreelists;
     oscount : dword;        { number of os chunks on oslist }
     oscount : dword;        { number of os chunks on oslist }
+    { we gradually grow the size of the blocks used for fixed allocations in
+      case many of them are allocated. However, don't take successive
+      allocate/free cases into account, since that mean the block's size is
+      fine and that the program simply exhibits a cyclic behaviour (in which
+      case increasing the blocksize could even slow things down due to the
+      subdividing overhead) and MaxKeptOSChunks should probably be increased
+      instead. }
+    lastfixedopwasalloc: boolean;
+    { how many oschunks have been successively allocated in this thread since
+      the last time we doubled the locgrowheapsizesmall size }
+    fixedallocated: byte;
+    { the size of oschunks allocated for fixed allocations in this thread;
+      initialised on thread creation with the global growheapsizesmall setting }
+    locgrowheapsizesmall: ptruint;
     oslist_all : poschunk;  { all os chunks allocated }
     oslist_all : poschunk;  { all os chunks allocated }
-    fixedlists : tfixedfreelists;
     varlist : pmemchunk_var;
     varlist : pmemchunk_var;
     { chunks waiting to be freed from other thread }
     { chunks waiting to be freed from other thread }
     waitfixed : pmemchunk_fixed;
     waitfixed : pmemchunk_fixed;
@@ -476,6 +498,7 @@ procedure free_oschunk(loc_freelists: pfreelists; poc: poschunk);
 var
 var
   pocsize: ptruint;
   pocsize: ptruint;
 begin
 begin
+  loc_freelists^.lastfixedopwasalloc:=false;
   remove_freed_fixed_chunks(poc);
   remove_freed_fixed_chunks(poc);
   if assigned(poc^.prev_any) then
   if assigned(poc^.prev_any) then
     poc^.prev_any^.next_any := poc^.next_any
     poc^.prev_any^.next_any := poc^.next_any
@@ -781,9 +804,9 @@ begin
       { allocate smaller blocks for fixed-size chunks }
       { allocate smaller blocks for fixed-size chunks }
       if chunkindex<>0 then
       if chunkindex<>0 then
         begin
         begin
-          poc := SysOSAlloc(GrowHeapSizeSmall);
+          poc := SysOSAlloc(loc_freelists^.LocGrowHeapSizeSmall);
           if poc<>nil then
           if poc<>nil then
-            size := GrowHeapSizeSmall;
+            size := loc_freelists^.LocGrowHeapSizeSmall;
         end
         end
     { first try 256K (default) }
     { first try 256K (default) }
       else if size<=GrowHeapSize1 then
       else if size<=GrowHeapSize1 then
@@ -860,6 +883,21 @@ begin
       if pmc_next<>nil then
       if pmc_next<>nil then
         pmc_next^.prev_fixed := pmc;
         pmc_next^.prev_fixed := pmc;
       loc_freelists^.fixedlists[chunkindex] := pmemchunk_fixed(result);
       loc_freelists^.fixedlists[chunkindex] := pmemchunk_fixed(result);
+      { check whether we should increase the size of the fixed freelist blocks }
+      if (loc_freelists^.lastfixedopwasalloc) then
+        begin
+          inc(loc_freelists^.fixedallocated);
+          if (loc_freelists^.fixedallocated > fixedallocthreshold) then
+            begin
+              if (loc_freelists^.locgrowheapsizesmall < maxgrowheapsizesmall) then
+                inc(loc_freelists^.locgrowheapsizesmall,loc_freelists^.locgrowheapsizesmall);
+              { also set to zero in case we did not grow the blocksize to
+                prevent oveflows of this counter in case the rtl is compiled
+                range/overflow checking }
+              loc_freelists^.fixedallocated:=0;
+            end;
+        end;
+      loc_freelists^.lastfixedopwasalloc:=true;
     end
     end
   else
   else
     begin
     begin
@@ -1458,6 +1496,9 @@ begin
 {$endif}
 {$endif}
   loc_freelists := @freelists;
   loc_freelists := @freelists;
   fillchar(loc_freelists^,sizeof(tfreelists),0);
   fillchar(loc_freelists^,sizeof(tfreelists),0);
+  { initialise the local blocksize for allocating oschunks for fixed
+    freelists with the default starting value }
+  loc_freelists^.locgrowheapsizesmall:=growheapsizesmall;
   fillchar(orphaned_freelists,sizeof(orphaned_freelists),0);
   fillchar(orphaned_freelists,sizeof(orphaned_freelists),0);
 end;
 end;