#include <cstdlib>
#include <iostream>

/* Link me with  -lrt  for clock_gettime(). */

inline double timediff(const struct timespec &a, const struct timespec &b)
{
	return a.tv_sec - b.tv_sec + .000000001 * (a.tv_nsec - b.tv_nsec);
}

int main()
{
	const int repeatcount = 1000000;
	struct timespec starttime, stoptime;

	printf("size\tC\tC++\n");

	for (int size=0; size < 24; ++size) {
		printf("2^%d\t", size);
		
		/* Measure malloc/free speed */
		clock_gettime(CLOCK_REALTIME, &starttime);
		for (int repeat=0; repeat < repeatcount; ++repeat) {
			void* p = malloc(1<<size);
			free(p);
		}
		clock_gettime(CLOCK_REALTIME, &stoptime);
		printf("%f\t", timediff(stoptime, starttime));

		/* Measure new/delete speed */
		clock_gettime(CLOCK_REALTIME, &starttime);
		for (int repeat=0; repeat < repeatcount; ++repeat) {
			unsigned char *p = new unsigned char [1<<size];
			delete p;
		}
		clock_gettime(CLOCK_REALTIME, &stoptime);
		printf("%f\n", timediff(stoptime, starttime));
	}
}

/* Typical output:

size    C               C++
2^0     0.079643        0.103578
2^1     0.079431        0.103126
2^2     0.079281        0.102660
2^3     0.079358        0.103062
2^4     0.079945        0.103202
2^5     0.079437        0.103297
2^6     0.079589        0.103089
2^7     0.134973        0.161627
2^8     0.131455        0.157902
2^9     0.128527        0.154722
2^10    0.128650        0.154682
2^11    0.128286        0.156002
2^12    0.131556        0.154421
2^13    0.128194        0.154417
2^14    0.129464        0.157335
2^15    0.130017        0.156220
2^16    0.130088        0.157181
2^17    0.130130        0.157181
2^18    0.118299        0.144945
2^19    4.516640        4.688484
2^20    6.142792        6.301859
2^21    7.223532        7.411921
2^22    9.378322        9.580369
2^23    9.409887        9.612058

The discontinuity between 2^18 and 2^19 is where glibc switches
allocation strategies from managing buffers within the brk() space
to doing a mmap(,,,MAP_PRIVATE|MAP_ANONYMOUS,,) for each allocation.

*/

