Skip to content

Commit 391b30a

Browse files
author
Nikita Glukhov
committed
Add generic json cache support and jsonbc key cache
1 parent 8952f1b commit 391b30a

File tree

3 files changed

+148
-3
lines changed

3 files changed

+148
-3
lines changed

src/backend/utils/adt/json_generic.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,13 @@
1616
#include "utils/memutils.h"
1717
#include "utils/builtins.h"
1818

19-
static Json *JsonExpand(Json *tmp, Datum value, bool freeValue,
20-
JsonContainerOps *ops, CompressionOptions options);
2119

20+
JsonCacheContext JsonCache;
2221
JsonContainerOps jsonvContainerOps;
2322

23+
static Json *JsonExpand(Json *tmp, Datum value, bool freeValue,
24+
JsonContainerOps *ops, CompressionOptions options);
25+
2426
JsonValue *
2527
JsonValueCopy(JsonValue *res, const JsonValue *val)
2628
{

src/backend/utils/adt/jsonbc_util.c

Lines changed: 81 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,17 +120,97 @@ typedef struct JsonbcPair
120120
static JEntry jsonbcEncodeValue(StringInfo buffer, const JsonbValue *val,
121121
int level, JsonbcDictId dict);
122122

123+
typedef struct JsonbcKeyCacheEntry
124+
{
125+
char *key;
126+
int len;
127+
JsonbcDictId dict;
128+
JsonbcKeyId id;
129+
} JsonbcKeyCacheEntry;
130+
131+
#define JSONBC_KEY_CACHE_ENTRIES 4
132+
133+
typedef struct JsonbcKeyCache
134+
{
135+
JsonbcKeyCacheEntry entries[JSONBC_KEY_CACHE_ENTRIES];
136+
int lastEntry;
137+
} JsonbcKeyCache;
138+
139+
static inline JsonbcKeyCache *
140+
jsonbcKeyCacheGet()
141+
{
142+
return JsonCacheGet(1 /* FIXME */, sizeof(JsonbcKeyCache));
143+
}
144+
145+
static inline JsonbcKeyCacheEntry *
146+
jsonbcKeyCacheGetIdByName(JsonbcDictId dict, JsonbcKeyName keyName)
147+
{
148+
JsonbcKeyCache *cache = jsonbcKeyCacheGet();
149+
int i;
150+
151+
if (!cache)
152+
return NULL;
153+
154+
for (i = 0; i < JSONBC_KEY_CACHE_ENTRIES; i++)
155+
{
156+
JsonbcKeyCacheEntry *entry = &cache->entries[i];
157+
158+
if (!entry->dict)
159+
break;
160+
161+
if (entry->dict == dict &&
162+
entry->key[0] == keyName.s[0] &&
163+
entry->len == keyName.len &&
164+
!memcmp(entry->key, keyName.s, entry->len))
165+
return entry;
166+
}
167+
168+
return NULL;
169+
}
170+
171+
static inline void
172+
jsonbcKeyCacheAdd(JsonbcDictId dict, JsonbcKeyName key, JsonbcKeyId id)
173+
{
174+
JsonbcKeyCache *cache = jsonbcKeyCacheGet();
175+
JsonbcKeyCacheEntry *entry;
176+
177+
if (!cache)
178+
return;
179+
180+
entry = &cache->entries[cache->lastEntry];
181+
182+
if (entry->key)
183+
pfree(entry->key);
184+
185+
entry->key = MemoryContextAlloc(JsonCache.mcxt, key.len);
186+
memcpy(entry->key, key.s, key.len);
187+
entry->len = key.len;
188+
entry->dict = dict;
189+
entry->id = id;
190+
191+
cache->lastEntry = (cache->lastEntry + 1) & (JSONBC_KEY_CACHE_ENTRIES - 1);
192+
}
193+
123194
static JsonbcKeyId
124195
jsonbcConvertKeyNameToId(JsonbcDictId dict, const JsonValue *string,
125196
bool insert)
126197
{
127198
JsonbcKeyName keyName;
128199
JsonbcKeyId keyId;
200+
JsonbcKeyCacheEntry *entry;
129201

130202
keyName.s = string->val.string.val;
131203
keyName.len = string->val.string.len;
132204

133-
keyId = jsonbcDictGetIdByName(dict, keyName, insert);
205+
entry = jsonbcKeyCacheGetIdByName(dict, keyName);
206+
207+
if (entry)
208+
keyId = entry->id;
209+
else
210+
{
211+
keyId = jsonbcDictGetIdByName(dict, keyName, insert);
212+
jsonbcKeyCacheAdd(dict, keyName, keyId);
213+
}
134214

135215
if (insert && keyId == JsonbcInvalidKeyId)
136216
elog(ERROR, "could not insert key \"%.*s\" into jsonbc dictionary",

src/include/utils/json_generic.h

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -548,4 +548,67 @@ extern void JsonbEncode(StringInfo, const JsonValue *, CompressionOptions);
548548

549549
extern int lengthCompareJsonbStringValue(const void *a, const void *b);
550550

551+
typedef struct JsonCacheData
552+
{
553+
int id;
554+
char data[FLEXIBLE_ARRAY_MEMBER];
555+
} JsonCacheData;
556+
557+
typedef struct JsonCacheContext
558+
{
559+
JsonCacheData **data;
560+
MemoryContext mcxt;
561+
} JsonCacheContext;
562+
563+
extern PGDLLIMPORT JsonCacheContext JsonCache;
564+
565+
static inline JsonCacheContext
566+
JsonCacheSwitchTo(JsonCacheContext newcxt)
567+
{
568+
JsonCacheContext oldcxt = JsonCache;
569+
JsonCache = newcxt;
570+
return oldcxt;
571+
}
572+
573+
static inline JsonCacheContext
574+
JsonCacheSwitchTo2(void **data, MemoryContext mcxt)
575+
{
576+
JsonCacheContext oldcxt = JsonCache;
577+
578+
JsonCache.data = (JsonCacheData **) data;
579+
JsonCache.mcxt = mcxt;
580+
581+
return oldcxt;
582+
}
583+
584+
static inline JsonCacheContext
585+
JsonCacheSwitchToFunc(FunctionCallInfo fcinfo)
586+
{
587+
JsonCacheContext newcxt = {
588+
fcinfo->flinfo ? (JsonCacheData **) &fcinfo->flinfo->fn_extra : NULL,
589+
fcinfo->flinfo ? fcinfo->flinfo->fn_mcxt : NULL
590+
};
591+
return JsonCacheSwitchTo(newcxt);
592+
}
593+
594+
static inline void *
595+
JsonCacheGet(int id, size_t size)
596+
{
597+
JsonCacheContext *cache = &JsonCache;
598+
599+
if (!cache->mcxt || !cache->data)
600+
return NULL;
601+
602+
if (!*cache->data || (*cache->data)->id != id)
603+
{
604+
if (*cache->data)
605+
pfree(*cache->data);
606+
*cache->data = MemoryContextAllocZero(cache->mcxt,
607+
offsetof(JsonCacheData, data) + size);
608+
(*cache->data)->id = id;
609+
}
610+
611+
return (void *)(*cache->data)->data;
612+
}
613+
551614
#endif /* UTILS_JSON_GENERIC_H */

0 commit comments

Comments
 (0)