Changeset: 01bc5a1a96ba for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=01bc5a1a96ba
Modified Files:
        clients/Tests/exports.stable.out
        gdk/gdk_join.c
        gdk/gdk_search.c
        gdk/gdk_search.h
Branch: default
Log Message:

Speed up the most common case for hashjoin.


diffs (211 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
@@ -252,7 +252,7 @@ size_t GDKvm_cursize(void);
 void *GDKzalloc(size_t size) __attribute__((__malloc__)) 
__attribute__((__warn_unused_result__));
 void HASHdestroy(BAT *b);
 BUN HASHlist(Hash *h, BUN i);
-BUN HASHprobe(Hash *h, const void *v);
+BUN HASHprobe(const Hash *h, const void *v);
 void HEAP_free(Heap *heap, var_t block);
 void HEAP_initialize(Heap *heap, size_t nbytes, size_t nprivate, int 
alignment);
 var_t HEAP_malloc(Heap *heap, size_t nbytes);
diff --git a/gdk/gdk_join.c b/gdk/gdk_join.c
--- a/gdk/gdk_join.c
+++ b/gdk/gdk_join.c
@@ -1994,6 +1994,41 @@ binsearchcand(const oid *cand, BUN lo, B
                if (hb >= (lo) && hb < (hi) &&                  \
                    simple_EQ(v, BUNtloc(bi, hb), TYPE))
 
+#define HASHJOIN(TYPE, WIDTH)                                          \
+       do {                                                            \
+               BUN hashnil = HASHnil(hsh);                             \
+               for (lo = lstart - BUNfirst(l) + l->hseqbase;           \
+                    lstart < lend;                                     \
+                    lo++) {                                            \
+                       v = FVALUE(l, lstart);                          \
+                       lstart++;                                       \
+                       nr = 0;                                         \
+                       if (*(const TYPE*)v != TYPE##_nil) {            \
+                               for (rb = HASHget##WIDTH(hsh, hash_##TYPE(hsh, 
v)); \
+                                    rb != hashnil;                     \
+                                    rb = HASHgetlink##WIDTH(hsh, rb))  \
+                                       if (rb >= rl && rb < rh &&      \
+                                           * (const TYPE *) v == ((const TYPE 
*) base)[rb]) { \
+                                               ro = (oid) (rb - rl + rseq); \
+                                               HASHLOOPBODY();         \
+                                       }                               \
+                       }                                               \
+                       if (nr == 0) {                                  \
+                               lskipped = BATcount(r1) > 0;            \
+                       } else {                                        \
+                               if (lskipped) {                         \
+                                       r1->tdense = 0;                 \
+                               }                                       \
+                               if (nr > 1) {                           \
+                                       r1->tkey = 0;                   \
+                                       r1->tdense = 0;                 \
+                               }                                       \
+                               if (BATcount(r1) > nr)                  \
+                                       r1->trevsorted = 0;             \
+                       }                                               \
+               }                                                       \
+       } while (0)
+
 static gdk_return
 hashjoin(BAT *r1, BAT *r2, BAT *l, BAT *r, BAT *sl, BAT *sr, int nil_matches,
         int nil_on_miss, int semi, int only_misses, BUN maxsize, lng t0,
@@ -2017,6 +2052,8 @@ hashjoin(BAT *r1, BAT *r2, BAT *l, BAT *
        oid lval = oid_nil;     /* hold value if l has dense tail */
        const char *v = (const char *) &lval;
        int lskipped = 0;       /* whether we skipped values in l */
+       const Hash *restrict hsh;
+       int t;
 
        ALGODEBUG fprintf(stderr, "#hashjoin(l=%s#" BUNFMT "[%s]%s%s%s,"
                          "r=%s#" BUNFMT "[%s]%s%s%s,sl=%s#" BUNFMT "%s%s%s,"
@@ -2118,8 +2155,47 @@ hashjoin(BAT *r1, BAT *r2, BAT *l, BAT *
                goto bailout;
        ri = bat_iterator(r);
        nrcand = (BUN) (rcandend - rcand);
+       hsh = r->T->hash;
+       t = ATOMbasetype(r->ttype);
 
-       if (lcand) {
+       if (lcand == NULL && rcand == NULL && lvars == NULL &&
+           !nil_matches && !nil_on_miss && !semi && !only_misses &&
+           l->ttype != TYPE_void && (t == TYPE_int || t == TYPE_lng)) {
+               /* special case for a common way of calling this
+                * function */
+               const void *restrict base = Tloc(r, 0);
+
+               if (t == TYPE_int) {
+                       switch (hsh->width) {
+                       case BUN2:
+                               HASHJOIN(int, 2);
+                               break;
+                       case BUN4:
+                               HASHJOIN(int, 4);
+                               break;
+#ifdef BUN8
+                       case BUN8:
+                               HASHJOIN(int, 8);
+                               break;
+#endif
+                       }
+               } else {
+                       /* t == TYPE_lng */
+                       switch (hsh->width) {
+                       case BUN2:
+                               HASHJOIN(lng, 2);
+                               break;
+                       case BUN4:
+                               HASHJOIN(lng, 4);
+                               break;
+#ifdef BUN8
+                       case BUN8:
+                               HASHJOIN(lng, 8);
+                               break;
+#endif
+                       }
+               }
+       } else if (lcand) {
                while (lcand < lcandend) {
                        lo = *lcand++;
                        if (l->ttype == TYPE_void) {
@@ -2132,7 +2208,7 @@ hashjoin(BAT *r1, BAT *r2, BAT *l, BAT *
                        if (!nil_matches && cmp(v, nil) == 0) {
                                /* no match */
                        } else if (rcand) {
-                               HASHloop_bound(ri, r->T->hash, rb, v, rl, rh) {
+                               HASHloop_bound(ri, hsh, rb, v, rl, rh) {
                                        ro = (oid) (rb - rl + rseq);
                                        if (!binsearchcand(rcand, 0, nrcand, 
ro))
                                                continue;
@@ -2145,7 +2221,7 @@ hashjoin(BAT *r1, BAT *r2, BAT *l, BAT *
                                                break;
                                }
                        } else {
-                               HASHloop_bound(ri, r->T->hash, rb, v, rl, rh) {
+                               HASHloop_bound(ri, hsh, rb, v, rl, rh) {
                                        ro = (oid) (rb - rl + rseq);
                                        if (only_misses) {
                                                nr++;
@@ -2211,8 +2287,6 @@ hashjoin(BAT *r1, BAT *r2, BAT *l, BAT *
                                r1->trevsorted = 0;
                }
        } else {
-               int t = ATOMbasetype(r->ttype);
-
                for (lo = lstart - BUNfirst(l) + l->hseqbase; lstart < lend; 
lo++) {
                        if (l->ttype == TYPE_void) {
                                if (l->tseqbase != oid_nil)
@@ -2224,7 +2298,7 @@ hashjoin(BAT *r1, BAT *r2, BAT *l, BAT *
                        nr = 0;
                        if (rcand) {
                                if (nil_matches || cmp(v, nil) != 0) {
-                                       HASHloop_bound(ri, r->T->hash, rb, v, 
rl, rh) {
+                                       HASHloop_bound(ri, hsh, rb, v, rl, rh) {
                                                ro = (oid) (rb - rl + rseq);
                                                if (!binsearchcand(rcand, 0, 
nrcand, ro))
                                                        continue;
@@ -2241,7 +2315,7 @@ hashjoin(BAT *r1, BAT *r2, BAT *l, BAT *
                                switch (t) {
                                case TYPE_int:
                                        if (nil_matches || *(const int*)v != 
int_nil) {
-                                               HASHloop_bound_TYPE(ri, 
r->T->hash, rb, v, rl, rh, int) {
+                                               HASHloop_bound_TYPE(ri, hsh, 
rb, v, rl, rh, int) {
                                                        ro = (oid) (rb - rl + 
rseq);
                                                        if (only_misses) {
                                                                nr++;
@@ -2255,7 +2329,7 @@ hashjoin(BAT *r1, BAT *r2, BAT *l, BAT *
                                        break;
                                case TYPE_lng:
                                        if (nil_matches || *(const lng*)v != 
lng_nil) {
-                                               HASHloop_bound_TYPE(ri, 
r->T->hash, rb, v, rl, rh, lng) {
+                                               HASHloop_bound_TYPE(ri, hsh, 
rb, v, rl, rh, lng) {
                                                        ro = (oid) (rb - rl + 
rseq);
                                                        if (only_misses) {
                                                                nr++;
@@ -2270,7 +2344,7 @@ hashjoin(BAT *r1, BAT *r2, BAT *l, BAT *
 #ifdef HAVE_HGE
                                case TYPE_hge:
                                        if (nil_matches || *(const hge*)v != 
hge_nil) {
-                                               HASHloop_bound_TYPE(ri, 
r->T->hash, rb, v, rl, rh, hge) {
+                                               HASHloop_bound_TYPE(ri, hsh, 
rb, v, rl, rh, hge) {
                                                        ro = (oid) (rb - rl + 
rseq);
                                                        if (only_misses) {
                                                                nr++;
@@ -2285,7 +2359,7 @@ hashjoin(BAT *r1, BAT *r2, BAT *l, BAT *
 #endif
                                default:
                                        if (nil_matches || cmp(v, nil) != 0) {
-                                               HASHloop_bound(ri, r->T->hash, 
rb, v, rl, rh) {
+                                               HASHloop_bound(ri, hsh, rb, v, 
rl, rh) {
                                                        ro = (oid) (rb - rl + 
rseq);
                                                        if (only_misses) {
                                                                nr++;
diff --git a/gdk/gdk_search.c b/gdk/gdk_search.c
--- a/gdk/gdk_search.c
+++ b/gdk/gdk_search.c
@@ -562,7 +562,7 @@ BAThash(BAT *b, BUN masksize)
  * routine HASHprobe.
  */
 BUN
-HASHprobe(Hash *h, const void *v)
+HASHprobe(const Hash *h, const void *v)
 {
        switch (ATOMbasetype(h->type)) {
        case TYPE_bte:
diff --git a/gdk/gdk_search.h b/gdk/gdk_search.h
--- a/gdk/gdk_search.h
+++ b/gdk/gdk_search.h
@@ -19,7 +19,7 @@
  * with integer anding. The new implementation reflects this.
  */
 gdk_export void HASHdestroy(BAT *b);
-gdk_export BUN HASHprobe(Hash *h, const void *v);
+gdk_export BUN HASHprobe(const Hash *h, const void *v);
 gdk_export BUN HASHlist(Hash *h, BUN i);
 
 
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to