Statistics code.
authorRobert Haas <[email protected]>
Mon, 30 Jul 2012 16:22:12 +0000 (16:22 +0000)
committerRobert Haas <[email protected]>
Mon, 30 Jul 2012 16:22:12 +0000 (16:22 +0000)
src/backend/utils/hash/chash.c

index f44b65009f3a1a50ff4b8810a6560b12f26908e7..bfcf809d3648fe3636a3f353778a116381ae3578 100644 (file)
@@ -158,10 +158,24 @@ typedef struct CHashTableData
        char               *arena;                      /* arena */
 
        /*
-        * This field will be different in each backend; the shared copy is
+        * These fields will be different in each backend; the shared copy is
         * unused.
         */
        uint32                  gc_next;                /* next garbage list to reclaim */
+       uint64                  s_insert_retry; /* insert point concurrently updated */
+       uint64                  s_delete_retry; /* delete point concurrently updated */
+       uint64                  s_cleanup_scan; /* expunge-after-delete failed */
+       uint64                  s_scan_expunge_ok;              /* scan did expunge */
+       uint64                  s_scan_expunge_fail;    /* expunge failed */
+       uint64                  s_scan_restart;                 /* scan restarted */
+       uint64                  s_cleanup_expunge_ok;   /* cleanup scan did expunge */
+       uint64                  s_cleanup_expunge_fail; /* cleanup scan expunge failed */
+       uint64                  s_cleanup_restart;              /* cleanup scan restarted */
+       uint64                  s_allocate_pop_fail;    /* freelist pop failed */
+       uint64                  s_gc_pop_fail;          /* garbage list pop failed */
+       uint64                  s_gc_reclaim_retry;     /* failed to return GC'd nodes */
+       uint64                  s_garbage_retry;        /* failed to enqueue garbage */
+       uint64                  s_free_retry;           /* failed to perform immediate free */
 } CHashTableData;
 
 #define CHashTableGetRaw(table, offset) \
@@ -225,7 +239,7 @@ CHashBootstrap(CHashDescriptor *desc)
        uint32                  bucket_shift;
 
        /* Allocate table and copy descriptor. */
-       table = MemoryContextAlloc(TopMemoryContext, sizeof(CHashTableData));
+       table = MemoryContextAllocZero(TopMemoryContext, sizeof(CHashTableData));
        memcpy(&table->desc, desc, sizeof(CHashDescriptor)); 
 
        /* Sanity checks. */
@@ -474,7 +488,10 @@ retry:
                nnew->next = scan.target;
                if (!__sync_bool_compare_and_swap(scan.pointer_to_target,
                                                                                  scan.target, new))
+               {
+                       table->s_insert_retry++;
                        goto retry;
+               }
        }
 
        /* Allow garbage collection for this bucket. */
@@ -536,6 +553,7 @@ CHashDelete(CHashTable table, void *entry)
                                cleanup_scan = true;
                        break;
                }
+               table->s_delete_retry++;
        }
 
        /*
@@ -543,7 +561,10 @@ CHashDelete(CHashTable table, void *entry)
         * to make sure it's really gone.
         */
        if (cleanup_scan)
+       {
+               table->s_cleanup_scan++;
                CHashBucketCleanup(table, &table->bucket[bucket], hashcode);
+       }
 
        /* Allow garbage collection for this bucket. */
        CHashTableUnsuppressGC();
@@ -631,6 +652,7 @@ zap:
                                 * all non-deleted items (and possibly some deleted items)
                                 * that were present at the time we began the scan.
                                 */
+                               table->s_scan_expunge_ok++;
                                CHashAddToGarbage(table, hashcode & table->bucket_mask,
                                                                  target);
                                target = CHashPtrUnmark(next);
@@ -658,9 +680,13 @@ zap:
                                 * have to be pretty unlucky to have it happen even twice in
                                 * a row.
                                 */
+                               table->s_scan_expunge_fail++;
                                target = *pointer_to_target;
                                if (CHashPtrIsMarked(target))
+                               {
+                                       table->s_scan_restart++;
                                        goto retry;
+                               }
                                continue;
                        }
                }
@@ -771,6 +797,7 @@ retry:
                                                                                         CHashPtrUnmark(next)))
                        {
                                /* We removed the item. */
+                               table->s_cleanup_expunge_ok++;
                                CHashAddToGarbage(table, hashcode & table->bucket_mask,
                                                                  target);
                                target = CHashPtrUnmark(next);
@@ -845,14 +872,18 @@ CHashAllocate(CHashTable table)
                        pg_read_barrier_depends();
                        if (__sync_bool_compare_and_swap(b, new, n->un.gcnext))
                                return new;
+                       table->s_allocate_pop_fail++;
                }
 
                /* If next garbage list is non-empty, empty it via compare-and-swap. */
                table->gc_next = (table->gc_next + 1) % table->ngarbage;
                b = &table->garbage[table->gc_next];
                garbage = *b;
-               if (!CHashPtrIsInvalid(garbage) &&
-                       __sync_bool_compare_and_swap(b, garbage, InvalidCHashPtr))
+               if (CHashPtrIsInvalid(garbage))
+                       ;
+               else if (!__sync_bool_compare_and_swap(b, garbage, InvalidCHashPtr))
+                       ++table->s_gc_pop_fail;
+               else
                {
                        uint64          chash_bucket;
                        uint32          i;
@@ -905,11 +936,14 @@ CHashAllocate(CHashTable table)
 
                                /* Push reclaimed elements onto home free list. */
                                b = &table->freelist[f_home];
-                               do
+                               for (;;)
                                {
                                        oldhead = *b;
                                        n->un.gcnext = oldhead;
-                               } while (!__sync_bool_compare_and_swap(b, oldhead, fhead));
+                                       if (__sync_bool_compare_and_swap(b, oldhead, fhead))
+                                               break;
+                                       ++table->s_gc_reclaim_retry;
+                               }
                        }
 
                        /* Return the element we saved for ourselves. */
@@ -943,11 +977,14 @@ CHashAddToGarbage(CHashTable table, uint32 bucket, CHashPtr c)
        n = CHashTableGetNode(table, c);
        garbage = &table->garbage[garbage_bucket];
 
-       do
+       while (1)
        {
                g = *garbage;
                n->un.gcnext = g;
-       } while (!__sync_bool_compare_and_swap(garbage, g, c));
+               if (__sync_bool_compare_and_swap(garbage, g, c))
+                       break;
+               ++table->s_garbage_retry;
+       }
 }
 
 /*
@@ -970,9 +1007,12 @@ CHashImmediateFree(CHashTable table, CHashPtr c)
        n = CHashTableGetNode(table, c);
        free = &table->freelist[f_home];
 
-       do
+       for (;;)
        {
                f = *free;
                n->un.gcnext = f;
-       } while (!__sync_bool_compare_and_swap(free, f, c));
+               if (__sync_bool_compare_and_swap(free, f, c))
+                       break;
+               ++table->s_free_retry;
+       }
 }