Changeset: 62fb0d6419ab for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=62fb0d6419ab
Added Files:
gdk/gdk_hash.c
gdk/gdk_hash.h
Modified Files:
clients/Tests/exports.stable.out
gdk/Makefile.ag
gdk/gdk.h
gdk/gdk_bat.c
gdk/gdk_batop.c
gdk/gdk_group.c
gdk/gdk_join.c
gdk/gdk_logger.c
gdk/gdk_private.h
gdk/gdk_search.c
gdk/gdk_search.h
gdk/gdk_select.c
gdk/gdk_setop.c
gdk/gdk_unique.c
monetdb5/mal/mal_runtime.c
monetdb5/modules/kernel/bat5.c
monetdb5/modules/mal/cluster.c
monetdb5/modules/mal/tokenizer.c
sql/backends/monet5/sql.c
sql/storage/bat/bat_table.c
Branch: partioned-hash
Log Message:
Implemented partioned hash tables.
The hash table implementation is now in a separate file, gdk_hash.c.
The idea behind the hash table has not changed, except that now the
hash table is split into multiple pieces.
diffs (truncated from 2922 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
@@ -135,7 +135,7 @@ BAT *BATgroupsum(BAT *b, BAT *g, BAT *e,
BAT *BATgroupvariance_population(BAT *b, BAT *g, BAT *e, BAT *s, int tp, int
skip_nils, int abort_on_error);
BAT *BATgroupvariance_sample(BAT *b, BAT *g, BAT *e, BAT *s, int tp, int
skip_nils, int abort_on_error);
BUN BATgrows(BAT *b);
-gdk_return BAThash(BAT *b, BUN masksize);
+gdk_return BAThash(BAT *b);
gdk_return BATimprints(BAT *b);
gdk_return BATins(BAT *b, BAT *c, bit force);
BAT *BATintersectcand(BAT *a, BAT *b);
diff --git a/gdk/Makefile.ag b/gdk/Makefile.ag
--- a/gdk/Makefile.ag
+++ b/gdk/Makefile.ag
@@ -26,6 +26,7 @@ lib_gdk = {
gdk_system.h gdk_system_private.h gdk_tm.h gdk_storage.h \
gdk_calc.c gdk_calc.h gdk_calc_compare.h gdk_calc_private.h \
gdk_aggr.c gdk_group.c gdk_mapreduce.c gdk_mapreduce.h \
+ gdk_hash.c gdk_hash.h \
gdk_imprints.c gdk_imprints.h \
gdk_join.c gdk_join_legacy.c \
gdk_unique.c \
diff --git a/gdk/gdk.h b/gdk/gdk.h
--- a/gdk/gdk.h
+++ b/gdk/gdk.h
@@ -622,12 +622,12 @@ typedef size_t BUN;
#endif
typedef uint16_t BUN2type;
typedef uint32_t BUN4type;
-#if SIZEOF_BUN > 4
+#ifdef BUN8
typedef uint64_t BUN8type;
#endif
#define BUN2_NONE ((BUN2type) 0xFFFF)
#define BUN4_NONE ((BUN4type) 0xFFFFFFFF)
-#if SIZEOF_BUN > 4
+#ifdef BUN8
#define BUN8_NONE ((BUN8type) LL_CONSTANT(0xFFFFFFFFFFFFFFFF))
#endif
@@ -663,16 +663,7 @@ typedef struct {
bat parentid; /* cache id of VIEW parent bat */
} Heap;
-typedef struct {
- int type; /* type of index entity */
- int width; /* width of hash entries */
- BUN nil; /* nil representation */
- BUN lim; /* collision list size */
- BUN mask; /* number of hash buckets-1 (power of 2) */
- void *Hash; /* hash table */
- void *Link; /* collision list */
- Heap *heap; /* heap where the hash is stored */
-} Hash;
+#include "gdk_hash.h"
typedef struct Imprints Imprints;
@@ -2072,7 +2063,8 @@ gdk_export oid OIDnew(oid inc);
* accelerator on the tail of the BAT exists. GDK_FAIL is returned
* upon failure to create the supportive structures.
*/
-gdk_export gdk_return BAThash(BAT *b, BUN masksize);
+
+gdk_export gdk_return BAThash(BAT *b);
/*
* @- Column Imprints Functions
@@ -2975,85 +2967,8 @@ gdk_export void ALIGNsetH(BAT *b1, BAT *
#define DELloop(b, p, q) \
for (q = (b)->batFirst, p = (b)->batDeleted; p < q; p++)
-/*
- * @- hash-table supported loop over BUNs
- * The first parameter `b' is a BAT, the second (`h') should point to
- * `b->H->hash', and `v' a pointer to an atomic value (corresponding
- * to the head column of `b'). The 'hb' is an integer index, pointing
- * out the `hb'-th BUN.
- */
#define GDK_STREQ(l,r) (*(char*) (l) == *(char*) (r) && !strcmp(l,r))
-#define HASHloop(bi, h, hb, v) \
- for (hb = HASHget(h, HASHprobe((h), v)); \
- hb != HASHnil(h); \
- hb = HASHgetlink(h,hb)) \
- if (ATOMcmp(h->type, v, BUNtail(bi, hb)) == 0)
-#define HASHloop_str_hv(bi, h, hb, v) \
- for (hb = HASHget((h),((BUN *) (v))[-1]&(h)->mask); \
- hb != HASHnil(h); \
- hb = HASHgetlink(h,hb)) \
- if (GDK_STREQ(v, BUNtvar(bi, hb)))
-#define HASHloop_str(bi, h, hb, v) \
- for (hb = HASHget((h),strHash(v)&(h)->mask); \
- hb != HASHnil(h); \
- hb = HASHgetlink(h,hb)) \
- if (GDK_STREQ(v, BUNtvar(bi, hb)))
-
-/*
- * The following example shows how the hashloop is used:
- *
- * @verbatim
- * void
- * print_books(BAT *books_author, str author)
- * {
- * BAT *b = books_author;
- * BUN i;
- *
- * printf("%s\n==================\n", author);
- * HASHloop(b, (b)->T->hash, i, author)
- * printf("%s\n", ((str) BUNhead(b, i));
- * }
- * @end verbatim
- *
- * Note that for optimization purposes, we could have used a
- * HASHloop_str instead, and also a BUNhvar instead of a BUNhead
- * (since we know the head-type of books_author is string, hence
- * variable-sized). However, this would make the code less general.
- *
- * @- specialized hashloops
- * HASHloops come in various flavors, from the general HASHloop, as
- * above, to specialized versions (for speed) where the type is known
- * (e.g. HASHloop_int), or the fact that the atom is fixed-sized
- * (HASHlooploc) or variable-sized (HASHloopvar).
- */
-#define HASHlooploc(bi, h, hb, v) \
- for (hb = HASHget(h, HASHprobe(h, v)); \
- hb != HASHnil(h); \
- hb = HASHgetlink(h,hb)) \
- if (ATOMcmp(h->type, v, BUNtloc(bi, hb)) == 0)
-#define HASHloopvar(bi, h, hb, v) \
- for (hb = HASHget(h,HASHprobe(h, v)); \
- hb != HASHnil(h); \
- hb = HASHgetlink(h,hb)) \
- if (ATOMcmp(h->type, v, BUNtvar(bi, hb)) == 0)
-
-#define HASHloop_TYPE(bi, h, hb, v, TYPE) \
- for (hb = HASHget(h, hash_##TYPE(h, v)); \
- hb != HASHnil(h); \
- hb = HASHgetlink(h,hb)) \
- if (simple_EQ(v, BUNtloc(bi, hb), TYPE))
-
-#define HASHloop_bte(bi, h, hb, v) HASHloop_TYPE(bi, h, hb, v, bte)
-#define HASHloop_sht(bi, h, hb, v) HASHloop_TYPE(bi, h, hb, v, sht)
-#define HASHloop_int(bi, h, hb, v) HASHloop_TYPE(bi, h, hb, v, int)
-#define HASHloop_lng(bi, h, hb, v) HASHloop_TYPE(bi, h, hb, v, lng)
-#ifdef HAVE_HGE
-#define HASHloop_hge(bi, h, hb, v) HASHloop_TYPE(bi, h, hb, v, hge)
-#endif
-#define HASHloop_flt(bi, h, hb, v) HASHloop_TYPE(bi, h, hb, v, flt)
-#define HASHloop_dbl(bi, h, hb, v) HASHloop_TYPE(bi, h, hb, v, dbl)
-
/*
* @- loop over a BAT with ordered tail
* Here we loop over a BAT with an ordered tail column (see for
diff --git a/gdk/gdk_bat.c b/gdk/gdk_bat.c
--- a/gdk/gdk_bat.c
+++ b/gdk/gdk_bat.c
@@ -1815,7 +1815,6 @@ BUNlocate(BAT *b, const void *x, const v
lng l;
} hidx, tidx;
BUN p, q;
- BAT *v = NULL;
BATcheck(b, "BUNlocate: BAT parameter required", 0);
BATcheck(x, "BUNlocate: value parameter required", 0);
@@ -1840,7 +1839,7 @@ BUNlocate(BAT *b, const void *x, const v
}
/* positional lookup is always the best choice */
- if (BATtdense(b))
+ if (BATtdense(b) && !BAThdense(b))
usemirror();
if (BAThdense(b)) {
BUN i = (BUN) (*(oid *) x - b->hseqbase);
@@ -1871,61 +1870,12 @@ BUNlocate(BAT *b, const void *x, const v
if (p >= q)
return BUN_NONE; /* value combination cannot occur */
- /* if the range is still larger than 32 BUNs, consider
- * investing in a hash table */
- if ((q - p) > (1 << 5)) {
- /* regrettably MonetDB support only single-column hashes
- * strategy: create a hash on both columns, and select
- * the column with the best distribution
- */
- if ((b->T->hash && b->H->hash == NULL) || !dohash(b->H))
- usemirror();
- if (b->H->hash == NULL && (v = VIEWcreate_(b, b, TRUE)) !=
NULL) {
- /* As we are going to remove the worst hash
- * table later, we must do everything in a
- * view, as it is not permitted to remove a
- * hash table from a read-only operation (like
- * BUNlocate). Other threads might then crash.
- */
- if (dohash(v->H))
- (void) BAThash(BATmirror(v), 0);
- if (dohash(v->T))
- (void) BAThash(v, 0);
- if (v->H->hash && v->T->hash) { /* we can choose
between two hash tables */
- BUN hcnt = 0, tcnt = 0;
- BUN i;
-
- for (i = 0; i <= v->H->hash->mask; i++)
- hcnt += HASHget(v->H->hash,i) !=
HASHnil(v->H->hash);
- for (i = 0; i <= v->T->hash->mask; i++)
- tcnt += HASHget(v->T->hash,i) !=
HASHnil(v->T->hash);
- if (hcnt < tcnt) {
- usemirror();
- v = BATmirror(v);
- }
- /* remove the least selective hash table */
- HASHremove(v);
- }
- if (v->H->hash == NULL) {
- usemirror();
- v = BATmirror(v);
- }
- if (v->H->hash) {
- MT_lock_set(&GDKhashLock(abs(b->batCacheid)),
"BUNlocate");
- if (b->H->hash == NULL) { /* give it to
the parent */
- b->H->hash = v->H->hash;
- }
- MT_lock_unset(&GDKhashLock(abs(b->batCacheid)),
"BUNlocate");
- }
- BBPreclaim(v);
- v = NULL;
- }
- }
-
/* exploit string double elimination, when present */
htpe = ATOMbasetype(b->htype);
ttpe = ATOMbasetype(b->ttype);
- if (ATOMstorage(htpe) == TYPE_str && GDK_ELIMDOUBLES(b->H->vheap) &&
b->H->width > 2) {
+ if (ATOMstorage(htpe) == TYPE_str &&
+ GDK_ELIMDOUBLES(b->H->vheap) &&
+ b->H->width > 2) {
hidx.v = strLocate(b->H->vheap, x);
if (hidx.v == 0)
return BUN_NONE; /* x does not occur */
@@ -1950,7 +1900,9 @@ BUNlocate(BAT *b, const void *x, const v
}
}
}
- if (ATOMstorage(ttpe) == TYPE_str && GDK_ELIMDOUBLES(b->T->vheap) &&
b->T->width > 2) {
+ if (ATOMstorage(ttpe) == TYPE_str &&
+ GDK_ELIMDOUBLES(b->T->vheap) &&
+ b->T->width > 2) {
tidx.v = strLocate(b->T->vheap, y);
if (tidx.v == 0)
return BUN_NONE; /* y does not occur */
@@ -1998,26 +1950,28 @@ BUNlocate(BAT *b, const void *x, const v
/* hashloop over head values, check tail values */
if (b->H->hash) {
BUN h;
+ BUN prb = HASHprobe(b->H->hash, x);
+ int pcs;
bi = bat_iterator(BATmirror(b)); /* HASHloop works on tail */
if (hint && tint) {
- HASHloop_int(bi, b->H->hash, h, x)
+ HASHloop_int(bi, b->H->hash, prb, x, h, pcs)
if (*(int *) y == *(int *) BUNhloc(bi, h))
return h;
} else if (hint && tlng) {
- HASHloop_int(bi, b->H->hash, h, x)
+ HASHloop_int(bi, b->H->hash, prb, x, h, pcs)
if (*(lng *) y == *(lng *) BUNhloc(bi, h))
return h;
} else if (hlng && tint) {
- HASHloop_lng(bi, b->H->hash, h, x)
+ HASHloop_lng(bi, b->H->hash, prb, x, h, pcs)
if (*(int *) y == *(int *) BUNhloc(bi, h))
return h;
} else if (hlng && tlng) {
- HASHloop_lng(bi, b->H->hash, h, x)
+ HASHloop_lng(bi, b->H->hash, prb, x, h, pcs)
if (*(lng *) y == *(lng *) BUNhloc(bi, h))
return h;
} else {
- HASHloop(bi, b->H->hash, h, x)
+ HASHloop(bi, b->H->hash, prb, x, h, pcs)
if ((*tcmp) (y, BUNhead(bi, h)) == 0)
return h;
}
@@ -2850,7 +2804,7 @@ BATassertHeadProps(BAT *b)
}
PROPDEBUG { /* only do a scan if property checking is requested */
- if (b->hsorted || b->hrevsorted || !b->hkey) {
+ if (b->hsorted || b->hrevsorted || !b->hkey || BATcount(b) ==
0) {
/* if sorted (either way), or we don't have to
* prove uniqueness, we can do a simple
* scan */
@@ -2894,16 +2848,15 @@ BATassertHeadProps(BAT *b)
/* we need to check for uniqueness the hard
* way (i.e. using a hash table) */
const char *nme = BBP_physical(b->batCacheid);
- char *ext;
size_t nmelen = strlen(nme);
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list