Safer push_back and faster push_back (I went from 0(n^2) to 0(1))
This commit is contained in:
@@ -0,0 +1,187 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <pthread.h>
|
||||
|
||||
typedef struct {
|
||||
char* arr;
|
||||
size_t size;
|
||||
size_t capacity;
|
||||
} Vec8_t;
|
||||
|
||||
Vec8_t create(Vec8_t* input) {
|
||||
Vec8_t vec = { .arr = nullptr, .size = 0, .capacity = 4 };
|
||||
if(input == nullptr) {
|
||||
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 != nullptr) free(vec->arr);
|
||||
vec->arr = nullptr;
|
||||
}
|
||||
|
||||
char at(Vec8_t* vec, int idx) {
|
||||
if (vec == nullptr) return -2;
|
||||
if (vec->arr == nullptr) return -3;
|
||||
if (vec->size <= idx) return -4;
|
||||
if (vec != nullptr && vec->arr != nullptr && vec->size > idx) {
|
||||
return vec->arr[idx];
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int begin(Vec8_t* vec) {
|
||||
if (vec != nullptr && vec->arr != nullptr && vec->size > 0) return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int end(Vec8_t* vec) {
|
||||
if (vec != nullptr && vec->arr != nullptr && vec->size > 0) return (int)(vec->size - 1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
char front(Vec8_t* vec) {
|
||||
return at(vec, 0);
|
||||
}
|
||||
|
||||
char back(Vec8_t* vec) {
|
||||
if (vec) return at(vec, (int)vec->size - 1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
Vec8_t add_back(Vec8_t* vec, char val) {
|
||||
Vec8_t ret = { .arr = nullptr, .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);
|
||||
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;
|
||||
}
|
||||
|
||||
int main() {
|
||||
struct timespec start, end_t;
|
||||
Vec8_t vec;
|
||||
|
||||
printf("=== CPU Stress Tests ===\n\n");
|
||||
|
||||
// Test 1: Rapid fire inserts (tight loop)
|
||||
printf("--- Test 1: Rapid Fire (100M tight loop) ---\n");
|
||||
vec = create(nullptr);
|
||||
clock_gettime(CLOCK_MONOTONIC, &start);
|
||||
for (int i = 0; i < 100000000; i++) {
|
||||
vec = add_back(&vec, (char)i);
|
||||
}
|
||||
clock_gettime(CLOCK_MONOTONIC, &end_t);
|
||||
double t1 = time_diff(start, end_t);
|
||||
printf(" Time: %.3f sec\n", t1);
|
||||
printf(" Rate: %.0f/sec\n", 100000000.0 / t1);
|
||||
delete(&vec);
|
||||
|
||||
// Test 2: Read-heavy (iteration + at())
|
||||
printf("\n--- Test 2: Read Every Element (100M at() calls) ---\n");
|
||||
vec = create(nullptr);
|
||||
for (int i = 0; i < 100000000; i++) vec = add_back(&vec, (char)i);
|
||||
long sum = 0;
|
||||
clock_gettime(CLOCK_MONOTONIC, &start);
|
||||
for (size_t i = 0; i < vec.size; i++) {
|
||||
sum += at(&vec, (int)i);
|
||||
}
|
||||
clock_gettime(CLOCK_MONOTONIC, &end_t);
|
||||
double t2 = time_diff(start, end_t);
|
||||
printf(" Time: %.3f sec\n", t2);
|
||||
printf(" Sum: %ld\n", sum);
|
||||
printf(" Rate: %.0f reads/sec\n", 100000000.0 / t2);
|
||||
delete(&vec);
|
||||
|
||||
// Test 3: Mixed operations
|
||||
printf("\n--- Test 3: Mixed Operations (50M each) ---\n");
|
||||
vec = create(nullptr);
|
||||
clock_gettime(CLOCK_MONOTONIC, &start);
|
||||
for (int i = 0; i < 50000000; i++) {
|
||||
vec = add_back(&vec, (char)i);
|
||||
char f = front(&vec);
|
||||
char b = back(&vec);
|
||||
at(&vec, i / 2);
|
||||
}
|
||||
clock_gettime(CLOCK_MONOTONIC, &end_t);
|
||||
double t3 = time_diff(start, end_t);
|
||||
printf(" Time: %.3f sec\n", t3);
|
||||
printf(" Rate: %.0f ops/sec\n", 50000000.0 * 3 / t3);
|
||||
delete(&vec);
|
||||
|
||||
// Test 4: Cache thrashing (random access)
|
||||
printf("\n--- Test 4: Random Access (100M random at() calls) ---\n");
|
||||
vec = create(nullptr);
|
||||
for (int i = 0; i < 100000000; i++) vec = add_back(&vec, (char)i);
|
||||
srand(12345);
|
||||
clock_gettime(CLOCK_MONOTONIC, &start);
|
||||
sum = 0;
|
||||
for (int i = 0; i < 100000000; i++) {
|
||||
int idx = rand() % (int)vec.size;
|
||||
sum += at(&vec, idx);
|
||||
}
|
||||
clock_gettime(CLOCK_MONOTONIC, &end_t);
|
||||
double t4 = time_diff(start, end_t);
|
||||
printf(" Time: %.3f sec\n", t4);
|
||||
printf(" Sum: %ld\n", sum);
|
||||
printf(" Rate: %.0f random reads/sec\n", 100000000.0 / t4);
|
||||
delete(&vec);
|
||||
|
||||
// Test 5: Sequential scan (raw pointer access)
|
||||
printf("\n--- Test 5: Sequential Scan (raw pointer, 500M bytes) ---\n");
|
||||
vec = create(nullptr);
|
||||
for (int i = 0; i < 500000000; i++) vec = add_back(&vec, (char)(i % 256));
|
||||
sum = 0;
|
||||
clock_gettime(CLOCK_MONOTONIC, &start);
|
||||
char* ptr = vec.arr;
|
||||
for (size_t i = 0; i < vec.size; i++) {
|
||||
sum += ptr[i];
|
||||
}
|
||||
clock_gettime(CLOCK_MONOTONIC, &end_t);
|
||||
double t5 = time_diff(start, end_t);
|
||||
printf(" Time: %.3f sec\n", t5);
|
||||
printf(" Throughput: %.1f GB/sec\n", (vec.size / 1e9) / t5);
|
||||
printf(" Sum: %ld\n", sum);
|
||||
delete(&vec);
|
||||
|
||||
// Test 6: Create/delete cycles (memory allocation stress)
|
||||
printf("\n--- Test 6: Create/Delete Cycles (1M vectors) ---\n");
|
||||
clock_gettime(CLOCK_MONOTONIC, &start);
|
||||
for (int i = 0; i < 1000000; i++) {
|
||||
vec = create(nullptr);
|
||||
for (int j = 0; j < 100; j++) vec = add_back(&vec, (char)j);
|
||||
delete(&vec);
|
||||
}
|
||||
clock_gettime(CLOCK_MONOTONIC, &end_t);
|
||||
double t6 = time_diff(start, end_t);
|
||||
printf(" Time: %.3f sec\n", t6);
|
||||
printf(" Rate: %.0f create/delete cycles/sec\n", 1000000.0 / t6);
|
||||
|
||||
printf("\n=== CPU Stress Complete ===\n");
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user