Changeset: 13cfc888fcfb for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/13cfc888fcfb
Modified Files:
        clients/Tests/exports.stable.out
        gdk/gdk.h
        gdk/gdk_align.c
        gdk/gdk_bat.c
        gdk/gdk_batop.c
        gdk/gdk_bbp.c
        gdk/gdk_sketch.c
        gdk/gdk_storage.c
        monetdb5/modules/kernel/aggr.c
        sql/backends/monet5/sql_statistics.c
        sql/scripts/80_statistics.sql
        sql/storage/bat/bat_storage.c
Branch: persistent_sketches
Log Message:

Persistent sketches for persistent BATs. WIP.

Handling heap load/unload. Handling some appends/updates. Missing deletes.


diffs (truncated from 1131 to 300 lines):

diff --git a/clients/Tests/exports.stable.out b/clients/Tests/exports.stable.out
--- a/clients/Tests/exports.stable.out
+++ b/clients/Tests/exports.stable.out
@@ -597,8 +597,10 @@ const ptr ptr_nil;
 ssize_t shtFromStr(allocator *ma, const char *src, size_t *len, sht **dst, 
bool external);
 ssize_t shtToStr(allocator *ma, char **dst, size_t *len, const sht *src, bool 
external);
 const sht sht_nil;
-double sketch_estimate(uint8_t cnt_sketch[BUCKETS][CLZ_BUCKETS]);
-int sketch_populate(BAT *n, BATiter *ni, struct canditer *nci, uint8_t 
cnting_sketch[BUCKETS][CLZ_BUCKETS]);
+gdk_export gdk_return sketch_update_many(BATiter *bi, uint8_t 
(*sketch)[CLZ_BUCKETS], const void *values, size_t count);
+gdk_export gdk_return sketch_merge(uint8_t (*dst)[CLZ_BUCKETS], uint8_t 
(*src)[CLZ_BUCKETS]);
+gdk_export double sketch_estimate(uint8_t (*sketch)[CLZ_BUCKETS]);
+gdk_return bat_sketch(BATiter *bi, struct canditer *bci, uint8_t 
(*sketch)[CLZ_BUCKETS]);
 ssize_t sql_daytime_fromstr(allocator *ma, const char *buf, daytime *d, long 
tz_sec, bool tzlocal);
 ssize_t sql_timestamp_fromstr(allocator *ma, const char *buf, timestamp *d, 
long tz_sec, bool tzlocal);
 ssize_t strFromStr(allocator *ma, const char *restrict src, size_t *restrict 
len, char **restrict dst, bool external);
diff --git a/gdk/gdk.h b/gdk/gdk.h
--- a/gdk/gdk.h
+++ b/gdk/gdk.h
@@ -1549,12 +1549,13 @@ typedef struct pipeline_io {
 
 #define ORDERIDXOFF            3
 
-#define HLL_BITS 6
+#define HLL_BITS    6
 #define BITS_MASK   ((1ULL << HLL_BITS) - 1)
 #define MAX_CLZ     (64 - HLL_BITS)
 #define BUCKETS     (1U << HLL_BITS)
 #define CLZ_BUCKETS (MAX_CLZ + 1)
 #define HLLSEED     0xadc83b19ULL
+#define SKETCH_SIZE (BUCKETS * CLZ_BUCKETS)
 
 /* assert that atom width is power of 2, i.e., width == 1<<shift */
 #define assert_shift_width(shift,width)                                \
@@ -1631,6 +1632,7 @@ typedef struct BAT {
        Heap *theap;            /* space for the column. */
        BUN tbaseoff;           /* offset in heap->base (in whole items) */
        Heap *tvheap;           /* space for the varsized data. */
+       Heap *tsketch;
        Hash *thash;            /* hash table */
 #ifdef HAVE_RTREE
        RTree *trtree;          /* rtree geometric index */
@@ -2082,6 +2084,20 @@ gdk_export const inet6 inet6_nil;
 #define ATOMtype(t)            ((t) == TYPE_void ? TYPE_oid : (t))
 #define ATOMextern(t)          (ATOMstorage(t) >= TYPE_str)
 
+static inline bool
+ATOMsketchable(int type)
+{
+       switch (type) {
+       case TYPE_void:
+       case TYPE_bit:
+       case TYPE_msk:
+       case TYPE_oid:
+       case TYPE_ptr:
+               return false;
+       }
+       return true;
+}
+
 /* The base type is the storage type if the comparison function, the
  * hash function, and the nil value are the same as those of the
  * storage type; otherwise it is the type itself. */
@@ -2308,6 +2324,7 @@ typedef struct BATiter {
        Heap *h;
        void *base;
        Heap *vh;
+       Heap *skh;
        BUN count;
        BUN baseoff;
        oid tseq;
@@ -2355,6 +2372,7 @@ bat_iterator_nolock(BAT *b)
                                : NULL,
                        .baseoff = b->tbaseoff,
                        .vh = b->tvheap,
+                       .skh = b->tsketch,
                        .count = b->batCount,
                        .width = b->twidth,
                        .shift = b->tshift,
@@ -3421,11 +3439,11 @@ gdk_export void STRMPdestroy(BAT *b);
 gdk_export bool BAThasstrimps(BAT *b);
 gdk_export gdk_return BATsetstrimps(BAT *b);
 
-gdk_export int sketch_populate(BAT* n, BATiter *ni, struct canditer *nci,
-                              uint8_t cnting_sketch[BUCKETS][CLZ_BUCKETS]);
-/* gdk_export void sketch_merge(BAT* b, BAT* n); */
-gdk_export double sketch_estimate(uint8_t cnt_sketch[BUCKETS][CLZ_BUCKETS]);
-gdk_export double bat_guess_uniques(BAT *b, BATiter *bi, struct canditer *bci);
+/* Sketches exported functions */
+gdk_export gdk_return sketch_update_many(BATiter *bi, uint8_t 
(*sketch)[CLZ_BUCKETS], const void *values, size_t count);
+gdk_export gdk_return sketch_merge(uint8_t (*dst)[CLZ_BUCKETS], uint8_t 
(*src)[CLZ_BUCKETS]);
+gdk_export double sketch_estimate(uint8_t (*sketch)[CLZ_BUCKETS]);
+gdk_return bat_sketch(BATiter *bi, struct canditer *bci, uint8_t 
(*sketch)[CLZ_BUCKETS]);
 
 /* Rtree structure functions */
 #ifdef HAVE_RTREE
@@ -3900,7 +3918,8 @@ enum heaptype {
        hashheap,
        orderidxheap,
        strimpheap,
-       dataheap
+       dataheap,
+       sketchheap
 };
 gdk_export int BBPselectfarm(role_t role, int type, enum heaptype hptype);
 
diff --git a/gdk/gdk_align.c b/gdk/gdk_align.c
--- a/gdk/gdk_align.c
+++ b/gdk/gdk_align.c
@@ -190,6 +190,7 @@ VIEWcreate(oid seq, BAT *b, BUN l, BUN h
        bn->theap = bi.h;
        bn->tbaseoff = bi.baseoff;
        bn->tvheap = bi.vh;
+       bn->tsketch = bi.skh;
 
        tp = VIEWtparent(b);
        if (tp == 0 && b->ttype != TYPE_void)
@@ -198,12 +199,16 @@ VIEWcreate(oid seq, BAT *b, BUN l, BUN h
        HEAPincref(bi.h);
        if (bi.vh)
                HEAPincref(bi.vh);
+       if (bi.skh)
+               HEAPincref(bi.skh);
        if (l != 0 || h < bi.count)
                VIEWboundsbi(&bi, bn, l, h);
        MT_lock_unset(&b->theaplock);
 
        BBPcacheit(bn, true);
        BBPretain(bn->theap->parentid);
+       if (bn->tsketch)
+               BBPretain(bn->tsketch->parentid);
        if (bn->tvheap)
                BBPretain(bn->tvheap->parentid);
        if (bn->ustr)
diff --git a/gdk/gdk_bat.c b/gdk/gdk_bat.c
--- a/gdk/gdk_bat.c
+++ b/gdk/gdk_bat.c
@@ -44,7 +44,6 @@
 #include "monetdb_config.h"
 #include "gdk.h"
 #include "gdk_private.h"
-#include "mutils.h"
 
 #ifdef ALIGN
 #undef ALIGN
@@ -118,7 +117,7 @@ BATcreatedesc(oid hseq, int tt, bool hea
 {
        bat bid;
        BAT *bn;
-       Heap *h = NULL, *vh = NULL;
+       Heap *h = NULL, *vh = NULL, *skh = NULL;
 
        /*
         * Alloc space for the BAT and its dependent records.
@@ -148,12 +147,26 @@ BATcreatedesc(oid hseq, int tt, bool hea
                                .refs = ATOMIC_VAR_INIT(1),
                        };
                }
+
+               if (ATOMsketchable(tt) && role == PERSISTENT) {
+                       if ((skh = GDKmalloc(sizeof(Heap))) == NULL) {
+                               GDKfree(h);
+                               GDKfree(vh);
+                               return NULL;
+                       }
+                       *skh = (Heap) {
+                               .farmid = BBPselectfarm(role, tt, sketchheap),
+                               .dirty = true,
+                               .refs = ATOMIC_VAR_INIT(1),
+                       };
+               }
        }
 
        bid = BBPallocbat(tt);
        if (bid == 0) {
                GDKfree(h);
                GDKfree(vh);
+               GDKfree(skh);
                return NULL;
        }
        bn = BBP_desc(bid);
@@ -183,6 +196,7 @@ BATcreatedesc(oid hseq, int tt, bool hea
                .batRestricted = BAT_WRITE,
                .theap = h,
                .tvheap = vh,
+               .tsketch = skh,
                .creator_tid = MT_getpid(),
                .qc = role == TRANSIENT ? MT_thread_get_qry_ctx() : NULL,
        };
@@ -192,6 +206,12 @@ BATcreatedesc(oid hseq, int tt, bool hea
                const char *nme = BBP_physical(bn->batCacheid);
                settailname(bn->theap, nme, tt, width);
 
+               if (bn->tsketch) {
+                       bn->tsketch->parentid = bn->batCacheid;
+                       strtconcat(bn->tsketch->filename,
+                                  sizeof(bn->tsketch->filename),
+                                  nme, ".tsketch", NULL);
+               }
                if (bn->tvheap) {
                        bn->tvheap->parentid = bn->batCacheid;
                        strtconcat(bn->tvheap->filename,
@@ -334,10 +354,21 @@ COLnew2(oid hseq, int tt, BUN cap, role_
                goto bailout;
        }
 
+       if (ATOMsketchable(tt) && role == PERSISTENT) {
+               assert(bn->tsketch);
+               if (HEAPalloc(bn->tsketch, SKETCH_SIZE, sizeof(uint8_t)) != 
GDK_SUCCEED) {
+                       HEAPfree(bn->theap, true);
+                       goto bailout;
+               }
+               memset(bn->tsketch->base, 0, SKETCH_SIZE);
+       }
+
        if (bn->tvheap && width == 0 && ATOMheap(tt, bn->tvheap, cap) != 
GDK_SUCCEED) {
                HEAPfree(bn->theap, true);
+               HEAPfree(bn->tsketch, true);
                goto bailout;
        }
+
        BBPcacheit(bn, true);
        TRC_DEBUG(ALGO, "-> " ALGOBATFMT "\n", ALGOBATPAR(bn));
        return bn;
@@ -539,6 +570,11 @@ BATclear(BAT *b, bool force)
                }
        }
 
+       if (b->tsketch) {
+               memset(b->tsketch->base, 0, SKETCH_SIZE);
+               b->tsketch->dirty = true;
+       }
+
        b->batInserted = 0;
        b->batCount = 0;
        if (b->ttype == TYPE_void)
@@ -610,6 +646,19 @@ BATfree(BAT *b)
                assert(b->tvheap->parentid == b->batCacheid);
                HEAPfree(b->tvheap, false);
        }
+       /* wait until there are no other references to the heap; a
+        * reference is possible in e.g. BBPsync that uses a
+        * bat_iterator directly on the BBP_desc, i.e. without fix */
+       while (b->tsketch && (ATOMIC_GET(&b->tsketch->refs) & HEAPREFS) > 1) {
+               MT_lock_unset(&b->theaplock);
+               MT_sleep_ms(1);
+               MT_lock_set(&b->theaplock);
+       }
+       if (b->tsketch) {
+               assert((ATOMIC_GET(&b->tsketch->refs) & HEAPREFS) == 1);
+               assert(b->tsketch->parentid == b->batCacheid);
+               HEAPfree(b->tsketch, false);
+       }
        MT_lock_unset(&b->theaplock);
 }
 
@@ -627,6 +676,9 @@ BATdestroy(BAT *b)
        if (b->theap) {
                GDKfree(b->theap);
        }
+       if (b->tsketch) {
+               GDKfree(b->tsketch);
+       }
        if (b->oldtail) {
                ATOMIC_AND(&b->oldtail->refs, ~DELAYEDREMOVE);
                /* the bat has not been committed, so we cannot remove
@@ -872,6 +924,10 @@ COLcopy2(BAT *b, int tt, bool writable, 
                memcpy(bn->theap->base, bi.base, bi.hfree);
                bn->theap->free = bi.hfree;
                bn->theap->dirty = true;
+               if (bn->tsketch) {
+                       memcpy(bn->theap->base, bi.skh, SKETCH_SIZE);
+                       bn->tsketch->dirty = true;
+               }
 
                /* make sure we use the correct capacity */
                if (ATOMstorage(bn->ttype) == TYPE_msk)
@@ -886,10 +942,13 @@ COLcopy2(BAT *b, int tt, bool writable, 
 
                TIMEOUT_LOOP_IDX_DECL(p, bi.count, qry_ctx) {
                        const void *t = BUNtail(&bi, p);
-
-                       if (bunfastapp_nocheck(bn, t) != GDK_SUCCEED) {
+                       if (bunfastapp_nocheck(bn, t) != GDK_SUCCEED)
                                goto bunins_failed;
-                       }
+               }
+               if (bn->tsketch) {
+                       if (bat_sketch(&bi, NULL, (uint8_t (*)[CLZ_BUCKETS]) 
bn->tsketch->base) != GDK_SUCCEED)
+                               goto bunins_failed;
+                       bn->tsketch->dirty = true;
                }
                TIMEOUT_CHECK(qry_ctx, 
GOTO_LABEL_TIMEOUT_HANDLER(bunins_failed, qry_ctx));
                bn->theap->dirty |= bi.count > 0;
@@ -921,6 +980,10 @@ COLcopy2(BAT *b, int tt, bool writable, 
                memcpy(Tloc(bn, 0), bi.base, bn->theap->free);
                bn->theap->dirty |= bi.count > 0;
                algo = "memcpy heap";
+               if (bn->tsketch) {
+                       memcpy(bn->tsketch->base, bi.skh, SKETCH_SIZE);
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to