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


Reply via email to