Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

memory: user-space #13

Open
wants to merge 8 commits into
base: Matvii.Zorin
Choose a base branch
from
Open
22 changes: 22 additions & 0 deletions memory/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Memory management

## Homework
1. Create user-space C or C++ program which tries to allocate buffers
with sizes 2^x for x in range from 0 to maximium possible value
using functions:
**malloc, calloc, alloca, (optional for C++) new **.
Measure time of each allocation/freeing.
2^x means x power of 2 in this task.
Pull request should contains program source code and program output
in text format.

2. Create kernel module and test allocation/freeing time for functions:
**kmalloc, kzmalloc, vmalloc, get_free_pages,
(optional and only for drivers integrated to kernel)alloc_bootmem**.
Measure the time of each allocation/freeing except alloc_bootmem.
The results should be presented in text file table with followed columns:
Buffer size, allocation time, freeing time.
Size unit is 1 byte, time unit is 1 ns.

Pull request should contains source code of developed driver, Makefile
and program output from system log in text format.
103 changes: 103 additions & 0 deletions memory/log.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@

*--------------------------*malloc()*--------------------------*
Power Buffer size (bytes) Allocation (ns) Freeing (ns)
0 1 562 188
1 2 126 142
2 4 87 92
3 8 62 66
4 16 114 80
5 32 201 100
6 64 180 100
7 128 216 99
8 256 161 82
9 512 182 94
10 1024 257 98
11 2048 3071 427
12 4096 202 144
13 8192 2991 118
14 16384 2922 130
15 32768 2956 127
16 65536 3157 115
17 131072 7894 11804
18 262144 6035 5208
19 524288 4953 4626
20 1048576 4590 4788
21 2097152 7491 7109
22 4194304 7855 6362
23 8388608 6855 6457
24 16777216 7230 4132
25 33554432 4343 3841
26 67108864 4183 4081
27 134217728 4370 4466
28 268435456 4272 5380
29 536870912 6116 11445
30 1073741824 7452 17836
31 2147483648 8581 18082
32 4294967296 7534 17259

MEAN 3551 4093

*--------------------------*calloc()*--------------------------*
Power Buffer size (bytes) Allocation (ns) Freeing (ns)
0 1 473 163
1 2 200 115
2 4 164 105
3 8 122 80
4 16 170 78
5 32 172 87
6 64 200 100
7 128 385 70
8 256 248 82
9 512 317 102
10 1024 381 96
11 2048 343 341
12 4096 785 112
13 8192 4993 152
14 16384 3966 112
15 32768 11941 136
16 65536 26086 204
17 131072 69981 187
18 262144 150670 423
19 524288 53354 1525
20 1048576 866863 2804
21 2097152 899034 483
22 4194304 1189385 1004
23 8388608 2389343 839
24 16777216 5158120 1421
25 33554432 26193 17083
26 67108864 10045 9273
Copy link
Contributor

@yekovalyov yekovalyov Feb 13, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can You explain why allocation of 2^25 bytes faster than allocation of 2^24 bytes?

Copy link
Author

@matthewzorin matthewzorin Feb 13, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think maybe in linux calloc function uses simple allocation and memset in cases, where we need lesser than the certain amount of bytes. So, in another cases it switches to the more efficient way for getting zero-initialized memory. For example - zeroed pages (2^24 bytes - 4096 pages, 1 page - 4096 bytes), but this method needs more time than I measured. I'd glad to receive Your opinion about this result

27 134217728 8189 10461
28 268435456 8123 9737
29 536870912 7246 12217
30 1073741824 9096 20275
31 2147483648 9524 19847
32 4294967296 8271 19839

MEAN 330738 3925

*--------------------------*alloca()*--------------------------*
Power Buffer size (bytes) Allocation (ns)
0 1 108
1 2 115
2 4 92
3 8 80
4 16 103
5 32 85
6 64 90
7 128 96
8 256 98
9 512 95
10 1024 80
11 2048 95
12 4096 4182
13 8192 3719
14 16384 3736
15 32768 3407
16 65536 5579
17 131072 4074
18 262144 4447
19 524288 5853
20 1048576 4167
21 2097152 5172

MEAN 2066
140 changes: 140 additions & 0 deletions memory/uapi_memory.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <pthread.h>

#define ALLOC_COEF .9F //For controling the stack memory allocation

long get_interval(struct timespec *ts1, struct timespec *ts2)
{
return 1000000000 * (ts2->tv_sec - ts1->tv_sec) +
(ts2->tv_nsec - ts1->tv_nsec);
}

static inline void malloc_test(void)
{
struct timespec ts1, ts2;
void *restrict pdata = NULL;
long mean_alloc = 0;
long mean_free = 0;
long curr_alloc = 0;
long curr_free = 0;
long inter_count = 0;

printf("\n*--------------------------*malloc()*--------------------------*\n");
printf("%-8s%-25s%-20s%-20s\n", "Power", "Buffer size (bytes)", "Allocation (ns)", "Freeing (ns)");
size_t alloc_size = 1;
do {
clock_gettime(CLOCK_REALTIME, &ts1);
pdata = malloc(alloc_size);
clock_gettime(CLOCK_REALTIME, &ts2);

if (!pdata)
break;

curr_alloc = get_interval(&ts1, &ts2);
mean_alloc += curr_alloc;

clock_gettime(CLOCK_REALTIME, &ts1);
free(pdata);
clock_gettime(CLOCK_REALTIME, &ts2);

curr_free = get_interval(&ts1, &ts2);
mean_free += curr_free;

printf("%-8ld%-25lu%-20ld%-20ld\n", inter_count, alloc_size, curr_alloc, curr_free);

++inter_count;
} while(alloc_size *= 2);

mean_alloc /= inter_count;
mean_free /= inter_count;
printf("\n%-33s%-20ld%-20ld\n", "MEAN", mean_alloc, mean_free);
}

static inline void calloc_test(void)
{
struct timespec ts1, ts2;
void *restrict pdata = NULL;
long mean_alloc = 0;
long mean_free = 0;
long curr_alloc = 0;
long curr_free = 0;
long inter_count = 0;

printf("\n*--------------------------*calloc()*--------------------------*\n");
printf("%-8s%-25s%-20s%-20s\n", "Power", "Buffer size (bytes)", "Allocation (ns)", "Freeing (ns)");
size_t alloc_size = 1;
do {
clock_gettime(CLOCK_REALTIME, &ts1);
pdata = calloc(alloc_size, 1);
clock_gettime(CLOCK_REALTIME, &ts2);

if (!pdata)
break;

curr_alloc = get_interval(&ts1, &ts2);
mean_alloc += curr_alloc;

clock_gettime(CLOCK_REALTIME, &ts1);
free(pdata);
clock_gettime(CLOCK_REALTIME, &ts2);

curr_free = get_interval(&ts1, &ts2);
mean_free += curr_free;

printf("%-8ld%-25lu%-20ld%-20ld\n", inter_count, alloc_size, curr_alloc, curr_free);

++inter_count;
} while(alloc_size *= 2);

mean_alloc /= inter_count;
mean_free /= inter_count;
printf("\n%-33s%-20ld%-20ld\n", "MEAN", mean_alloc, mean_free);
}

static inline void alloca_test(void)
{
struct timespec ts1, ts2;
void *restrict pdata = NULL;
long mean_alloc = 0;
long curr_alloc = 0;
long inter_count = 0;
ssize_t stack_rem = 0;
pthread_attr_t pth_attr;

pthread_attr_init(&pth_attr);
pthread_attr_getstacksize(&pth_attr, &stack_rem);
stack_rem *= ALLOC_COEF;

printf("\n*--------------------------*alloca()*--------------------------*\n");
printf("%-8s%-25s%-20s\n", "Power", "Buffer size (bytes)", "Allocation (ns)");
size_t alloc_size = 1;
do {
stack_rem -= alloc_size;
if (stack_rem < 0)
break;

clock_gettime(CLOCK_REALTIME, &ts1);
pdata = alloca(alloc_size);
clock_gettime(CLOCK_REALTIME, &ts2);

curr_alloc = get_interval(&ts1, &ts2);
mean_alloc += curr_alloc;

printf("%-8ld%-25lu%-20ld\n", inter_count, alloc_size, curr_alloc);

++inter_count;
} while(alloc_size *= 2);

mean_alloc /= inter_count;
printf("\n%-33s%-20ld\n", "MEAN", mean_alloc);
}

int main(void)
{
malloc_test();
calloc_test();
alloca_test();
return 0;
}
19 changes: 19 additions & 0 deletions timer/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Internal Kernel API (Time Management)

## Homework

1. User space. Implement program which shows absolute time in user space.
Pull request should contain the commit with source code and
generated output in text format.

2. Kernel space.
a) Implement kernel module with API in sysfs,
which show relation time in maximum possible resolution
passed since previous read of it.
b) Implement kernel module with API in sysfs which shows absolute time of
previous reading with maximum resolution like ‘400.123567’ seconds.
c) (optional) Implement kernel module with API in sysfs which shows
average processor load updated once in a second.
Pull request should contain the commit with source code and
text output from sysfs.