Changeset: 97b4c0bd5bc2 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/97b4c0bd5bc2
Modified Files:
gdk/gdk_hash.c
gdk/gdk_join.c
gdk/gdk_private.h
gdk/gdk_string.c
Branch: ustr
Log Message:
Try to do less double work when inserting into a ustr column.
diffs (truncated from 355 to 300 lines):
diff --git a/gdk/gdk_hash.c b/gdk/gdk_hash.c
--- a/gdk/gdk_hash.c
+++ b/gdk/gdk_hash.c
@@ -732,7 +732,7 @@ BAThashsave(BAT *b, bool dosync)
* values in the tvheap that they point to. */
Hash *
BAThash_impl(BATiter *restrict bi, struct canditer *restrict ci,
- bool offsets, const char *restrict ext)
+ bool offsets, const char *restrict ext, uint8_t width)
{
BAT *b = bi->b;
lng t0 = 0;
@@ -752,6 +752,7 @@ BAThash_impl(BATiter *restrict bi, struc
assert(strcmp(ext, "thash") != 0 || !hascand);
assert(bi->type != TYPE_msk);
assert(bi->type != TYPE_void);
+ assert((width & (width - 1)) == 0 && (size_t) width <= sizeof(var_t));
MT_thread_setalgorithm(hascand ? "create hash with candidates" :
"create hash");
TRC_DEBUG_IF(ACCELERATOR) t0 = GDKusec();
@@ -764,7 +765,7 @@ BAThash_impl(BATiter *restrict bi, struc
GDKfree(h);
return NULL;
}
- h->width = HASHwidth(BATcapacity(b));
+ h->width = width <= 1 ? HASHwidth(BATcapacity(b)) : width;
h->offsets = offsets;
h->heaplink.dirty = true;
h->heapbckt.dirty = true;
@@ -1099,7 +1100,7 @@ BAThash(BAT *b)
struct canditer ci;
BATiter bi = bat_iterator(b);;
canditer_init(&ci, b, NULL);
- b->thash = BAThash_impl(&bi, &ci, b->ustr != 0, "thash");
+ b->thash = BAThash_impl(&bi, &ci, b->ustr != 0, "thash", 0);
bat_iterator_end(&bi);
if (b->thash == NULL) {
MT_rwlock_wrunlock(&b->thashlock);
@@ -1155,7 +1156,7 @@ HASHprobe(const Hash *h, const void *v)
}
void
-HASHappend_locked(BATiter *bi, BUN i, const void *v)
+HASHappend_locked_hashval(BATiter *bi, BUN i, const void *v, BUN hsh)
{
BAT *b = bi->b;
Hash *h = b->thash;
@@ -1200,34 +1201,56 @@ HASHappend_locked(BATiter *bi, BUN i, co
return;
}
h->Link = h->heaplink.base;
- BUN c = HASHprobe(h, v);
+ BUN c = HASHbucket(h, hsh);
h->heaplink.free += h->width;
BUN hb = HASHget(h, c);
- BUN hb2;
- if (h->offsets) {
- for (hb2 = hb;
- hb2 != BUN_NONE;
- hb2 = HASHgetlink(h, hb2)) {
- if (*(var_t *) v == VarHeapVal(bi->base, hb2,
bi->width))
- break;
+ if (!b->tvkey) {
+ BUN hb2;
+ if (h->offsets) {
+ for (hb2 = hb;
+ hb2 != BUN_NONE;
+ hb2 = HASHgetlink(h, hb2)) {
+ if (*(var_t *) v == VarHeapVal(bi->base, hb2,
bi->width))
+ break;
+ }
+ } else {
+ bool (*atomeq)(const void *, const void *) =
ATOMequal(h->type);
+ for (hb2 = hb;
+ hb2 != BUN_NONE;
+ hb2 = HASHgetlink(h, hb2)) {
+ if (atomeq(v, BUNtail(bi, hb2)))
+ break;
+ }
}
+ h->nunique += hb2 == BUN_NONE;
} else {
- bool (*atomeq)(const void *, const void *) = ATOMequal(h->type);
- for (hb2 = hb;
- hb2 != BUN_NONE;
- hb2 = HASHgetlink(h, hb2)) {
- if (atomeq(v, BUNtail(bi, hb2)))
- break;
- }
+ h->nunique++;
}
h->nheads += hb == BUN_NONE;
- h->nunique += hb2 == BUN_NONE;
HASHputlink(h, i, hb);
HASHput(h, c, i);
h->heapbckt.dirty = true;
h->heaplink.dirty = true;
}
+void
+HASHappend_locked(BATiter *bi, BUN i, const void *v)
+{
+ BAT *b = bi->b;
+ Hash *h = b->thash;
+ if (h == NULL) {
+ return;
+ }
+ if (h == (Hash *) 1) {
+ b->thash = NULL;
+ doHASHdestroy(b, h);
+ GDKclrerr();
+ return;
+ }
+ BUN hsh = ATOMhash(h->type, v);
+ HASHappend_locked_hashval(bi, i, v, hsh);
+}
+
BUN
HASHappend(BAT *b, BUN i, const void *v)
{
diff --git a/gdk/gdk_join.c b/gdk/gdk_join.c
--- a/gdk/gdk_join.c
+++ b/gdk/gdk_join.c
@@ -2818,7 +2818,7 @@ vkeyjoin(BAT **r1p, BAT **r2p, BAT **r3p
(unsigned) MT_getpid()) >= (int) sizeof(ext))
return GDK_FAIL;
BATiter ri = bat_iterator(r);
- hsh = BAThash_impl(&ri, rci, true, ext);
+ hsh = BAThash_impl(&ri, rci, true, ext, 0);
bat_iterator_end(&ri);
if (hsh == NULL)
return GDK_FAIL;
@@ -3252,7 +3252,7 @@ hashjoin(BAT **r1p, BAT **r2p, BAT **r3p
(unsigned) MT_getpid()) >= (int) sizeof(ext))
goto bailout;
BATiter ri = bat_iterator(r);
- hsh = BAThash_impl(&ri, rci, false, ext);
+ hsh = BAThash_impl(&ri, rci, false, ext, 0);
bat_iterator_end(&ri);
if (hsh == NULL)
goto bailout;
diff --git a/gdk/gdk_private.h b/gdk/gdk_private.h
--- a/gdk/gdk_private.h
+++ b/gdk/gdk_private.h
@@ -59,7 +59,7 @@ void BATfree(BAT *b)
gdk_return BATgroup_internal(BAT **groups, BAT **extents, BAT **histo, BAT *b,
BAT *s, BAT *g, BAT *e, BAT *h, bool subsorted)
__attribute__((__warn_unused_result__))
__attribute__((__visibility__("hidden")));
-Hash *BAThash_impl(BATiter *restrict bi, struct canditer *restrict ci, bool
offsets, const char *restrict ext)
+Hash *BAThash_impl(BATiter *restrict bi, struct canditer *restrict ci, bool
offsets, const char *restrict ext, uint8_t width)
__attribute__((__visibility__("hidden")));
void BAThashsave(BAT *b, bool dosync)
__attribute__((__visibility__("hidden")));
@@ -172,6 +172,8 @@ BUN HASHappend(BAT *b, BUN i, const void
__attribute__((__visibility__("hidden")));
void HASHappend_locked(BATiter *bi, BUN i, const void *v)
__attribute__((__visibility__("hidden")));
+void HASHappend_locked_hashval(BATiter *bi, BUN i, const void *v, BUN hsh)
+ __attribute__((__visibility__("hidden")));
void HASHfree(BAT *b)
__attribute__((__visibility__("hidden")));
BUN HASHdelete(BATiter *bi, BUN p, const void *v)
diff --git a/gdk/gdk_string.c b/gdk/gdk_string.c
--- a/gdk/gdk_string.c
+++ b/gdk/gdk_string.c
@@ -189,7 +189,10 @@ ustrPut(BAT *b, var_t *dst, const char *
MT_rwlock_wrlock(&ustrbat->thashlock);
MT_lock_set(&ustrbat->theaplock);
assert(ustrbat->tvkey);
+
+ Heap *h = ustrbat->tvheap;
BUN p = BUN_NONE;
+ BUN hsh = strHash(v);
if (ustrbat->batCount != 0) {
BATiter ui = bat_iterator_nolock(ustrbat);
if (ustrbat->thash == NULL) {
@@ -201,15 +204,45 @@ ustrPut(BAT *b, var_t *dst, const char *
.hseq = ustrbat->hseqbase,
.ncand = ustrbat->batCount,
};
- if ((ustrbat->thash = BAThash_impl(&ui, &cui, false,
"thash")) == NULL) {
+ if ((ustrbat->thash = BAThash_impl(
+ &ui, &cui, false, "thash",
+ sizeof(var_t))) == NULL) {
MT_lock_unset(&ustrbat->theaplock);
MT_rwlock_wrunlock(&ustrbat->thashlock);
return (var_t) -1;
}
}
- HASHloop_str(&ui, ustrbat->thash, p, v)
- break;
+ for (p = HASHget(ustrbat->thash,
+ HASHbucket(ustrbat->thash, hsh));
+ p != BUN_NONE;
+ p = HASHgetlink(ustrbat->thash, p))
+ if (strcmp(v,
+ ui.vh->base + ((var_t *) ui.base)[p]) == 0)
+ break;
+#if SIZEOF_VAR_T == 8
+ } else if (GDKupgradevarheap(ustrbat, (var_t) 1 << 33,
+ ustrbat->batCapacity, 0) != GDK_SUCCEED) {
+ MT_lock_unset(&ustrbat->theaplock);
+ MT_rwlock_wrunlock(&ustrbat->thashlock);
+ return (var_t) -1;
+#endif
+ } else {
+ if (h->size < GDK_STRHASHSIZE + BATTINY * GDK_VARALIGN) {
+ if (HEAPgrow(&b->tvheap, GDK_STRHASHSIZE + BATTINY *
GDK_VARALIGN, true) != GDK_SUCCEED) {
+ return (var_t) -1;
+ }
+ h = b->tvheap;
+ }
+ h->free = GDK_STRHASHSIZE;
+#ifdef NDEBUG
+ memset(h->base, 0, h->free);
+#else
+ /* fill should solve initialization problems within valgrind */
+ memset(h->base, 0, h->size);
+#endif
+ h->dirty = true;
}
+
if (p == BUN_NONE) {
/* string does not yet occur in ustrbat */
p = ustrbat->batCount;
@@ -221,34 +254,107 @@ ustrPut(BAT *b, var_t *dst, const char *
}
ustrbat->batCapacity = (BUN) (ustrbat->theap->size >>
ustrbat->tshift);
}
- if (tfastins_nochecknolockVAR(ustrbat, p, v) != GDK_SUCCEED) {
- MT_lock_unset(&ustrbat->theaplock);
- MT_rwlock_wrunlock(&ustrbat->thashlock);
+
+#ifndef NDEBUG
+ if (!checkUTF8(v)) {
+ GDKerror("incorrectly encoded UTF-8\n");
return (var_t) -1;
}
+#endif
+
+ size_t pad;
+ size_t len = strlen(v) + 1;
+
+ if (GDK_ELIMBASE(h->free) != 0) {
+ /* no extra padding needed when no hash links needed
+ * (but only when padding doesn't cross duplicate
+ * elimination boundary) */
+ pad = 0;
+ } else {
+ pad = GDK_VARALIGN - (h->free & (GDK_VARALIGN - 1));
+ if (GDK_ELIMBASE(h->free + pad) == 0) {
+ /* i.e. h->free+pad < GDK_ELIMLIMIT */
+ if (pad < sizeof(stridx_t)) {
+ /* make room for hash link */
+ pad += GDK_VARALIGN;
+ }
+ }
+ }
+
+ /* check heap for space */
+ if (h->free + pad + len >= h->size) {
+ size_t newsize = MAX(h->size, 4096);
+
+ /* double the heap size until we have enough space */
+ do {
+ if (newsize < 4 * 1024 * 1024)
+ newsize <<= 1;
+ else
+ newsize += 4 * 1024 * 1024;
+ } while (newsize <= h->free + pad + len);
+
+ assert(newsize);
+
+ if (h->free + pad + len >= (size_t) VAR_MAX) {
+ GDKerror("string heap gets larger than %zuGiB.",
+ (size_t) VAR_MAX >> 30);
+ return (var_t) -1;
+ }
+ TRC_DEBUG(HEAP, "HEAPextend in strPut %s %zu %zu\n",
+ h->filename, h->size, newsize);
+ if (HEAPgrow(&ustrbat->tvheap, newsize, true) !=
GDK_SUCCEED)
+ return (var_t) -1;
+ h = ustrbat->tvheap;
+ }
+
+ /* insert string */
+ size_t pos = h->free + pad;
+ if (pad > 0)
+ memset(h->base + h->free, 0, pad);
+ memcpy(h->base + pos, v, len);
+ h->free += pad + len;
+ h->dirty = true;
+ if (ustrbat->tascii) {
+ for (const uint8_t *s = (const uint8_t *) v; *s; s++) {
+ if (*s & 0x80) {
+ ustrbat->tascii = false;
+ b->tascii = false;
+ break;
+ }
+ }
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]