Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit9ad1b57

Browse files
committed
Allow repalloc() to give back space when a large chunk is downsized.
Up to now, if you resized a large (>8K) palloc chunk down to a smallersize, aset.c made no attempt to return any space to the malloc pool.That's unpleasant if a really large allocation is resized to asignificantly smaller size. I think no such cases existed when thiscode was designed, and I'm not sure whether they're common even yet,but an upcoming fix to encoding conversion will certainly create suchcases. Therefore, fix AllocSetRealloc so that it gives realloc()a chance to do something with the block. This doesn't noticeablyincrease complexity, we mostly just have to change the order in whichthe cases are considered.Back-patch to all supported branches.Discussion:https://postgr.es/m/20190816181418.GA898@alvherre.pgsqlDiscussion:https://postgr.es/m/3614.1569359690@sss.pgh.pa.us
1 parentede0ab6 commit9ad1b57

File tree

1 file changed

+76
-64
lines changed

1 file changed

+76
-64
lines changed

‎src/backend/utils/mmgr/aset.c

Lines changed: 76 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -932,61 +932,12 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
932932
set->header.name,chunk);
933933
#endif
934934

935-
/*
936-
* Chunk sizes are aligned to power of 2 in AllocSetAlloc(). Maybe the
937-
* allocated area already is >= the new size. (In particular, we always
938-
* fall out here if the requested size is a decrease.)
939-
*/
940-
if (oldsize >=size)
941-
{
942-
#ifdefMEMORY_CONTEXT_CHECKING
943-
Sizeoldrequest=chunk->requested_size;
944-
945-
#ifdefRANDOMIZE_ALLOCATED_MEMORY
946-
/* We can only fill the extra space if we know the prior request */
947-
if (size>oldrequest)
948-
randomize_mem((char*)pointer+oldrequest,
949-
size-oldrequest);
950-
#endif
951-
952-
chunk->requested_size=size;
953-
VALGRIND_MAKE_MEM_NOACCESS(&chunk->requested_size,
954-
sizeof(chunk->requested_size));
955-
956-
/*
957-
* If this is an increase, mark any newly-available part UNDEFINED.
958-
* Otherwise, mark the obsolete part NOACCESS.
959-
*/
960-
if (size>oldrequest)
961-
VALGRIND_MAKE_MEM_UNDEFINED((char*)pointer+oldrequest,
962-
size-oldrequest);
963-
else
964-
VALGRIND_MAKE_MEM_NOACCESS((char*)pointer+size,
965-
oldsize-size);
966-
967-
/* set mark to catch clobber of "unused" space */
968-
if (size<oldsize)
969-
set_sentinel(pointer,size);
970-
#else/* !MEMORY_CONTEXT_CHECKING */
971-
972-
/*
973-
* We don't have the information to determine whether we're growing
974-
* the old request or shrinking it, so we conservatively mark the
975-
* entire new allocation DEFINED.
976-
*/
977-
VALGRIND_MAKE_MEM_NOACCESS(pointer,oldsize);
978-
VALGRIND_MAKE_MEM_DEFINED(pointer,size);
979-
#endif
980-
981-
returnpointer;
982-
}
983-
984935
if (oldsize>set->allocChunkLimit)
985936
{
986937
/*
987938
* The chunk must have been allocated as a single-chunk block. Use
988-
* realloc() to make the containing block bigger with minimum space
989-
* wastage.
939+
* realloc() to make the containing block bigger, or smaller, with
940+
*minimum spacewastage.
990941
*/
991942
AllocBlockblock= (AllocBlock) (((char*)chunk)-ALLOC_BLOCKHDRSZ);
992943
Sizechksize;
@@ -1000,11 +951,19 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
1000951
if (block->aset!=set||
1001952
block->freeptr!=block->endptr||
1002953
block->freeptr!= ((char*)block)+
1003-
(chunk->size+ALLOC_BLOCKHDRSZ+ALLOC_CHUNKHDRSZ))
954+
(oldsize+ALLOC_BLOCKHDRSZ+ALLOC_CHUNKHDRSZ))
1004955
elog(ERROR,"could not find block containing chunk %p",chunk);
1005956

957+
/*
958+
* Even if the new request is less than set->allocChunkLimit, we stick
959+
* with the single-chunk block approach. Therefore we need
960+
* chunk->size to be bigger than set->allocChunkLimit, so we don't get
961+
* confused about the chunk's status in future calls.
962+
*/
963+
chksize=Max(size,set->allocChunkLimit+1);
964+
chksize=MAXALIGN(chksize);
965+
1006966
/* Do the realloc */
1007-
chksize=MAXALIGN(size);
1008967
blksize=chksize+ALLOC_BLOCKHDRSZ+ALLOC_CHUNKHDRSZ;
1009968
block= (AllocBlock)realloc(block,blksize);
1010969
if (block==NULL)
@@ -1025,17 +984,21 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
1025984
#ifdefMEMORY_CONTEXT_CHECKING
1026985
#ifdefRANDOMIZE_ALLOCATED_MEMORY
1027986
/* We can only fill the extra space if we know the prior request */
1028-
randomize_mem((char*)pointer+chunk->requested_size,
1029-
size-chunk->requested_size);
987+
if (size>chunk->requested_size)
988+
randomize_mem((char*)pointer+chunk->requested_size,
989+
size-chunk->requested_size);
1030990
#endif
1031991

1032992
/*
1033-
* realloc() (or randomize_mem()) will have leftthe newly-allocated
993+
* realloc() (or randomize_mem()) will have leftany newly-allocated
1034994
* part UNDEFINED, but we may need to adjust trailing bytes from the
1035995
* old allocation.
1036996
*/
1037-
VALGRIND_MAKE_MEM_UNDEFINED((char*)pointer+chunk->requested_size,
1038-
oldsize-chunk->requested_size);
997+
#ifdefUSE_VALGRIND
998+
if (oldsize>chunk->requested_size)
999+
VALGRIND_MAKE_MEM_UNDEFINED((char*)pointer+chunk->requested_size,
1000+
oldsize-chunk->requested_size);
1001+
#endif
10391002

10401003
chunk->requested_size=size;
10411004
VALGRIND_MAKE_MEM_NOACCESS(&chunk->requested_size,
@@ -1059,15 +1022,64 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
10591022

10601023
returnpointer;
10611024
}
1025+
1026+
/*
1027+
* Chunk sizes are aligned to power of 2 in AllocSetAlloc(). Maybe the
1028+
* allocated area already is >= the new size. (In particular, we will
1029+
* fall out here if the requested size is a decrease.)
1030+
*/
1031+
elseif (oldsize >=size)
1032+
{
1033+
#ifdefMEMORY_CONTEXT_CHECKING
1034+
Sizeoldrequest=chunk->requested_size;
1035+
1036+
#ifdefRANDOMIZE_ALLOCATED_MEMORY
1037+
/* We can only fill the extra space if we know the prior request */
1038+
if (size>oldrequest)
1039+
randomize_mem((char*)pointer+oldrequest,
1040+
size-oldrequest);
1041+
#endif
1042+
1043+
chunk->requested_size=size;
1044+
VALGRIND_MAKE_MEM_NOACCESS(&chunk->requested_size,
1045+
sizeof(chunk->requested_size));
1046+
1047+
/*
1048+
* If this is an increase, mark any newly-available part UNDEFINED.
1049+
* Otherwise, mark the obsolete part NOACCESS.
1050+
*/
1051+
if (size>oldrequest)
1052+
VALGRIND_MAKE_MEM_UNDEFINED((char*)pointer+oldrequest,
1053+
size-oldrequest);
1054+
else
1055+
VALGRIND_MAKE_MEM_NOACCESS((char*)pointer+size,
1056+
oldsize-size);
1057+
1058+
/* set mark to catch clobber of "unused" space */
1059+
if (size<oldsize)
1060+
set_sentinel(pointer,size);
1061+
#else/* !MEMORY_CONTEXT_CHECKING */
1062+
1063+
/*
1064+
* We don't have the information to determine whether we're growing
1065+
* the old request or shrinking it, so we conservatively mark the
1066+
* entire new allocation DEFINED.
1067+
*/
1068+
VALGRIND_MAKE_MEM_NOACCESS(pointer,oldsize);
1069+
VALGRIND_MAKE_MEM_DEFINED(pointer,size);
1070+
#endif
1071+
1072+
returnpointer;
1073+
}
10621074
else
10631075
{
10641076
/*
1065-
*Small-chunk case. We just do this by brute force, ie, allocate a
1066-
* new chunk and copy the data. Since we know the existing data isn't
1067-
* huge, this won't involve any great memcpy expense, so it's not
1068-
* worth being smarter. (At one time we tried to avoid memcpy when it
1069-
* was possible to enlarge the chunk in-place, but that turns out to
1070-
* misbehave unpleasantly for repeated cycles of
1077+
*Enlarge-a-small-chunk case. We just do this by brute force, ie,
1078+
*allocate anew chunk and copy the data. Since we know the existing
1079+
*data isn'thuge, this won't involve any great memcpy expense, so
1080+
*it's notworth being smarter. (At one time we tried to avoid
1081+
*memcpy when itwas possible to enlarge the chunk in-place, but that
1082+
*turns out tomisbehave unpleasantly for repeated cycles of
10711083
* palloc/repalloc/pfree: the eventually freed chunks go into the
10721084
* wrong freelist for the next initial palloc request, and so we leak
10731085
* memory indefinitely. See pgsql-hackers archives for 2007-08-11.)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp