Compare commits
2 commits
Author | SHA1 | Date | |
---|---|---|---|
|
c4b96af829 | ||
|
e1eb2c8413 |
13 changed files with 571 additions and 10 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -7,6 +7,7 @@ INSTALL
|
||||||
Makefile.in
|
Makefile.in
|
||||||
aclocal.m4
|
aclocal.m4
|
||||||
autom4te.cache
|
autom4te.cache
|
||||||
|
compile
|
||||||
config.guess
|
config.guess
|
||||||
config.h.in
|
config.h.in
|
||||||
config.sub
|
config.sub
|
||||||
|
@ -23,6 +24,7 @@ config.log
|
||||||
config.status
|
config.status
|
||||||
libtool
|
libtool
|
||||||
stamp-h1
|
stamp-h1
|
||||||
|
test-driver
|
||||||
umem.spec
|
umem.spec
|
||||||
umem_test
|
umem_test
|
||||||
umem_test1
|
umem_test1
|
||||||
|
|
|
@ -36,7 +36,10 @@ libumem_la_SOURCES = init_lib.c \
|
||||||
sys/vmem_impl_user.h
|
sys/vmem_impl_user.h
|
||||||
|
|
||||||
libumem_malloc_la_SOURCES = malloc.c
|
libumem_malloc_la_SOURCES = malloc.c
|
||||||
libumem_malloc_la_LDFLAGS = -lpthread -R$(libdir) -lumem
|
libumem_malloc_la_LDFLAGS = -lpthread -R$(libdir) -lumem
|
||||||
|
|
||||||
|
AM_CFLAGS = -fno-builtin-calloc
|
||||||
|
ACLOCAL_AMFLAGS = -I m4
|
||||||
|
|
||||||
man3_MANS = umem_alloc.3 umem_cache_create.3 umem_debug.3
|
man3_MANS = umem_alloc.3 umem_cache_create.3 umem_debug.3
|
||||||
EXTRA_DIST = COPYRIGHT OPENSOLARIS.LICENSE umem.spec Doxyfile umem_test4 \
|
EXTRA_DIST = COPYRIGHT OPENSOLARIS.LICENSE umem.spec Doxyfile umem_test4 \
|
||||||
|
|
2
README
2
README
|
@ -17,7 +17,7 @@ Linux and Windows versions of our product as we have found it to be stable.
|
||||||
We will continue to update this project as and when we make improvements, and
|
We will continue to update this project as and when we make improvements, and
|
||||||
welcome third-party patches that improve the usability for everyone.
|
welcome third-party patches that improve the usability for everyone.
|
||||||
|
|
||||||
|
|
||||||
Wez Furlong,
|
Wez Furlong,
|
||||||
Message Systems, Inc.
|
Message Systems, Inc.
|
||||||
wez (at) messagesystems (dot) com
|
wez (at) messagesystems (dot) com
|
||||||
|
|
16
README-alpha
16
README-alpha
|
@ -16,7 +16,7 @@ installation instructions are set forth in the file README.
|
||||||
incomplete. The subversion history is the authoritative documentation of all
|
incomplete. The subversion history is the authoritative documentation of all
|
||||||
recent changes.
|
recent changes.
|
||||||
|
|
||||||
Report bugs at https://labs.omniti.com/trac/portableumem/newticket
|
Report bugs at https://github.com/gburd/libumem/issues
|
||||||
|
|
||||||
* Checking Out the Sources
|
* Checking Out the Sources
|
||||||
|
|
||||||
|
@ -31,20 +31,30 @@ To checkout the source tree from subversion issue the following command:
|
||||||
|
|
||||||
In order to build this you will first need to have right versions
|
In order to build this you will first need to have right versions
|
||||||
of autotools and some auxiliary GNU programs. At the time of this
|
of autotools and some auxiliary GNU programs. At the time of this
|
||||||
writing these are:
|
writing these are:
|
||||||
|
|
||||||
Package Version (>=)
|
Package Version (>=)
|
||||||
======== ============
|
======== ============
|
||||||
automake 1.4
|
automake 1.4
|
||||||
autoconf 2.50
|
autoconf 2.50
|
||||||
libtool 1.5.0
|
libtool 1.5.0
|
||||||
|
|
||||||
To prepare the package for building run autogen.sh. Then run
|
To prepare the package for building run autogen.sh. Then run
|
||||||
./configure with the desired options (See INSTALL and README for the
|
./configure with the desired options (See INSTALL and README for the
|
||||||
detailed instructions). Finally, run make. Notice that the first make
|
detailed instructions). Finally, run make. Notice that the first make
|
||||||
of the package should be made in the source directory. Subsequent
|
of the package should be made in the source directory. Subsequent
|
||||||
makes can use build directory different from the source one.
|
makes can use build directory different from the source one.
|
||||||
|
|
||||||
|
* Use
|
||||||
|
|
||||||
|
To use link with both umem and umem_malloc (e.g. '-lumem -lumem_malloc').
|
||||||
|
|
||||||
|
* Testing
|
||||||
|
|
||||||
|
There are two basic test files included, test.c and hello.c, with
|
||||||
|
basic instructions within those files at the end. Basic performance
|
||||||
|
testing was done using hyperfine.
|
||||||
|
|
||||||
* Copyright information:
|
* Copyright information:
|
||||||
|
|
||||||
Please see COPYRIGHT and OPENSOLARIS.LICENSE for the copyright
|
Please see COPYRIGHT and OPENSOLARIS.LICENSE for the copyright
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
AC_INIT([umem], [1.0.2], [], [umem])
|
AC_INIT([umem], [1.0.2], [], [umem])
|
||||||
AM_INIT_AUTOMAKE([dist-bzip2])
|
AM_INIT_AUTOMAKE([dist-bzip2])
|
||||||
|
AC_CONFIG_MACRO_DIRS([m4])
|
||||||
|
|
||||||
AC_PROG_CC
|
AC_PROG_CC
|
||||||
AM_PROG_AS
|
AM_PROG_AS
|
||||||
|
@ -8,8 +9,8 @@ AC_PROG_LIBTOOL
|
||||||
AC_C_INLINE
|
AC_C_INLINE
|
||||||
|
|
||||||
AC_MSG_CHECKING([whether pthread_mutex_t is larger than 24 bytes])
|
AC_MSG_CHECKING([whether pthread_mutex_t is larger than 24 bytes])
|
||||||
AC_TRY_RUN(
|
AC_TRY_RUN(
|
||||||
[
|
[
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
int main(void){return (sizeof(pthread_mutex_t) > 24);}
|
int main(void){return (sizeof(pthread_mutex_t) > 24);}
|
||||||
],
|
],
|
||||||
|
@ -19,7 +20,7 @@ int main(void){return (sizeof(pthread_mutex_t) > 24);}
|
||||||
AC_DEFINE(UMEM_PTHREAD_MUTEX_TOO_BIG, [1], [need bigger cache])
|
AC_DEFINE(UMEM_PTHREAD_MUTEX_TOO_BIG, [1], [need bigger cache])
|
||||||
AC_MSG_WARN([*** increasing umem cpu cache size to compensate.])
|
AC_MSG_WARN([*** increasing umem cpu cache size to compensate.])
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
AC_CHECK_LIB(dl,dlopen)
|
AC_CHECK_LIB(dl,dlopen)
|
||||||
|
|
||||||
|
|
17
hello.c
Normal file
17
hello.c
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
char *ptr = (char *)malloc(4096);
|
||||||
|
snprintf(ptr, 4096, "%s", "Hello, World!");
|
||||||
|
printf("%s 0x%p\n", ptr, ptr);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local variables:
|
||||||
|
* tab-width:4
|
||||||
|
* compile-command: "gcc -fpic -Wall -Werror -Ofast -march=native -mtune=native hello.c -o hello"
|
||||||
|
* End:
|
||||||
|
*/
|
||||||
|
|
1
m4/libtool.m4
vendored
Symbolic link
1
m4/libtool.m4
vendored
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
/usr/share/aclocal/libtool.m4
|
1
m4/ltoptions.m4
vendored
Symbolic link
1
m4/ltoptions.m4
vendored
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
/usr/share/aclocal/ltoptions.m4
|
1
m4/ltsugar.m4
vendored
Symbolic link
1
m4/ltsugar.m4
vendored
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
/usr/share/aclocal/ltsugar.m4
|
1
m4/ltversion.m4
vendored
Symbolic link
1
m4/ltversion.m4
vendored
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
/usr/share/aclocal/ltversion.m4
|
1
m4/lt~obsolete.m4
vendored
Symbolic link
1
m4/lt~obsolete.m4
vendored
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
/usr/share/aclocal/lt~obsolete.m4
|
521
test.c
Normal file
521
test.c
Normal file
|
@ -0,0 +1,521 @@
|
||||||
|
/* malloc-test.c
|
||||||
|
* by Wolfram Gloger 1995, 1996
|
||||||
|
*
|
||||||
|
* This program is provided `as is', there is no warranty.
|
||||||
|
* https://raw.githubusercontent.com/emeryberger/Malloc-Implementations/master/allocators/CAMA/malloc-test.c
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(__STDC__)
|
||||||
|
#define __STDC__ 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#if !defined(_WIN32)
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/resource.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MEMORY
|
||||||
|
#define MEMORY 4000000l
|
||||||
|
#endif
|
||||||
|
#ifndef BINS_MAX
|
||||||
|
#define BINS_MAX 32768
|
||||||
|
#endif
|
||||||
|
#define SBINS_MAX 1024
|
||||||
|
#define SIZE 4024
|
||||||
|
#define I_MAX 5000
|
||||||
|
#ifndef I_AVERAGE
|
||||||
|
#define I_AVERAGE 200
|
||||||
|
#endif
|
||||||
|
#define ACTIONS_MAX 50
|
||||||
|
#ifndef SBRK_AVG
|
||||||
|
#define SBRK_AVG 0
|
||||||
|
#endif
|
||||||
|
#ifndef MMAP_THRESH
|
||||||
|
#define MMAP_THRESH 0
|
||||||
|
#endif
|
||||||
|
#ifndef TEST
|
||||||
|
#define TEST 4 /* minimal testing */
|
||||||
|
#endif
|
||||||
|
#ifndef TEST_INC
|
||||||
|
#define TEST_INC 2047
|
||||||
|
#endif
|
||||||
|
#if defined(__i386__) || defined(__sparc__) || defined(mips) || defined(_WIN32)
|
||||||
|
#define PAGE_SIZE 4096
|
||||||
|
#elif defined(__alpha__)
|
||||||
|
#define PAGE_SIZE 8192
|
||||||
|
#elif defined(__SVR4)
|
||||||
|
#define PAGE_SIZE 8192
|
||||||
|
#else
|
||||||
|
#define PAGE_SIZE 4096 /* default */
|
||||||
|
#endif
|
||||||
|
#define RANDOM(s) (lran2(0) % (s))
|
||||||
|
|
||||||
|
/* All probabilities are parts in 1024. */
|
||||||
|
#ifndef PROB_MEMALIGN
|
||||||
|
#define PROB_MEMALIGN 0
|
||||||
|
#endif
|
||||||
|
#ifndef PROB_REALLOC
|
||||||
|
#define PROB_REALLOC 48
|
||||||
|
#endif
|
||||||
|
#ifndef PROB_CALLOC
|
||||||
|
#define PROB_CALLOC 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct bin {
|
||||||
|
unsigned char *ptr;
|
||||||
|
unsigned long size;
|
||||||
|
} m[BINS_MAX], sm[SBINS_MAX];
|
||||||
|
|
||||||
|
unsigned long size = SIZE, bins=0, sbins=0;
|
||||||
|
unsigned long total_size=0, total_size_max=0;
|
||||||
|
unsigned char *base_ptr;
|
||||||
|
unsigned long base_save;
|
||||||
|
|
||||||
|
long
|
||||||
|
#if __STDC__
|
||||||
|
lran2(long seed)
|
||||||
|
#else
|
||||||
|
lran2(seed) long seed;
|
||||||
|
#endif
|
||||||
|
#define LRAN2_MAX 714025l /* constants for portable */
|
||||||
|
#define IA 1366l /* random number generator */
|
||||||
|
#define IC 150889l /* (see Numerical Recipes p. 211) */
|
||||||
|
{
|
||||||
|
static int first = 1;
|
||||||
|
static long x, y, v[97];
|
||||||
|
int j;
|
||||||
|
|
||||||
|
if(seed || first) {
|
||||||
|
first = 0;
|
||||||
|
x = (IC - seed) % LRAN2_MAX;
|
||||||
|
if(x < 0) x = -x;
|
||||||
|
for(j=0; j<97; j++) {
|
||||||
|
x = (IA*x + IC) % LRAN2_MAX;
|
||||||
|
v[j] = x;
|
||||||
|
}
|
||||||
|
x = (IA*x + IC) % LRAN2_MAX;
|
||||||
|
y = x;
|
||||||
|
}
|
||||||
|
j = y % 97;
|
||||||
|
y = v[j];
|
||||||
|
x = (IA*x + IC) % LRAN2_MAX;
|
||||||
|
v[j] = x;
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
#undef IA
|
||||||
|
#undef IC
|
||||||
|
|
||||||
|
void
|
||||||
|
#if __STDC__
|
||||||
|
mem_init(unsigned char *ptr, unsigned long size)
|
||||||
|
#else
|
||||||
|
mem_init(ptr, size) unsigned char *ptr; unsigned long size;
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
unsigned long i, j;
|
||||||
|
|
||||||
|
if(size == 0) return;
|
||||||
|
if(size > sizeof(unsigned long)) {
|
||||||
|
/* Try the complete initial word. */
|
||||||
|
*(unsigned long *)ptr = (unsigned long)ptr ^ size;
|
||||||
|
i = TEST_INC;
|
||||||
|
} else
|
||||||
|
i = 0;
|
||||||
|
for(; i<size; i+=TEST_INC) {
|
||||||
|
j = (unsigned long)ptr ^ i;
|
||||||
|
ptr[i] = ((j ^ (j>>8)) & 0xFF);
|
||||||
|
}
|
||||||
|
j = (unsigned long)ptr ^ (size-1);
|
||||||
|
ptr[size-1] = ((j ^ (j>>8)) & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
#if __STDC__
|
||||||
|
mem_check(unsigned char *ptr, unsigned long size)
|
||||||
|
#else
|
||||||
|
mem_check(ptr, size) unsigned char *ptr; unsigned long size;
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
unsigned long i, j;
|
||||||
|
|
||||||
|
if(size == 0) return 0;
|
||||||
|
if(size > sizeof(unsigned long)) {
|
||||||
|
if(*(unsigned long *)ptr != ((unsigned long)ptr ^ size)) {
|
||||||
|
printf ("failed size check: expected %lx, found %lx!\n",
|
||||||
|
((unsigned long) ptr ^ size), *(unsigned long *) ptr);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
i = TEST_INC;
|
||||||
|
} else
|
||||||
|
i = 0;
|
||||||
|
for(; i<size; i+=TEST_INC) {
|
||||||
|
j = (unsigned long)ptr ^ i;
|
||||||
|
if(ptr[i] != ((j ^ (j>>8)) & 0xFF)) return 2;
|
||||||
|
}
|
||||||
|
j = (unsigned long)ptr ^ (size-1);
|
||||||
|
if(ptr[size-1] != ((j ^ (j>>8)) & 0xFF)) {
|
||||||
|
printf ("failed last byte check: expected %lx, found %x!\n",
|
||||||
|
((unsigned long) ((j ^ (j>>8)) & 0xFF)), ptr[size-1]);
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
long
|
||||||
|
#if __STDC__
|
||||||
|
random_size(long max)
|
||||||
|
#else
|
||||||
|
random_size(max) long max;
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
long r1, r2, r, max_pages;
|
||||||
|
|
||||||
|
max_pages = max/PAGE_SIZE;
|
||||||
|
if(max_pages > 0) {
|
||||||
|
r1 = RANDOM(1024);
|
||||||
|
r2 = (r1 & 7)*4;
|
||||||
|
if(r1 < 512) {
|
||||||
|
/* small value near power of two */
|
||||||
|
r = (1L << (r1 >> 6)) + r2;
|
||||||
|
} else if(r1 < 512+20) {
|
||||||
|
/* value near a multiple of the page size */
|
||||||
|
r = (RANDOM(max_pages)+1)*PAGE_SIZE + r2 - 16;
|
||||||
|
/*printf("r = %4lx\n", r);*/
|
||||||
|
} else r = RANDOM(max) + 1;
|
||||||
|
} else r = RANDOM(max) + 1;
|
||||||
|
/*if(r <= 0) exit(-1);*/
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
#if __STDC__
|
||||||
|
bin_alloc(struct bin *m)
|
||||||
|
#else
|
||||||
|
bin_alloc(m) struct bin *m;
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
long r, key;
|
||||||
|
unsigned long sz;
|
||||||
|
|
||||||
|
#if TEST > 0
|
||||||
|
if(mem_check(m->ptr, m->size)) {
|
||||||
|
printf("bin_alloc: memory corrupt at %p, size=%lu!\n", m->ptr, m->size);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
total_size -= m->size;
|
||||||
|
r = RANDOM(1024);
|
||||||
|
if(r < PROB_MEMALIGN) {
|
||||||
|
#if !defined(_WIN32)
|
||||||
|
if(m->size > 0) free(m->ptr);
|
||||||
|
m->size = random_size(size);
|
||||||
|
#if PROB_MEMALIGN
|
||||||
|
m->ptr = (unsigned char *)memalign(4 << RANDOM(8), m->size);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
} else if(r < (PROB_MEMALIGN + PROB_REALLOC)) {
|
||||||
|
if(m->size == 0) {
|
||||||
|
#ifndef __sparc__
|
||||||
|
m->ptr = NULL;
|
||||||
|
#else
|
||||||
|
/* SunOS4 does not realloc() a NULL pointer */
|
||||||
|
m->ptr = (unsigned char *)malloc(1);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#if TEST > 2
|
||||||
|
key = RANDOM(256);
|
||||||
|
sz = m->size;
|
||||||
|
for(r=0; r<sz; r++) m->ptr[r] = (r ^ key) & 0xFF;
|
||||||
|
#endif
|
||||||
|
m->size = random_size(size);
|
||||||
|
/*printf("realloc %d\n", (int)m->size);*/
|
||||||
|
m->ptr = (unsigned char *)realloc(m->ptr, m->size);
|
||||||
|
#if TEST > 2
|
||||||
|
if(m->size < sz) sz = m->size;
|
||||||
|
for(r=0; r<sz; r++)
|
||||||
|
if(m->ptr[r] != ((r ^ key) & 0xFF)) {
|
||||||
|
printf("realloc bug !\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
} else if(r < (PROB_MEMALIGN + PROB_REALLOC + PROB_CALLOC)) {
|
||||||
|
if(m->size > 0) free(m->ptr);
|
||||||
|
m->size = random_size(size);
|
||||||
|
m->ptr = (unsigned char *)calloc(m->size, 1);
|
||||||
|
#if TEST > 2
|
||||||
|
for(r=0; r<m->size; r++)
|
||||||
|
if(m->ptr[r] != '\0') {
|
||||||
|
printf("calloc bug !\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
} else { /* normal malloc call */
|
||||||
|
if(m->size > 0) free(m->ptr);
|
||||||
|
m->size = random_size(size);
|
||||||
|
m->ptr = (unsigned char *)malloc(m->size);
|
||||||
|
}
|
||||||
|
if(!m->ptr) {
|
||||||
|
printf("out of memory!\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
total_size += m->size;
|
||||||
|
if(total_size > total_size_max) total_size_max = total_size;
|
||||||
|
#if TEST > 0
|
||||||
|
mem_init(m->ptr, m->size);
|
||||||
|
#endif
|
||||||
|
if(m->ptr < base_ptr) {
|
||||||
|
#ifdef VERBOSE
|
||||||
|
printf("hmmm, allocating below brk...\n");
|
||||||
|
#endif
|
||||||
|
base_ptr = m->ptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
#if __STDC__
|
||||||
|
bin_free(struct bin *m)
|
||||||
|
#else
|
||||||
|
bin_free(m) struct bin *m;
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
if(m->size == 0) return;
|
||||||
|
#if TEST > 0
|
||||||
|
if(mem_check(m->ptr, m->size)) {
|
||||||
|
printf("bin_free: memory corrupt!\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
total_size -= m->size;
|
||||||
|
free(m->ptr);
|
||||||
|
m->size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
bin_test()
|
||||||
|
{
|
||||||
|
unsigned int b;
|
||||||
|
int v;
|
||||||
|
// printf ("bin_test.\n");
|
||||||
|
|
||||||
|
for(b=0; b<bins; b++) {
|
||||||
|
if((v = mem_check(m[b].ptr, m[b].size))) {
|
||||||
|
printf("bin_test: memory corrupt! m[%d].ptr = %hhn, m[%d].size = %ld\n",
|
||||||
|
b, m[b].ptr, b, m[b].size);
|
||||||
|
printf ("error = %d\n", v);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(b=0; b<sbins; b++) {
|
||||||
|
if(mem_check(sm[b].ptr, sm[b].size)) {
|
||||||
|
printf("bin_test: memory corrupt! sm[%d].ptr = %hhn, sm[%d].size = %ld\n",
|
||||||
|
b, sm[b].ptr, b, sm[b].size);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
print_times()
|
||||||
|
{
|
||||||
|
#if !defined(_WIN32)
|
||||||
|
struct rusage ru;
|
||||||
|
long total_sec, total_usec;
|
||||||
|
|
||||||
|
getrusage(RUSAGE_SELF, &ru);
|
||||||
|
printf(" u=%ld.%06ldsec",
|
||||||
|
(long)ru.ru_utime.tv_sec, (long)ru.ru_utime.tv_usec);
|
||||||
|
printf(" s=%ld.%06ldsec",
|
||||||
|
(long)ru.ru_stime.tv_sec, (long)ru.ru_stime.tv_usec);
|
||||||
|
total_usec = (long)ru.ru_utime.tv_usec + (long)ru.ru_stime.tv_usec;
|
||||||
|
total_sec = (long)ru.ru_utime.tv_sec + (long)ru.ru_stime.tv_sec;
|
||||||
|
if(total_usec >= 1000000) {
|
||||||
|
total_usec -= 1000000;
|
||||||
|
total_sec++;
|
||||||
|
}
|
||||||
|
printf(" t=%ld.%06ldsec", total_sec, total_usec);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
#if __STDC__
|
||||||
|
main(int argc, char *argv[])
|
||||||
|
#else
|
||||||
|
main(argc, argv) int argc; char *argv[];
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
int i, j, next_i, count, max=I_MAX, actions;
|
||||||
|
unsigned int b;
|
||||||
|
long sbrk_max, sum;
|
||||||
|
double sbrk_used_sum, total_size_sum;
|
||||||
|
|
||||||
|
if(argc > 1) max = atoi(argv[1]);
|
||||||
|
if(argc > 2) size = atoi(argv[2]);
|
||||||
|
lran2((long)max ^ size);
|
||||||
|
bins = (MEMORY/size)*4;
|
||||||
|
if(bins > BINS_MAX) bins = BINS_MAX;
|
||||||
|
#if 0 // FIX ME? Disable sbrk...
|
||||||
|
base_ptr = (unsigned char *)sbrk(0);
|
||||||
|
sum = (long)base_ptr % PAGE_SIZE;
|
||||||
|
if(sum > 0) {
|
||||||
|
if((char *)sbrk((long)PAGE_SIZE - sum) == (char *)-1) exit(1);
|
||||||
|
base_ptr += (long)PAGE_SIZE - sum;
|
||||||
|
/*printf("base_ptr = %lx\n", (long)base_ptr);*/
|
||||||
|
}
|
||||||
|
/* attempt to fill up the region below the initial brk */
|
||||||
|
void* dummy = 0;
|
||||||
|
for(i=0; i<10000; i++) {
|
||||||
|
dummy = malloc(1);
|
||||||
|
if(dummy >= (void*)base_ptr) break;
|
||||||
|
}
|
||||||
|
free(dummy);
|
||||||
|
base_save = ((unsigned long)base_ptr >> 24) << 24;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MMAP_THRESH > 0
|
||||||
|
if(!mallopt(-3, MMAP_THRESH)) printf("mallopt failed!\n");
|
||||||
|
if(!mallopt(-4, 200)) printf("mallopt failed!\n");
|
||||||
|
#endif
|
||||||
|
#ifdef VERBOSE
|
||||||
|
printf("# mmap_thresh=%d\n", MMAP_THRESH);
|
||||||
|
printf("# bins=%d max=%d size=%d\n", bins, max, size);
|
||||||
|
printf("# base=%lx\n", base_save);
|
||||||
|
#endif
|
||||||
|
for(b=0; b<bins; b++) {
|
||||||
|
if(RANDOM(2) == 0) bin_alloc(&m[b]);
|
||||||
|
else m[b].size = 0;
|
||||||
|
}
|
||||||
|
sbrk_max = 0;
|
||||||
|
sbrk_used_sum = total_size_sum = 0.0;
|
||||||
|
for(i=next_i=count=0; i<=max;) {
|
||||||
|
#if TEST > 1
|
||||||
|
bin_test();
|
||||||
|
#endif
|
||||||
|
#ifdef MSTATS
|
||||||
|
malloc_stats();
|
||||||
|
#endif
|
||||||
|
actions = RANDOM(ACTIONS_MAX);
|
||||||
|
for(j=0; j<actions; j++) {
|
||||||
|
b = RANDOM(bins);
|
||||||
|
bin_free(&m[b]);
|
||||||
|
#if TEST > 3
|
||||||
|
bin_test();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
i += actions;
|
||||||
|
#ifdef AFTER_FREE
|
||||||
|
AFTER_FREE;
|
||||||
|
#endif
|
||||||
|
#if SBRK_AVG > 0
|
||||||
|
if(sbins<SBINS_MAX && RANDOM(SBRK_AVG)==0) {
|
||||||
|
/* throw in an explicit sbrk call */
|
||||||
|
sm[sbins].size = RANDOM(10000)+1;
|
||||||
|
sm[sbins].ptr = sbrk(sm[sbins].size);
|
||||||
|
if(sbins>0 && sm[sbins].ptr==(sm[sbins-1].ptr+sm[sbins-1].size)) {
|
||||||
|
sm[sbins-1].size += sm[sbins].size;
|
||||||
|
sbins--;
|
||||||
|
}
|
||||||
|
#ifdef VERBOSE
|
||||||
|
printf("sbrk #%d %p %ld\n", sbins, sm[sbins].ptr, sm[sbins].size);
|
||||||
|
#endif
|
||||||
|
#if TEST > 0
|
||||||
|
mem_init(sm[sbins].ptr, sm[sbins].size);
|
||||||
|
#endif
|
||||||
|
sbins++;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
actions = RANDOM(ACTIONS_MAX);
|
||||||
|
for(j=0; j<actions; j++) {
|
||||||
|
b = RANDOM(bins);
|
||||||
|
bin_alloc(&m[b]);
|
||||||
|
#if TEST > 3
|
||||||
|
bin_test();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
i += actions;
|
||||||
|
if(i >= next_i) { /* gather statistics */
|
||||||
|
count++;
|
||||||
|
#if !defined(_WIN32)
|
||||||
|
sum = (long)sbrk(0);
|
||||||
|
#else
|
||||||
|
sum = 0;
|
||||||
|
#endif
|
||||||
|
if(sum > sbrk_max) sbrk_max = sum;
|
||||||
|
sbrk_used_sum += sum;
|
||||||
|
total_size_sum += (double)total_size;
|
||||||
|
#ifdef VERBOSE
|
||||||
|
printf("%8d %7lu\n", i, total_size);
|
||||||
|
#endif
|
||||||
|
next_i += I_AVERAGE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Correct sbrk values. */
|
||||||
|
sbrk_max -= (long)base_ptr;
|
||||||
|
sbrk_used_sum -= (double)count*(long)base_ptr;
|
||||||
|
#ifdef VERBOSE
|
||||||
|
printf("# initial brk: %lx\n", (long)base_ptr);
|
||||||
|
printf("# max. sbrk()'ed memory: %ld bytes\n", sbrk_max);
|
||||||
|
printf("# avg. sbrk()'ed memory: %ld bytes\n",
|
||||||
|
(long)(sbrk_used_sum/count));
|
||||||
|
printf("# current size allocated: %ld bytes\n", total_size);
|
||||||
|
printf("# maximum size allocated: %ld bytes\n", total_size_max);
|
||||||
|
printf("# average size allocated: %.1f bytes\n", total_size_sum/count);
|
||||||
|
printf("# current heap waste: %.2f%%\n",
|
||||||
|
(1.0 - (double)total_size_max/sbrk_max)*100.0);
|
||||||
|
printf("# average heap waste: %.2f%%\n",
|
||||||
|
(1.0 - (double)total_size_sum/sbrk_used_sum)*100.0);
|
||||||
|
printf("# total sbrk calls performed: %d\n", sbins);
|
||||||
|
#else
|
||||||
|
printf("size=%7ld waste=%7.3f%%", size,
|
||||||
|
/* (1.0 - (double)total_size_max/sbrk_max)*100.0, */
|
||||||
|
(1.0 - (double)total_size_sum/sbrk_used_sum)*100.0);
|
||||||
|
print_times();
|
||||||
|
printf("\n");
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* testing:
|
||||||
|
* gcc -Wall -Werror -fpic -march=native -mtune=native -Ofast test.c -o test
|
||||||
|
* gcc -Wall -Werror -fpic -march=native -mtune=native -Ofast test.c -o test -lumem -lumem_malloc
|
||||||
|
*
|
||||||
|
* https://github.com/sharkdp/hyperfine
|
||||||
|
*
|
||||||
|
|
||||||
|
$ ldd test
|
||||||
|
linux-vdso.so.1 (0x00007ffc607de000)
|
||||||
|
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fb619a4d000)
|
||||||
|
/lib64/ld-linux-x86-64.so.2 (0x00007fb619ce9000)
|
||||||
|
$ ldd test_umem
|
||||||
|
linux-vdso.so.1 (0x00007ffd1ff59000)
|
||||||
|
libumem_malloc.so.0 => /usr/local/lib/libumem_malloc.so.0 (0x00007fe885b18000)
|
||||||
|
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fe885926000)
|
||||||
|
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fe885903000)
|
||||||
|
libumem.so.0 => /usr/local/lib/libumem.so.0 (0x00007fe88585b000)
|
||||||
|
/lib64/ld-linux-x86-64.so.2 (0x00007fe885bc7000)
|
||||||
|
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fe885855000)
|
||||||
|
|
||||||
|
$ hyperfine --warmup 3 --min-runs 10 ./test
|
||||||
|
Benchmark #1: ./test
|
||||||
|
Time (mean ± σ): 82.1 ms ± 1.1 ms [User: 81.0 ms, System: 0.9 ms]
|
||||||
|
Range (min … max): 79.3 ms … 84.4 ms 35 runs
|
||||||
|
|
||||||
|
$ hyperfine --warmup 3 --min-runs 10 ./test_umem
|
||||||
|
Benchmark #1: ./test_umem
|
||||||
|
Time (mean ± σ): 85.7 ms ± 1.5 ms [User: 83.2 ms, System: 2.5 ms]
|
||||||
|
Range (min … max): 81.8 ms … 89.2 ms 34 runs
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local variables:
|
||||||
|
* tab-width:4
|
||||||
|
* compile-command: "gcc -fpic -Wall -Werror -Ofast -march=native -mtune=native test.c -o test"
|
||||||
|
* End:
|
||||||
|
*/
|
|
@ -4,10 +4,13 @@
|
||||||
|
|
||||||
#include "umem.h"
|
#include "umem.h"
|
||||||
|
|
||||||
|
#define UMEM_STANDALONE 1
|
||||||
|
#include "umem_impl.h"
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
char *foo;
|
char *foo;
|
||||||
|
|
||||||
umem_startup(NULL, 0, 0, NULL, NULL);
|
umem_startup(NULL, 0, 0, NULL, NULL);
|
||||||
|
|
||||||
foo = umem_alloc(32, UMEM_DEFAULT);
|
foo = umem_alloc(32, UMEM_DEFAULT);
|
||||||
|
@ -20,4 +23,3 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue