Description
First off, what I'm doing is definitely a Bad Idea (TM), but let's leave that aside for the moment! 😄
I've been having fun combining blocks and structs to create "objects". It works just fine... except for performance.
From https://github.com/williamcotton/express-c/tree/master/research/blocks
/* Baseline */
int main() {
printf("string baseline!\n");
for (int i = 0; i < LOOPS; i++) {
char *test = "test";
size_t len = strlen(test);
char *new_str = malloc(len + 1);
for (size_t i = 0; i < len; i++) {
new_str[len - i - 1] = test[i];
}
new_str[len] = '\0';
free(new_str);
}
}
/* Bad Idea (TM) "objects" */
int main() {
printf("string block!\n");
for (int i = 0; i < LOOPS; i++) {
string_t *test = string("test");
test->reverse();
test->free();
}
}
The latter, which uses the string "object" below, is about 25 times slower than the former, which is to be expected considering all of the extra memory allocations.
Is there a way to reduce the number of memory allocations by implementing a version of Block_copy designed for the circus act you see below? That is, could the scope that each block closes over be copied just once instead of for each "method"?
From https://github.com/williamcotton/express-c/blob/master/src/string/string.c#L202
string_t *string(const char *strng) {
string_t *s = malloc(sizeof(string_t));
s->value = strdup(strng);
s->size = strlen(s->value);
s->blockCopyCount = 0;
s->blockCopy = Block_copy(^(void *block) {
void *ptr = Block_copy(block);
s->blockCopies[s->blockCopyCount++] = (malloc_t){.ptr = ptr};
return ptr;
});
s->print = s->blockCopy(^(void) {
printf("%s\n", s->value);
});
s->concat = s->blockCopy(^(const char *str) {
size_t size = s->size + strlen(str);
char *new_str = malloc(size + 1);
strlcpy(new_str, s->value, size + 1);
strlcat(new_str, str, size + 1);
free(s->value);
s->value = new_str;
s->size = size;
return s;
});
...
}