Subject: amap_extend does unnecessary malloc/memcpy.
To: None <tech-kern@netbsd.org>
From: enami tsugutomo <enami@but-b.or.jp>
List: tech-kern
Date: 11/17/2001 00:12:22
Hi.
I recently found amap_extend does unnecessary malloc and memcpy. Here
is a chagnes to allocate optimal size when extending amap with
assuming some malloc implementation and sizeof(int) and
sizeof(pointer).
Do you see any problem with this change?
Here is some benchmark; a time to build my kernel with
normal kernel:
382.95 real 303.87 user 39.98 sys
382.50 real 304.45 user 40.32 sys
382.52 real 303.79 user 39.78 sys
patched kernel:
370.48 real 298.90 user 33.52 sys
371.88 real 297.05 user 34.53 sys
370.66 real 299.46 user 32.58 sys
# we probably can't use realloc here since we don't want to copy
# vectors without locking.
enami.
Index: uvm_amap.c
===================================================================
RCS file: /h/cvsroot/syssrc/sys/uvm/uvm_amap.c,v
retrieving revision 1.37
diff -u -r1.37 uvm_amap.c
--- uvm_amap.c 2001/11/10 07:36:59 1.37
+++ uvm_amap.c 2001/11/16 09:25:24
@@ -291,13 +291,13 @@
{
struct vm_amap *amap = entry->aref.ar_amap;
int slotoff = entry->aref.ar_pageoff;
- int slotmapped, slotadd, slotneed;
+ int slotmapped, slotadd, slotneed, slotadded, slotalloc;
#ifdef UVM_AMAP_PPREF
int *newppref, *oldppref;
#endif
int *newsl, *newbck, *oldsl, *oldbck;
struct vm_anon **newover, **oldover;
- int slotadded;
+ size_t size;
UVMHIST_FUNC("amap_extend"); UVMHIST_CALLED(maphist);
UVMHIST_LOG(maphist, " (entry=0x%x, addsize=0x%x)", entry,addsize,0,0);
@@ -366,10 +366,16 @@
*/
amap_unlock(amap); /* unlock in case we sleep in malloc */
+ size = slotneed * sizeof(int);
+ if (size <= MAXALLOCSAVE)
+ slotalloc = (1 << BUCKETINDX(size)) / sizeof(int);
+ else
+ slotalloc = roundup(size, PAGE_SIZE) / sizeof(int);
#ifdef UVM_AMAP_PPREF
newppref = NULL;
if (amap->am_ppref && amap->am_ppref != PPREF_NONE) {
- newppref = malloc(slotneed * sizeof(int), M_UVMAMAP, M_NOWAIT);
+ newppref = malloc(slotalloc * sizeof(int), M_UVMAMAP,
+ M_NOWAIT);
if (newppref == NULL) {
/* give up if malloc fails */
free(amap->am_ppref, M_UVMAMAP);
@@ -377,9 +383,9 @@
}
}
#endif
- newsl = malloc(slotneed * sizeof(int), M_UVMAMAP, M_WAITOK);
- newbck = malloc(slotneed * sizeof(int), M_UVMAMAP, M_WAITOK);
- newover = malloc(slotneed * sizeof(struct vm_anon *),
+ newsl = malloc(slotalloc * sizeof(int), M_UVMAMAP, M_WAITOK);
+ newbck = malloc(slotalloc * sizeof(int), M_UVMAMAP, M_WAITOK);
+ newover = malloc(slotalloc * sizeof(struct vm_anon *),
M_UVMAMAP, M_WAITOK);
amap_lock(amap); /* re-lock! */
KASSERT(amap->am_maxslot < slotneed);
@@ -388,7 +394,7 @@
* now copy everything over to new malloc'd areas...
*/
- slotadded = slotneed - amap->am_nslot;
+ slotadded = slotalloc - amap->am_nslot;
/* do am_slots */
oldsl = amap->am_slots;
@@ -417,13 +423,14 @@
if ((slotoff + slotmapped) < amap->am_nslot)
amap_pp_adjref(amap, slotoff + slotmapped,
(amap->am_nslot - (slotoff + slotmapped)), 1);
- pp_setreflen(newppref, amap->am_nslot, 1, slotadded);
+ pp_setreflen(newppref, amap->am_nslot, 1,
+ slotneed - amap->am_nslot);
}
#endif
/* update master values */
amap->am_nslot = slotneed;
- amap->am_maxslot = slotneed;
+ amap->am_maxslot = slotalloc;
amap_unlock(amap);
free(oldsl, M_UVMAMAP);