I searched and found this question to help me make an application to animate numerous iterations of fractal functions across multiple arrays of complex values.
Thank you, Alexey Frunze, for your ideone.c code. It has certainly been helpful.
Building upon what I learned, in hopes of more helpfulness, I have written the following:
/* File: count-free-blocks.c
*
* Revision: 2018-24-12
*
* Copyright (C) Randall Sawyer
* <https://stackoverflow.com/users/341214/randall-sawyer>
*/
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
size_t available_blocks (size_t block_sz);
size_t largest_n_blocks (size_t block_sz);
size_t try_alloc (size_t n_blocks,
size_t block_sz);
void report (int indent,
const char *format,
...);
int main (int argc, const char **argv)
{
size_t n_blocks,
block_sz = 0;
if (argc > 1 && sscanf (argv[1], "%zu", &block_sz) != 1)
report (0, "Argument `%s' is not a valid block size.", argv[1]);
if (block_sz == 0)
{
report (0, "Using 1 byte block size...");
block_sz = 1;
}
n_blocks = available_blocks (block_sz);
report (0, "Available memory: %zu blocks of %zu bytes == %zu bytes",
n_blocks, block_sz, n_blocks * block_sz);
return 0;
}
size_t
available_blocks (size_t block_sz)
{
size_t n_blocks[2];
report (0, "calculating free memory...");
/* Calculate maximum number of blocks of given size which can be
* repeatedly allocated.
*/
do {
for ( n_blocks[0] = largest_n_blocks (block_sz);
(n_blocks[1] = largest_n_blocks (block_sz)) < n_blocks[0];
n_blocks[0] = n_blocks[1] );
report (1, "check once more...");
} while (try_alloc (n_blocks[0], block_sz) != n_blocks[0]);
return n_blocks[0];
}
size_t
largest_n_blocks (size_t block_sz)
{
static
const char *f = "phase %d";
size_t n_blocks, max, bit;
report (1, "calculating largest number of free blocks...");
/* Phase 1:
*
* Find greatest allocatable number-of-blocks such that
* it has only one bit set at '1' and '0' for the rest.
*/
report (2, f, 1);
n_blocks = ~(UINTPTR_MAX >> 1); // only MSB is set
max = UINTPTR_MAX / block_sz; // maximimum number of blocks
while (n_blocks && !(n_blocks & max))
n_blocks >>= 1;
while (try_alloc (n_blocks, block_sz) != n_blocks)
n_blocks >>= 1;
/* Phase 2:
*
* Starting with first allocatable number-of-blocks, add decreasingly
* significant bits to this value for each successful allocation.
*/
report (2, f, 2);
for ( bit = n_blocks >> 1; bit; bit >>= 1)
{
size_t n = n_blocks | bit;
if (try_alloc (n, block_sz) == n)
n_blocks = n;
}
/* Phase 3:
* For as long as allocation cannot be repeated,
* decrease number of blocks.
*/
report (2, f, 3);
while (try_alloc (n_blocks, block_sz) != n_blocks)
--n_blocks;
report (1, "free blocks: %zu", n_blocks);
return n_blocks;
}
size_t
try_alloc (size_t n_blocks,
size_t block_sz)
{
if (n_blocks != 0)
{
/* Try to allocate all of the requested blocks.
* If successful, return number of requested blocks;
* otherwise, return 0.
*/
void *p = calloc (n_blocks, block_sz);
report (3, "try %zu blocks of %zu bytes: %s",
n_blocks, block_sz, p ? "success" : "failure");
if (p)
{
free (p);
return n_blocks;
}
}
return 0;
}
#define MAX_INDENT 8
#define INDENT_SPACES " "
void
report (int indent,
const char *format,
...)
{
const char padding[MAX_INDENT+1] = INDENT_SPACES;
va_list args;
if (indent > MAX_INDENT)
indent = MAX_INDENT;
if (indent > 0)
printf ("%s", &padding[8-indent]);
va_start (args, format);
vprintf (format, args);
va_end (args);
printf ("\n");
}
Usage:
count-free-blocks [BLOCK_SIZE]
Input:
> ./count-free-blocks 33554432
Output:
calculating free memory...
calculating largest number of free blocks...
phase 1
try 64 blocks of 33554432 bytes: success
phase 2
try 96 blocks of 33554432 bytes: failure
try 80 blocks of 33554432 bytes: success
try 88 blocks of 33554432 bytes: success
try 92 blocks of 33554432 bytes: failure
try 90 blocks of 33554432 bytes: success
try 91 blocks of 33554432 bytes: success
phase 3
try 91 blocks of 33554432 bytes: success
free blocks: 91
calculating largest number of free blocks...
phase 1
try 64 blocks of 33554432 bytes: success
phase 2
try 96 blocks of 33554432 bytes: failure
try 80 blocks of 33554432 bytes: success
try 88 blocks of 33554432 bytes: success
try 92 blocks of 33554432 bytes: failure
try 90 blocks of 33554432 bytes: success
try 91 blocks of 33554432 bytes: success
phase 3
try 91 blocks of 33554432 bytes: success
free blocks: 91
check once more...
try 91 blocks of 33554432 bytes: success
Available memory: 91 blocks of 33554432 bytes == 3053453312 bytes
I intend to re-purpose these functions into my own application.