conditional dict content prefetching

based on nbSeq.
This commit is contained in:
Yann Collet
2018-09-12 15:35:21 -07:00
parent 5fb5ed3b31
commit 44d3b83bb1
+19 -17
View File
@@ -68,6 +68,9 @@
# include "zstd_legacy.h" # include "zstd_legacy.h"
#endif #endif
static const void* ZSTD_DDictDictContent(const ZSTD_DDict* ddict);
static size_t ZSTD_DDictDictSize(const ZSTD_DDict* ddict);
/*-************************************* /*-*************************************
* Errors * Errors
@@ -148,7 +151,7 @@ struct ZSTD_DCtx_s
/* dictionary */ /* dictionary */
ZSTD_DDict* ddictLocal; ZSTD_DDict* ddictLocal;
const ZSTD_DDict* ddict; const ZSTD_DDict* ddict; /* set by ZSTD_initDStream_usingDDict(), or ZSTD_DCtx_refDDict() */
U32 dictID; U32 dictID;
int ddictIsCold; /* if == 1 : dictionary is "new" for working context, and presumed "cold" (not in cpu cache) */ int ddictIsCold; /* if == 1 : dictionary is "new" for working context, and presumed "cold" (not in cpu cache) */
@@ -993,8 +996,6 @@ size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr,
} }
} }
*nbSeqPtr = nbSeq; *nbSeqPtr = nbSeq;
DEBUGLOG(2, "nbSeqs=%i", nbSeq);
/* FSE table descriptors */ /* FSE table descriptors */
if (ip+4 > iend) return ERROR(srcSize_wrong); /* minimum possible size */ if (ip+4 > iend) return ERROR(srcSize_wrong); /* minimum possible size */
@@ -1034,7 +1035,16 @@ size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr,
ip += mlhSize; ip += mlhSize;
} }
} }
/* prefetch dictionary content */
if (dctx->ddictIsCold) {
size_t const dictSize = (const char*)dctx->prefixStart - (const char*)dctx->virtualStart;
size_t const pSize = MIN(dictSize, (size_t)(64*nbSeq));
const void* const pStart = (const char*)dctx->dictEnd - pSize;
DEBUGLOG(2, "dictSize: %zu ; prefetchSize: %zu", dictSize, pSize);
PREFETCH_AREA(pStart, pSize);
dctx->ddictIsCold = 0; dctx->ddictIsCold = 0;
}
return ip-istart; return ip-istart;
} }
@@ -1911,9 +1921,6 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
return op-ostart; return op-ostart;
} }
static const void* ZSTD_DDictDictContent(const ZSTD_DDict* ddict);
static size_t ZSTD_DDictDictSize(const ZSTD_DDict* ddict);
static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx, static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
void* dst, size_t dstCapacity, void* dst, size_t dstCapacity,
const void* src, size_t srcSize, const void* src, size_t srcSize,
@@ -1922,6 +1929,8 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
{ {
void* const dststart = dst; void* const dststart = dst;
int moreThan1Frame = 0; int moreThan1Frame = 0;
DEBUGLOG(5, "ZSTD_decompressMultiFrame");
assert(dict==NULL || ddict==NULL); /* either dict or ddict set, not both */ assert(dict==NULL || ddict==NULL); /* either dict or ddict set, not both */
if (ddict) { if (ddict) {
@@ -2359,11 +2368,13 @@ struct ZSTD_DDict_s {
static const void* ZSTD_DDictDictContent(const ZSTD_DDict* ddict) static const void* ZSTD_DDictDictContent(const ZSTD_DDict* ddict)
{ {
assert(ddict != NULL);
return ddict->dictContent; return ddict->dictContent;
} }
static size_t ZSTD_DDictDictSize(const ZSTD_DDict* ddict) static size_t ZSTD_DDictDictSize(const ZSTD_DDict* ddict)
{ {
assert(ddict != NULL);
return ddict->dictSize; return ddict->dictSize;
} }
@@ -2372,8 +2383,8 @@ size_t ZSTD_decompressBegin_usingDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)
DEBUGLOG(4, "ZSTD_decompressBegin_usingDDict"); DEBUGLOG(4, "ZSTD_decompressBegin_usingDDict");
assert(dctx != NULL); assert(dctx != NULL);
if (ddict) { if (ddict) {
dctx->ddictIsCold = (dctx->dictID != ddict->dictID); dctx->ddictIsCold = (dctx->dictEnd != (const char*)ddict->dictContent + ddict->dictSize);
DEBUGLOG(4, "DDict is %s", DEBUGLOG(2, "DDict is %s",
dctx->ddictIsCold ? "~cold~" : "hot!"); dctx->ddictIsCold ? "~cold~" : "hot!");
} }
CHECK_F( ZSTD_decompressBegin(dctx) ); CHECK_F( ZSTD_decompressBegin(dctx) );
@@ -2393,15 +2404,6 @@ size_t ZSTD_decompressBegin_usingDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)
dctx->entropy.rep[0] = ddict->entropy.rep[0]; dctx->entropy.rep[0] = ddict->entropy.rep[0];
dctx->entropy.rep[1] = ddict->entropy.rep[1]; dctx->entropy.rep[1] = ddict->entropy.rep[1];
dctx->entropy.rep[2] = ddict->entropy.rep[2]; dctx->entropy.rep[2] = ddict->entropy.rep[2];
/* prefetch dictionary content */
if (dctx->ddictIsCold) {
size_t const dictSize = ddict->dictSize;
size_t const pSize = MIN(dictSize, 2 KB); /* very conservative; would need to know Nb of Copies in dictionary, or frameContentSize as a proxy */
const void* const pStart = (const char*)ddict->dictContent + dictSize - pSize;
PREFETCH_AREA(pStart, pSize);
}
} else { } else {
dctx->litEntropy = 0; dctx->litEntropy = 0;
dctx->fseEntropy = 0; dctx->fseEntropy = 0;