!1976 提升numeric计算时的性能
Merge pull request !1976 from junhangis/junhangis/performance/numeric_memory
This commit is contained in:
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
Reference in New Issue
Block a user