Re: What features should a systems programming language have
Posted: Wed Jan 29, 2014 4:17 pm
Conditional branching and loop structures...
The Place to Start for Operating System Developers
https://f.osdev.org/
Its not a fair test if the version which uses malloc() never frees - what you test is how efficiently malloc can grow its' heapbwat wrote:The bigger the heap the less often the scan. My GC alloc routine including collection was faster than Linux malloc. My alloc routine in my Scheme runtime isOwen wrote: However, how fast is garbage collection? It requires scanning a sizable portion of the heap. The amortized cost of (allocate + collect) is probably more than the equivalent (malloc + free), especially as in non-GC languages stack object references are often passed around which in GC languages must be on the heapTimes for auto-compilation of the cold compiler with GC (#undef GARBAGE_COLLECTION_TEST)Code: Select all
void * GC_alloc (unsigned int size) { void * addr; #ifdef GARBAGE_COLLECTION_TEST addr = malloc(size); #else if(GC_free + size >= GC_tospace + GC_space_size) { GC_flip(); if(GC_free + size >= GC_tospace + GC_space_size) { fprintf(stderr, "Out of memory! - tried to allocate %u bytes\n", size); GC_dump(); exit(EXIT_FAILURE); } } addr = (void *)GC_free; GC_free += size; #endif return addr; }
real 0m2.810s
user 0m2.736s
sys 0m0.044s
Times for auto-compilation of the cold compiler with malloc (#define GARBAGE_COLLECTION_TEST)
real 0m5.313s
user 0m4.828s
sys 0m0.444s
With GC, the heap was flipped (call of GC_flip which is the mark, scan and copy routine) 15 times. Heap size is 10000000 bytes which is roughly 9.5 megs (1 meg is 1024*1024 bytes for me).
Yep, predictable or precise timing would need some work and easily be not worth it, I agree. I've seen real-time Lisp processes not generate garbage to avoid collection, and systems where each interrupt service routine had its own GC'd heap.Owen wrote: That depends upon your system, but: if collection ever takes >1ms, that's probably too much for precise timing (quite possibly significantly too much, looking more towards ~200μS) dependent apps. What this means is your allocator must be per-emptible, which means that, for example, your scheduler can't use it*. This places constraints on use of a number of features of garbage collected languages
I've tried various ways to minimise the processing required when growing the heap (trying to preallocate) but it hasn't made any difference to the timings. The only real way to test this is putting my GC in a C application and comparing it to manual management. If I ever get round to it I'll report the timings.Owen wrote:Its not a fair test if the version which uses malloc() never frees - what you test is how efficiently malloc can grow its' heap
Code: Select all
void fopen(string filename, function failureHandler, function successHandler);
void fwrite(handle filehandle, byte[] data, function failureHandler, function successHandler);
void fclose(handle filehandle, function failureHandler, function successHandler);
void showDialog(string message);
// Write a file:
void writeFile(string filename, byte[] data) {
function failure = function() {
showDialog("unable to write to save to " + filename);
};
fopen(filename, failure, function(handle) {
// file is opened
fwrite(handle, data, failure, function() {
// data was written to the file
fclose(handle, failure, function() {
showDialog(filename + " saved!");
});
});
});
}
Code: Select all
void writeFunction(string filename, byte[] data);
// var args are the buttons in the format of string (button name), function (handler)
void yesNoDialog(string message, ...);
void askUserToSaveFile(string filename, byte[] data) {
// ask the user if they wish to save the file
yesNoDialog("Do you wish to save " + filename + "?",
"Yes", function() { // yes button
writeFunction(filename, data);
},
"No", function() {}, // no button
null); // no more buttons
};