a much more simplified version of push_back with reallocf instead of memcpy as it is faster (no copying just resizing the vector (entire point of vector))

This commit is contained in:
Andrew Haynes
2026-04-17 14:15:24 -04:00
parent c05e92dec0
commit b77f260a2c
9 changed files with 601 additions and 24 deletions
+181
View File
@@ -0,0 +1,181 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/resource.h>
typedef struct {
char* arr;
size_t size;
size_t capacity;
} Vec8_t;
Vec8_t create(const Vec8_t* input) {
Vec8_t vec = { .arr = NULL, .size = 0, .capacity = 4 };
if (input == NULL) {
vec.arr = calloc(vec.capacity, sizeof(char));
return vec;
}
if (input->size > 0) {
vec.size = input->size + 1;
}
if (input->capacity >= vec.capacity) {
vec.capacity = 2 * input->capacity;
}
vec.arr = calloc(vec.capacity, sizeof(char));
return vec;
}
void delete(Vec8_t* vec) {
if (vec->arr != NULL) {
free(vec->arr);
}
vec->arr = NULL;
}
Vec8_t add_back(Vec8_t* vec, const char val) {
Vec8_t ret = { .arr = NULL, .capacity = 0, .size = 0 };
if (vec->size < vec->capacity) {
vec->arr[vec->size] = val;
vec->size++;
return *vec;
}
if (vec->size >= vec->capacity) {
Vec8_t nvec = create(vec);
if (nvec.arr == NULL) {
return *vec;
}
memcpy(&nvec.arr[0], &vec->arr[0], vec->size * sizeof(char));
if (nvec.arr && (nvec.size > 0 || nvec.size > vec->size)) {
nvec.arr[vec->size] = val;
}
free(vec->arr);
return nvec;
}
return ret;
}
double time_diff(struct timespec start, struct timespec end_t) {
return (end_t.tv_sec - start.tv_sec) + (end_t.tv_nsec - start.tv_nsec) / 1e9;
}
void get_memory_usage(size_t* used, size_t* peak) {
struct rusage ru;
getrusage(RUSAGE_SELF, &ru);
*used = ru.ru_maxrss * 1024;
*peak = ru.ru_maxrss * 1024;
}
int main() {
printf("=== FULL STRESS TEST: add_back only ===\n\n");
struct timespec start, end_t;
Vec8_t vec;
size_t max_elements = 0;
int crashed = 0;
printf("=== TEST 1: MAX ELEMENTS BEFORE CRASH ===\n\n");
vec = create(NULL);
clock_gettime(CLOCK_MONOTONIC, &start);
for (size_t i = 0; i < SIZE_MAX; i++) {
vec = add_back(&vec, (char)(i % 256));
if (vec.arr == NULL) {
max_elements = i;
crashed = 1;
break;
}
if (i % 100000000 == 0) {
printf(" %zu elements: capacity %zu (%.2f GB)\n",
i + 1, vec.capacity, (double)(vec.capacity * sizeof(char)) / 1024 / 1024 / 1024);
}
if (i >= 1000000000) {
printf(" stopping at 1 billion elements\n");
max_elements = 1000000000;
break;
}
}
clock_gettime(CLOCK_MONOTONIC, &end_t);
if (!crashed && vec.arr != NULL) {
max_elements = vec.size;
}
printf("\nRESULT: %zu elements\n", max_elements);
printf("capacity: %zu\n", vec.capacity);
printf("memory: %.2f GB\n", (double)(vec.capacity * sizeof(char)) / 1024 / 1024 / 1024);
printf("time: %.2f sec\n", time_diff(start, end_t));
delete(&vec);
printf("\n=== TEST 2: DIRECT MALLOCATION LIMIT ===\n\n");
const size_t test_sizes[] = {1000000, 10000000, 100000000, 500000000, 1000000000};
int num_tests = 5;
for (int t = 0; t < num_tests; t++) {
size_t n = test_sizes[t];
printf("Testing %zu elements (%.2f GB)...\n",
n, (double)(n * sizeof(char)) / 1024 / 1024 / 1024);
char* test_arr = calloc(n, sizeof(char));
if (test_arr == NULL) {
printf(" FAILED at %zu\n", n);
break;
}
printf(" SUCCESS\n");
free(test_arr);
}
printf("\n=== TEST 3: SINGLE VECTOR ALLOCATION ===\n\n");
size_t single_max = 0;
for (size_t n = 1000000; n <= 5000000000UL; n *= 2) {
printf("Trying %.2f GB allocation...\n", (double)(n * sizeof(char)) / 1024 / 1024 / 1024);
Vec8_t test_vec = create(NULL);
Vec8_t* vp = calloc(1, sizeof(Vec8_t));
vp->arr = calloc(n, sizeof(char));
if (vp->arr == NULL) {
printf(" FAILED at %.2f GB\n", (double)(n * sizeof(char)) / 1024 / 1024 / 1024);
single_max = n / 2;
free(vp);
break;
}
printf(" SUCCESS: %.2f GB\n", (double)(n * sizeof(char)) / 1024 / 1024 / 1024);
free(vp->arr);
free(vp);
delete(&test_vec);
single_max = n;
}
printf("\n=== TEST 4: SPEED AT SCALE ===\n\n");
vec = create(NULL);
clock_gettime(CLOCK_MONOTONIC, &start);
for (size_t i = 0; i < 10000000; i++) {
vec = add_back(&vec, (char)(i % 256));
}
clock_gettime(CLOCK_MONOTONIC, &end_t);
double t10m = time_diff(start, end_t);
printf("10M elements:\n");
printf(" time: %.2f sec\n", t10m);
printf(" rate: %.0f/sec\n", 10000000.0 / t10m);
printf(" memory: %.2f MB\n", (vec.capacity * sizeof(char)) / 1024.0 / 1024.0);
delete(&vec);
printf("\n=== SUMMARY ===\n\n");
printf("Max elements (vector): %zu\n", max_elements);
printf("Single allocation max: %zu (%.2f GB)\n",
single_max, (double)(single_max * sizeof(char)) / 1024 / 1024 / 1024);
return 0;
}