On Sun, Jun 23, 2002 at 12:40:58AM +0100, Matthew Toseland wrote:
> On Sat, Jun 22, 2002 at 11:46:45PM +0100, Matthew Toseland wrote:
> > On Sat, Jun 22, 2002 at 11:39:14PM +0100, Matthew Toseland wrote:
> > > Fixed. Attached patch includes my previous work on a histogram of keys
> > > in the datastore by size, I can separate this if people object. The
> > > easiest way to deal with this is to give me CVS write access. Next stop,
> > > P(success).
> > I'm not sure that hooking in AwaitingStoreData is fully comprehensive...
> > what if we generate the StoreData? RequestDone is definitely not the
> > place to use either... any suggestions?
> Oh, please nobody commit this yet. I have almost finished the next part.
> But the above patch forces a datastore reset, at least on Kaffe, because
> I add a new KeyHistogram successDistribution (and a new method,
> pSuccess) to Core.java. If these shouldn't be there, neither should
> requestDistribution IMVHO. I'm on #freenet.

Attached is the latest version of the Big Histogram Patch (tm).
It implements a new table, 'Probability of success of an incoming
request', as well as histograms of successful incoming requests and
of the sizes of the files in the datastore. It forces a datastore reset
at least on my Kaffe, relative to unpatched CVS, because I add a new
KeyHistogram (successDistribution) to Core.java. It is possible that
this is not the right place to put it; I suggest that if we move
successDistribution, we should also move requestDistribution.
? noderefs.txt
? src/freenet/support/KeySizeHistogram.java
Index: src/freenet/Core.java
===================================================================
RCS file: /cvsroot/freenet/freenet/src/freenet/Core.java,v
retrieving revision 1.10
diff -u -r1.10 Core.java
--- src/freenet/Core.java       25 Apr 2002 05:02:37 -0000      1.10
+++ src/freenet/Core.java       23 Jun 2002 00:46:06 -0000
@@ -211,6 +211,20 @@
     /** Distribution of inbound requests over the keyspace. **/
     public static KeyHistogram requestDistribution = null;
 
+    /** Distribution of successful inbound requests over the keyspace **/
+    public static KeyHistogram successDistribution = null;
+
+    /**
+     * Returns the probability of success of a request that would go into
+     * a given bin for stats purposes
+     */
+    public static float pSuccess(int bin)
+    {
+       int x = requestDistribution.getBin(bin);
+       //if(x == 0) return 0;
+       return ((float)successDistribution.getBin(bin) / (float)x);
+    }
+
     /**
      * Sets the logging object to be used for logging messages
      * @param log a Logger object that will log messages to an output stream.
Index: src/freenet/client/http/NodeStatusServlet.java
===================================================================
RCS file: /cvsroot/freenet/freenet/src/freenet/client/http/NodeStatusServlet.java,v
retrieving revision 1.26
diff -u -r1.26 NodeStatusServlet.java
--- src/freenet/client/http/NodeStatusServlet.java      30 May 2002 23:56:51 -0000     
 1.26
+++ src/freenet/client/http/NodeStatusServlet.java      23 Jun 2002 00:46:10 -0000
@@ -41,6 +41,7 @@
 import freenet.support.StringMap;
 import freenet.support.SimpleStringMap;
 import freenet.support.KeyHistogram;
+import freenet.support.KeySizeHistogram;
 import freenet.support.graph.BitmapEncoder;
 
 /*
@@ -141,6 +142,11 @@
                 return;
             }
 
+           if (uri.endsWith("ds_size_histogram.txt")) {
+               sendDSSizeHistogram(resp, false);
+               return;
+           };
+
             if (uri.endsWith("inbound_request_histogram.txt")) {
                 int[] bins = null;
                 if (node.requestDistribution != null) {
@@ -149,10 +155,21 @@
                 sendKeyHistogram(resp, false, bins, 
                                  "Histogram of requested keys.",
                                  "This count has nothing to do with keys in your 
datastore",
-                                 MSG_NO_REQUEST_DIST);
+                                 MSG_NO_REQUEST_DIST, "keys", false);
                 return;
             }
 
+           if(uri.endsWith("inbound_success_histogram.txt")) {
+              int [] bins = null;
+              if (node.successDistribution != null) {
+                  bins = node.successDistribution.getBins();
+              }
+              sendKeyHistogram(resp, false, bins,
+                               "Histogram of successfully requested keys.",
+                               "This count has nothing to do with keys in your 
+datastore",
+                               MSG_NO_REQUEST_DIST, "keys", false);
+              return;
+           }
 
             if (uri.endsWith("key_histogram_data.txt")) {
                 sendRTHistogram(resp, true);
@@ -164,6 +181,11 @@
                 return;
             }
 
+           if (uri.endsWith("ds_size_histogram_data.txt")) {
+               sendDSSizeHistogram(resp, true);
+               return;
+           }
+
             if (uri.endsWith("inbound_request_histogram_data.txt")) {
                 int[] bins = null;
                 if (node.requestDistribution != null) {
@@ -173,11 +195,29 @@
                 sendKeyHistogram(resp, true, bins,  
                                  "Histogram of requested keys.",
                                  "This count has nothing to do with keys in your 
datastore",
-                                 MSG_NO_REQUEST_DIST); 
+                                 MSG_NO_REQUEST_DIST, "keys", false); 
 
                 return;
             }
 
+           if (uri.endsWith("inbound_success_histogram_data.txt")) {
+               int[] bins = null;
+               if (node.successDistribution != null) {
+                   bins = node.successDistribution.getBins();
+               }
+               
+               sendKeyHistogram(resp, true, bins,
+                                "Histogram of successfully requested keys.",
+                                "This count has nothing to do with keys in your 
+datastore",
+                                MSG_NO_REQUEST_DIST, "keys", false);
+               return;
+           }
+
+           if (uri.endsWith("psuccess_data.txt")) {
+               sendPSuccessList(resp);
+               return;
+           }
+           
             if (uri.endsWith("noderefs.txt")) {
                 sendRefList(req, resp);
             }
@@ -338,13 +378,23 @@
         pw.println("            <li> <a href=\"" + baseURL + "ds_histogram.txt\"> " +
                    " Histogram of keys in the local DataStore. </a>"  +
                    " &nbsp &nbsp  <em>Note: Slow. Be patient. </em> ");
-        pw.println("            <a href= \"" + baseURL +
-                   "ds_histogram_data.txt\">" +
+        pw.println("            <li> <a href= \"" + baseURL +
+                   "ds_histogram_data.txt\"> " +
                    "<br>(flat ascii)</a><br>");
-
-        pw.println("            <li> <em> TODO: We need distribution data for 
succcessful requests. </em>");
-        pw.println("                 <br>I'm really busy these days.  It would be 
cool if someone could code");
-        pw.println("                 this up. --gj");
+       pw.println("            <li> <a href=\"" + baseURL + "ds_size_histogram.txt\"> 
+" +
+                   " Histogram of sizes of keys in local DataStore. </a>");
+       pw.println("            <li> <a href= \"" + baseURL +
+                  "ds_size_histogram_data.txt\">" +
+                  "<br>(flat ascii)</a><br>");
+
+       pw.println("            <li> <a href=\"" + baseURL + 
+"inbound_success_histogram.txt\"> " +
+                  " Histogram of successful inbound request search keys </a>");
+       pw.println("            <li> <a href=\"" + baseURL + 
+                  "inbound_success_histogram_data.txt\">" +
+                  "<br>(flat ascii)</a><br>");
+       pw.println("            <li> <a href=\"" + baseURL +
+                  "psuccess_data.txt\">" +
+                  " Probability of success of an incoming request </a><br>");
         pw.println("        </ul> <p>");
         pw.println("    <li> <a href=\"" + baseURL +"diagnostics/index.html\"> 
Diagnostics Values </a> <p>");
         pw.println("    <li> <a href=\"" + baseURL +"inboundContacts.txt\"> Inbound 
Contact Attempts </a> <br>");
@@ -392,7 +442,7 @@
     }
 
     private final static String drawLine(int binNum, int freq) {
-        String ret = Integer.toString(binNum, 16) + " |";
+        String ret = "";
         for (int i = 0; i < freq; i++) {
             ret += "=";
         }
@@ -486,7 +536,8 @@
                          "Histogram of keys in in fred's Routing table",
                          "This count has nothing to do with keys in your datastore, " 
+
                          "these keys are used for routing",
-                         MSG_OOPS /* bins should always be non-null */);
+                         MSG_OOPS /* bins should always be non-null */,
+                        "keys", false);
                          
     }
 
@@ -499,13 +550,55 @@
                          "Histogram of keys in in fred's data store",
                          "These are the keys to the data in your node's " +
                          "local cache (DataStore)",
-                         MSG_OOPS /* bins should always be non-null */);
+                         MSG_OOPS /* bins should always be non-null */,
+                        "keys", false);
                          
     }
 
+    private void sendDSSizeHistogram(HttpServletResponse resp, boolean justData) 
+throws IOException {
+
+       FSDataStore ds = (FSDataStore) node.ds;
+       KeySizeHistogram histogram = ds.getSizeHistogram();
+
+       sendKeyHistogram(resp, justData, histogram.getBins(),
+                  "Histogram of sizes of keys in fred's data store",
+                  "These are the numbers of keys in your DataStore" +
+                  " of (roughly) each size",
+                  MSG_OOPS /* bins should always be non-null */, "keys",
+                  true);
+    }
+
+    private void sendPSuccessList(HttpServletResponse resp) throws IOException
+    {
+       resp.setStatus(HttpServletResponse.SC_OK);
+       resp.setContentType("text/plain");
+       PrintWriter pw = resp.getWriter();
+       pw.println("Probability of success of an incoming request");
+       DateFormat df = DateFormat.getDateTimeInstance();
+       String date = df.format(new Date(System.currentTimeMillis()));
+       pw.println(date);
+       float pMax = 0;
+       for (int i = 0; i < node.requestDistribution.length(); i++) {
+           float p = node.pSuccess(i);
+           if(Float.isNaN(p))
+           {
+               pw.println(Integer.toString(i, 16) + " | -");
+           }
+           else
+           {
+               pw.println(Integer.toString(i, 16) + " | " + p);
+           }
+           if(p > pMax) pMax = p;
+       };
+       pw.println("");
+       pw.println("Max: " + pMax);
+       resp.flushBuffer();
+    }
+       
     private void sendKeyHistogram(HttpServletResponse resp, boolean justData, int[] 
bins,
                                   String title, String comment,
-                                  String complaint) throws IOException {
+                                  String complaint, String commodity,
+                                 boolean exponential) throws IOException {
 
         if (bins == null) {
             resp.setStatus(HttpServletResponse.SC_OK);
@@ -526,7 +619,7 @@
             }
         }
 
-        float scale = 1.0f;
+        double scale = 1.0f;
         if (maximum > 64) {
             // REDFLAG: test
             // Scale factor for ASCII limits line lengths to 64
@@ -543,24 +636,40 @@
         if (justData) {
             pw.println("# " + title);
             pw.println("# " + date);
-            pw.println("# keys: " + count);
+            pw.println("# " + commodity + ": " + count);
 
         }
         else {
             pw.println(title);
            pw.println(comment);
             pw.println(date);
-            pw.println("keys: " + count);
+            pw.println(commodity + ": " + count);
             pw.println("scale factor: " + scale + " (This is used to keep lines < 64 
characters)");
             pw.println("");
         }
         for (i = 0; i < bins.length; i++) {
+           String line;
+           if(exponential)
+           {
+               line = shortPowerString(10+i);
+               if(i == (bins.length-1))
+               {
+                       line += "+";
+               };
+           }
+           else
+           {
+               line = Integer.toString(i, 16);
+           };
             if (justData) {
-                pw.println(i + "\t" + bins[i] );
+               line += "\t" + bins[i];
             }
             else {
-                pw.println(drawLine(i, ((int)(bins[i] * scale))));
+               if(!exponential || (i != (bins.length-1))) line += " ";
+               while(line.length()<5) { line = " " + line; };
+               line += "|" + drawLine(i, ((int)(bins[i] * scale)));
             }
+           pw.println(line);
         }
 
         pw.println("");
@@ -572,6 +681,19 @@
         resp.flushBuffer(); 
     }
 
+    private String shortPowerString(int power)
+    {
+       int x = power % 10;
+       if(x==10) x = 0;
+       String ret = Integer.toString(1 << x);
+       char SI[] = {'k','M','G','T','P','E'};
+       if(power >= 10)
+       {
+               ret += SI[(power/10)-1];
+       };
+       return ret;
+    };
+           
     private void sendStatusPage(HttpServletResponse resp) throws IOException {
         long now = System.currentTimeMillis();
         DateFormat df = DateFormat.getDateTimeInstance();
Index: src/freenet/node/Main.java
===================================================================
RCS file: /cvsroot/freenet/freenet/src/freenet/node/Main.java,v
retrieving revision 1.44
diff -u -r1.44 Main.java
--- src/freenet/node/Main.java  1 Jun 2002 22:01:03 -0000       1.44
+++ src/freenet/node/Main.java  23 Jun 2002 00:46:15 -0000
@@ -635,6 +635,10 @@
             Core.requestDistribution = new KeyHistogram();
         }
 
+       // Non-optional because we want to use it for request
+       // triage in overload
+       Core.successDistribution = new KeyHistogram();
+       
         // the FCP interface
         SessionHandler clientSh = new SessionHandler();
         clientSh.register(new FnpLinkManager(), 10);
Index: src/freenet/node/ds/FSDataStore.java
===================================================================
RCS file: /cvsroot/freenet/freenet/src/freenet/node/ds/FSDataStore.java,v
retrieving revision 1.6
diff -u -r1.6 FSDataStore.java
--- src/freenet/node/ds/FSDataStore.java        25 Apr 2002 05:02:37 -0000      1.6
+++ src/freenet/node/ds/FSDataStore.java        23 Jun 2002 00:46:16 -0000
@@ -261,6 +261,27 @@
         return histogram;
     }
 
+    public KeySizeHistogram getSizeHistogram() {
+       KeySizeHistogram histogram = new KeySizeHistogram();
+
+       synchronized (dir.semaphore()) {
+           Enumeration keys = dir.keys(true);
+           while (keys.hasMoreElements()) {
+               FileNumber fn = (FileNumber) keys.nextElement();
+               Buffer buffer = dir.fetch(fn);
+               try {
+                   histogram.add( new Key(fn.getByteArray()), buffer.length() );
+               }
+               finally
+               {
+                   buffer.release();
+               }
+           }
+       }
+           
+       return histogram;
+    }
+       
     private static final class KeyWalk implements Walk {
         private final Walk fnw;
         KeyWalk(Walk fnw) {
Index: src/freenet/node/states/request/AwaitingStoreData.java
===================================================================
RCS file: 
/cvsroot/freenet/freenet/src/freenet/node/states/request/AwaitingStoreData.java,v
retrieving revision 1.5
diff -u -r1.5 AwaitingStoreData.java
--- src/freenet/node/states/request/AwaitingStoreData.java      25 Mar 2002 22:18:44 
-0000      1.5
+++ src/freenet/node/states/request/AwaitingStoreData.java      23 Jun 2002 00:46:17 
+-0000
@@ -76,7 +76,17 @@
         }
         // yay!
         routes.routeSucceeded();
-        // Update global network load estimate stats.
+       
+       // Update successful request distribution
+       if (n.successDistribution != null)
+       {
+           if(origPeer != null)
+           {
+              n.successDistribution.add(searchKey);
+           };
+       };
+
+       // Update global network load estimate stats.                       
         n.loadStats.storeRequestRateForNode(sd.dataSource(), sd.requestsPerHour());
         relayStoreData(n, sd);
 
Index: src/freenet/node/states/request/SendingReply.java
===================================================================
RCS file: /cvsroot/freenet/freenet/src/freenet/node/states/request/SendingReply.java,v
retrieving revision 1.4
diff -u -r1.4 SendingReply.java
--- src/freenet/node/states/request/SendingReply.java   25 Mar 2002 22:18:44 -0000     
 1.4
+++ src/freenet/node/states/request/SendingReply.java   23 Jun 2002 00:46:17 -0000
@@ -48,8 +48,17 @@
                     n.logger.log(this,
                         "Failed to send back StoreData to peer " + e.peer,
                         e, Logger.MINOR);
+                   // Not our fault, so still counts
                 }
-                return new RequestDone(this);
+               // Update successful request distribution
+               if (n.successDistribution != null)
+               {
+                   if(origPeer != null)
+                   {
+                      n.successDistribution.add(searchKey);
+                   };
+               };
+               return new RequestDone(this);
             
             case Presentation.CB_CACHE_FAILED:
                 fail(n, "Cache failed");
Index: src/freenet/support/KeyHistogram.java
===================================================================
RCS file: /cvsroot/freenet/freenet/src/freenet/support/KeyHistogram.java,v
retrieving revision 1.1
diff -u -r1.1 KeyHistogram.java
--- src/freenet/support/KeyHistogram.java       25 Apr 2002 05:02:37 -0000      1.1
+++ src/freenet/support/KeyHistogram.java       23 Jun 2002 00:46:17 -0000
@@ -18,5 +18,13 @@
         return ret;
     }
     
+    public synchronized int getBin(int bin) {
+       return bins[bin];
+    }
+    
+    public synchronized int length() {
+       return bins.length;
+    }
+    
     private int bins[] = new int[16];
 }
package freenet.support;

import freenet.Key;

public class KeySizeHistogram {

    public synchronized void add(Key key, long len) {
	int binNumber = 0;
	int i = 2048;
	for(binNumber=0; i<len;)
	{
		i <<= 1;
		binNumber++;
	};
	if(binNumber < 0) binNumber = 0;
	if(binNumber > 15) binNumber = 15;
	bins[binNumber]++;
    }

    // Distribution of keys with most significant nibbles 0-f.
    public synchronized int[] getBins() {
        int[] ret = new int[bins.length];
        System.arraycopy(bins, 0, ret, 0, bins.length);
        return ret;
    }
    
    private int bins[] = new int[21];
}

Attachment: msg03322/pgp00000.pgp
Description: PGP signature

Reply via email to