Author: stefan2
Date: Thu Jan 10 10:48:12 2013
New Revision: 1431268
URL: http://svn.apache.org/viewvc?rev=1431268&view=rev
Log:
Improve fsfs-access-map tool: saturate at 64k accesses instead
of just 255 per 64kB cluster. Tests show that we need some
resolution for > 1000 hits / cluster as these are quite frequent.
Also, generate a scale bitmap that may be used as (the basis of)
a legend in e.g. presentations.
* tools/dev/fsfs-access-map.c
(file_stats_t): mention that we record hits with 2 bytes now
(word): new typedef
(store_read_info,
open_file,
seek_file): update
(select_color): update; refine color scale
(write_bitmap_header): factored out from write_bitmap
(write_bitmap): update
(write_scale): new function
(main): call the new function, too
Modified:
subversion/trunk/tools/dev/fsfs-access-map.c
Modified: subversion/trunk/tools/dev/fsfs-access-map.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/tools/dev/fsfs-access-map.c?rev=1431268&r1=1431267&r2=1431268&view=diff
==============================================================================
--- subversion/trunk/tools/dev/fsfs-access-map.c (original)
+++ subversion/trunk/tools/dev/fsfs-access-map.c Thu Jan 10 10:48:12 2013
@@ -65,7 +65,7 @@ typedef struct file_stats_t
* (i.e. number of non-zero entries in read_map). */
apr_int64_t unique_clusters_read;
- /* cluster -> read count mapping (1 byte per cluster, saturated at 255) */
+ /* cluster -> read count mapping (1 word per cluster, saturated at 64k) */
apr_array_header_t *read_map;
} file_stats_t;
@@ -90,6 +90,7 @@ typedef struct handle_info_t
/* useful typedef */
typedef unsigned char byte;
+typedef unsigned short word;
/* global const char * file name -> *file_info_t map */
static apr_hash_t *files = NULL;
@@ -121,17 +122,17 @@ store_read_info(handle_info_t *handle_in
/* auto-expand access map in case the file later shrunk or got deleted */
while (handle_info->file->read_map->nelts <= last_cluster)
- APR_ARRAY_PUSH(handle_info->file->read_map, byte) = 0;
+ APR_ARRAY_PUSH(handle_info->file->read_map, word) = 0;
/* accumulate the accesses per cluster. Saturate and count first
* (i.e. disjoint) accesses clusters */
handle_info->file->clusters_read += last_cluster - first_cluster + 1;
for (i = first_cluster; i <= last_cluster; ++i)
{
- byte *count = &APR_ARRAY_IDX(handle_info->file->read_map, i, byte);
+ word *count = &APR_ARRAY_IDX(handle_info->file->read_map, i, word);
if (*count == 0)
handle_info->file->unique_clusters_read++;
- if (*count < 255)
+ if (*count < 0xffff)
++*count;
}
}
@@ -173,7 +174,7 @@ open_file(const char *name, int handle)
cluster_count = (apr_size_t)(1 + (file->size - 1) / cluster_size);
file->read_map = apr_array_make(pool, file->size
? cluster_count
- : 1, sizeof(byte));
+ : 1, sizeof(word));
while (file->read_map->nelts < cluster_count)
APR_ARRAY_PUSH(file->read_map, byte) = 0;
@@ -247,7 +248,7 @@ seek_file(int handle, apr_int64_t locati
* there will probably be a real I/O seek on the following read.
*/
if ( handle_info->file->read_map->nelts <= cluster
- || APR_ARRAY_IDX(handle_info->file->read_map, cluster, byte) == 0)
+ || APR_ARRAY_IDX(handle_info->file->read_map, cluster, word) == 0)
handle_info->file->uncached_seek_count++;
}
}
@@ -402,33 +403,38 @@ interpolate(int y0, int x0, int y1, int
/* Return the BMP-encoded 24 bit COLOR for the given value.
*/
static void
-select_color(byte color[3], byte value)
+select_color(byte color[3], word value)
{
+ enum { COLOR_COUNT = 10 };
+
/* value -> color table. Missing values get interpolated.
* { count, B - G - R } */
- byte table[7][4] =
+ word table[COLOR_COUNT][4] =
{
- { 0, 255, 255, 255 }, /* unread -> white */
- { 1, 128, 128, 0 }, /* read once -> turquoise */
- { 2, 0, 128, 0 }, /* twice -> green */
- { 4, 0, 192, 192 }, /* 4x -> yellow */
- { 16, 0, 0, 192 }, /* 16x -> red */
- { 64, 192, 0, 128 }, /* 64x -> purple */
- { 255, 0, 0, 0 } /* max -> black */
+ { 0, 255, 255, 255 }, /* unread -> white */
+ { 1, 64, 128, 0 }, /* read once -> turquoise */
+ { 2, 0, 128, 0 }, /* twice -> green */
+ { 8, 0, 192, 192 }, /* 8x -> yellow */
+ { 64, 0, 0, 192 }, /* 64x -> red */
+ { 256, 64, 32, 230 }, /* 256x -> bright red */
+ { 512, 192, 0, 128 }, /* 512x -> purple */
+ { 1024, 96, 32, 96 }, /* 1024x -> UV purple */
+ { 4096, 32, 16, 32 }, /* 4096x -> EUV purple */
+ { 65535, 0, 0, 0 } /* max -> black */
};
/* find upper limit entry for value */
int i;
- for (i = 0; i < 7; ++i)
+ for (i = 0; i < COLOR_COUNT; ++i)
if (table[i][0] >= value)
break;
/* exact match? */
if (table[i][0] == value)
{
- color[0] = table[i][1];
- color[1] = table[i][2];
- color[2] = table[i][3];
+ color[0] = (byte)table[i][1];
+ color[1] = (byte)table[i][2];
+ color[2] = (byte)table[i][3];
}
else
{
@@ -445,10 +451,11 @@ select_color(byte color[3], byte value)
}
}
-/* write the cluster read map for all files in INFO as BMP image to FILE.
+/* Writes a BMP image header to FILE for a 24-bit color picture of the
+ * given XSIZE and YSIZE dimension.
*/
static void
-write_bitmap(apr_array_header_t *info, apr_file_t *file)
+write_bitmap_header(apr_file_t *file, int xsize, int ysize)
{
/* BMP file header (some values need to filled in later)*/
byte header[54] =
@@ -470,7 +477,28 @@ write_bitmap(apr_array_header_t *info, a
0, 0, 0, 0, /* no colors in palette */
0, 0, 0, 0 /* no colors to import */
};
-
+
+ apr_size_t written;
+
+ /* rows in BMP files must be aligned to 4 bytes */
+ int row_size = APR_ALIGN(xsize * 3, 4);
+
+ /* write numbers to header */
+ write_number(header + 2, ysize * row_size + 54);
+ write_number(header + 18, xsize);
+ write_number(header + 22, ysize);
+ write_number(header + 38, ysize * row_size);
+
+ /* write header to file */
+ written = sizeof(header);
+ apr_file_write(file, header, &written);
+}
+
+/* write the cluster read map for all files in INFO as BMP image to FILE.
+ */
+static void
+write_bitmap(apr_array_header_t *info, apr_file_t *file)
+{
int ysize = info->nelts;
int xsize = 0;
int x, y;
@@ -493,15 +521,8 @@ write_bitmap(apr_array_header_t *info, a
row_size = APR_ALIGN(xsize * 3, 4);
padding = row_size - xsize * 3;
- /* write numbers to header */
- write_number(header + 2, ysize * row_size + 54);
- write_number(header + 18, xsize);
- write_number(header + 22, ysize);
- write_number(header + 38, ysize * row_size);
-
/* write header to file */
- written = sizeof(header);
- apr_file_write(file, header, &written);
+ write_bitmap_header(file, xsize, ysize);
/* write all rows */
for (y = 0; y < ysize; ++y)
@@ -512,7 +533,7 @@ write_bitmap(apr_array_header_t *info, a
byte color[3] = { 128, 128, 128 };
if (x < file_info->read_map->nelts)
{
- byte count = APR_ARRAY_IDX(file_info->read_map, x, byte);
+ word count = APR_ARRAY_IDX(file_info->read_map, x, word);
select_color(color, count);
}
@@ -529,6 +550,35 @@ write_bitmap(apr_array_header_t *info, a
}
}
+/* write a color bar with (roughly) logarithmic scale as BMP image to FILE.
+ */
+static void
+write_scale(apr_file_t *file)
+{
+ int x;
+ word value = 0, inc = 1;
+
+ /* write header to file */
+ write_bitmap_header(file, 64, 1);
+
+ for (x = 0; x < 64; ++x)
+ {
+ apr_size_t written;
+ byte color[3] = { 128, 128, 128 };
+
+ select_color(color, value);
+ if (value + (int)inc < 0x10000)
+ {
+ value += inc;
+ if (value >= 8 * inc)
+ inc *= 2;
+ }
+
+ written = sizeof(color);
+ apr_file_write(file, color, &written);
+ }
+}
+
/* Write a summary of the I/O ops to stdout.
* Use POOL for temporaries.
*/
@@ -618,5 +668,11 @@ int main(int argc, const char *argv[])
write_bitmap(get_rev_files(pool), file);
apr_file_close(file);
+ apr_file_open(&file, "scale.bmp",
+ APR_WRITE | APR_CREATE | APR_TRUNCATE | APR_BUFFERED,
+ APR_OS_DEFAULT, pool);
+ write_scale(file);
+ apr_file_close(file);
+
return 0;
}
\ No newline at end of file