!1976 提升numeric计算时的性能

Merge pull request !1976 from junhangis/junhangis/performance/numeric_memory
This commit is contained in:
opengauss-bot
2022-08-04 11:27:32 +00:00
committed by Gitee
2 changed files with 57 additions and 39 deletions

View File

@ -144,13 +144,6 @@ static void dump_var(const char* str, NumericVar* var);
#define dump_var(s, v)
#endif
#define digitbuf_alloc(ndigits) ((NumericDigit*)palloc((ndigits) * sizeof(NumericDigit)))
#define digitbuf_free(buf) \
do { \
if ((buf) != NULL) \
pfree_ext(buf); \
} while (0)
#define NUMERIC_CAN_BE_SHORT(scale, weight) \
((scale) <= NUMERIC_SHORT_DSCALE_MAX && (weight) <= NUMERIC_SHORT_WEIGHT_MAX && \
(weight) >= NUMERIC_SHORT_WEIGHT_MIN)
@ -504,7 +497,7 @@ Datum numeric_recv(PG_FUNCTION_ARGS)
ereport(ERROR,
(errcode(ERRCODE_INVALID_BINARY_REPRESENTATION), errmsg("invalid length in external \"numeric\" value")));
alloc_var(&value, len);
init_alloc_var(&value, len);
value.weight = (int16)pq_getmsgint(buf, sizeof(int16));
value.sign = (uint16)pq_getmsgint(buf, sizeof(uint16));
@ -3927,24 +3920,8 @@ static void dump_var(const char* str, NumericVar* var)
*/
static void alloc_var(NumericVar* var, int ndigits)
{
digitbuf_free(var->buf);
var->buf = digitbuf_alloc(ndigits + 1);
var->buf[0] = 0; /* spare digit for rounding */
var->digits = var->buf + 1;
var->ndigits = ndigits;
}
/*
* free_var() -
*
* Return the digit buffer of a variable to the free pool
*/
void free_var(NumericVar* var)
{
digitbuf_free(var->buf);
var->buf = NULL;
var->digits = NULL;
var->sign = NUMERIC_NAN;
digitbuf_free(var);
init_alloc_var(var, ndigits);
}
/*
@ -3955,9 +3932,8 @@ void free_var(NumericVar* var)
*/
static void zero_var(NumericVar* var)
{
digitbuf_free(var->buf);
var->buf = NULL;
var->digits = NULL;
digitbuf_free(var);
quick_init_var(var);
var->ndigits = 0;
var->weight = 0; /* by convention; doesn't really matter */
var->sign = NUMERIC_POS; /* anything but NAN... */
@ -4161,7 +4137,7 @@ void init_var_from_num(Numeric num, NumericVar* dest)
dest->sign = NUMERIC_SIGN(num);
dest->dscale = NUMERIC_DSCALE(num);
dest->digits = NUMERIC_DIGITS(num);
dest->buf = NULL; /* digits array is not palloc'd */
dest->buf = dest->ndb;
}
/*
@ -4181,7 +4157,7 @@ static void set_var_from_var(const NumericVar* value, NumericVar* dest)
newbuf + 1, value->ndigits * sizeof(NumericDigit), value->digits, value->ndigits * sizeof(NumericDigit));
securec_check(rc, "\0", "\0");
}
digitbuf_free(dest->buf);
digitbuf_free(dest);
rc = memmove_s(dest, sizeof(NumericVar), value, sizeof(NumericVar));
securec_check(rc, "\0", "\0");
@ -4431,10 +4407,8 @@ static char* get_str_from_var_sci(NumericVar* var, int rscale)
else
denom_scale = 0;
ret = memset_s(&denominator, sizeof(NumericVar), 0, sizeof(NumericVar));
securec_check(ret, "", "");
ret = memset_s(&significand, sizeof(NumericVar), 0, sizeof(NumericVar));
securec_check(ret, "", "");
init_var(&denominator);
init_var(&significand);
power_var_int(&const_ten, exponent, &denominator, denom_scale);
div_var(var, &denominator, &significand, rscale, true);
@ -6664,7 +6638,7 @@ static void add_abs(NumericVar* var1, NumericVar* var2, NumericVar* result)
Assert(carry == 0); /* else we failed to allow for carry out */
digitbuf_free(result->buf);
digitbuf_free(result);
result->ndigits = res_ndigits;
result->buf = res_buf;
result->digits = res_digits;
@ -6740,7 +6714,7 @@ static void sub_abs(NumericVar* var1, NumericVar* var2, NumericVar* result)
Assert(borrow == 0); /* else caller gave us var1 < var2 */
digitbuf_free(result->buf);
digitbuf_free(result);
result->ndigits = res_ndigits;
result->buf = res_buf;
result->digits = res_digits;

View File

@ -288,6 +288,8 @@ extern int32 get_ndigit_from_numeric(_in_ Numeric num);
* This is feasible because the digit buffer is separate from the variable.
* ----------
*/
#define NUMERIC_LOCAL_NDIG 36 /* number of 'digits' in local digits[] */
#define NUMERIC_LOCAL_NMAX (NUMERIC_LOCAL_NDIG - 2)
typedef struct NumericVar {
int ndigits; /* # of digits in digits[] - can be 0! */
int weight; /* weight of first digit */
@ -295,13 +297,55 @@ typedef struct NumericVar {
int dscale; /* display scale */
NumericDigit* buf; /* start of palloc'd space for digits[] */
NumericDigit* digits; /* base-NBASE digits */
NumericDigit ndb[NUMERIC_LOCAL_NDIG]; /* local space for digits[] */
} NumericVar;
#define init_var(v) MemSetAligned(v, 0, sizeof(NumericVar))
#define quick_init_var(v) \
do { \
(v)->buf = (v)->ndb; \
(v)->digits = NULL; \
} while (0)
#define init_var(v) \
do { \
quick_init_var((v)); \
(v)->ndigits = 0; \
(v)->weight = 0; \
(v)->sign = 0; \
(v)->dscale = 0; \
} while (0)
#define digitbuf_alloc(ndigits) \
((NumericDigit*) palloc((ndigits) * sizeof(NumericDigit)))
#define digitbuf_free(v) \
do { \
if ((v)->buf != (v)->ndb) { \
pfree((v)->buf); \
(v)->buf = (v)->ndb; \
} \
} while (0)
#define free_var(v) digitbuf_free((v));
/*
* Init a var and allocate digit buffer of ndigits digits (plus a spare digit for rounding).
* Called when first using a var.
*/
#define init_alloc_var(v, n) \
do { \
(v)->buf = (v)->ndb; \
(v)->ndigits = (n); \
if ((n) > NUMERIC_LOCAL_NMAX) { \
(v)->buf = digitbuf_alloc((n) + 1); \
} \
(v)->buf[0] = 0; \
(v)->digits = (v)->buf + 1; \
} while (0)
Numeric makeNumeric(NumericVar* var);
extern Numeric make_result(NumericVar *var);
extern void init_var_from_num(Numeric num, NumericVar* dest);
extern void free_var(NumericVar *var);
extern bool numericvar_to_int64(const NumericVar* var, int64* result, bool can_ignore = false);
extern void int64_to_numericvar(int64 val, NumericVar *var);
extern void add_var(NumericVar *var1, NumericVar *var2, NumericVar *result);