Skip to content

Commit 9bb1803

Browse files
committed
perf: push targetingRuleConditionValuesTypesFromValues down
validSemver is super-slow, so having it on the hot path in evaluateCondition adds a ton of overhead (as in, >50%).
1 parent 0fae041 commit 9bb1803

File tree

1 file changed

+30
-44
lines changed

1 file changed

+30
-44
lines changed

src/rules.ts

Lines changed: 30 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -154,8 +154,6 @@ function evaluateRuleConditions(
154154
function evaluateCondition(subjectAttributes: Record<string, any>, condition: Condition): boolean {
155155
const value = subjectAttributes[condition.attribute];
156156

157-
const conditionValueType = targetingRuleConditionValuesTypesFromValues(condition.value);
158-
159157
if (condition.operator === OperatorType.IS_NULL) {
160158
if (condition.value) {
161159
return value === null || value === undefined;
@@ -166,25 +164,25 @@ function evaluateCondition(subjectAttributes: Record<string, any>, condition: Co
166164
if (value != null) {
167165
switch (condition.operator) {
168166
case OperatorType.GTE:
169-
if (conditionValueType === OperatorValueType.SEM_VER) {
170-
return compareSemVer(value, condition.value, semverGte);
171-
}
172-
return compareNumber(value, condition.value, (a, b) => a >= b);
173167
case OperatorType.GT:
174-
if (conditionValueType === OperatorValueType.SEM_VER) {
175-
return compareSemVer(value, condition.value, semverGt);
176-
}
177-
return compareNumber(value, condition.value, (a, b) => a > b);
178168
case OperatorType.LTE:
179-
if (conditionValueType === OperatorValueType.SEM_VER) {
180-
return compareSemVer(value, condition.value, semverLte);
181-
}
182-
return compareNumber(value, condition.value, (a, b) => a <= b);
183169
case OperatorType.LT:
170+
const conditionValueType = targetingRuleConditionValuesTypesFromValues(condition.value);
184171
if (conditionValueType === OperatorValueType.SEM_VER) {
185-
return compareSemVer(value, condition.value, semverLt);
172+
const comparator =
173+
condition.operator === OperatorType.GTE ? semverGte :
174+
condition.operator === OperatorType.GT ? semverGt :
175+
condition.operator === OperatorType.LTE ? semverLte :
176+
semverLt;
177+
return compareSemVer(value, condition.value, comparator);
186178
}
187-
return compareNumber(value, condition.value, (a, b) => a < b);
179+
180+
const comparator = (a: number, b: number) =>
181+
condition.operator === OperatorType.GTE ? a >= b :
182+
condition.operator === OperatorType.GT ? a > b :
183+
condition.operator === OperatorType.LTE ? a <= b :
184+
a < b;
185+
return compareNumber(value, condition.value, comparator);
188186
case OperatorType.MATCHES:
189187
return new RegExp(condition.value as string).test(value as string);
190188
case OperatorType.NOT_MATCHES:
@@ -203,7 +201,6 @@ function evaluateObfuscatedCondition(
203201
condition: Condition,
204202
): boolean {
205203
const value = hashedSubjectAttributes[condition.attribute];
206-
const conditionValueType = targetingRuleConditionValuesTypesFromValues(value);
207204

208205
if (condition.operator === ObfuscatedOperatorType.IS_NULL) {
209206
if (condition.value === getMD5Hash('true')) {
@@ -215,40 +212,29 @@ function evaluateObfuscatedCondition(
215212
if (value != null) {
216213
switch (condition.operator) {
217214
case ObfuscatedOperatorType.GTE:
218-
if (conditionValueType === OperatorValueType.SEM_VER) {
219-
return compareSemVer(value, decodeBase64(condition.value as string), semverGte);
220-
}
221-
return compareNumber(
222-
value,
223-
Number(decodeBase64(condition.value as string)),
224-
(a, b) => a >= b,
225-
);
226215
case ObfuscatedOperatorType.GT:
227-
if (conditionValueType === OperatorValueType.SEM_VER) {
228-
return compareSemVer(value, decodeBase64(condition.value as string), semverGt);
229-
}
230-
return compareNumber(
231-
value,
232-
Number(decodeBase64(condition.value as string)),
233-
(a, b) => a > b,
234-
);
235216
case ObfuscatedOperatorType.LTE:
236-
if (conditionValueType === OperatorValueType.SEM_VER) {
237-
return compareSemVer(value, decodeBase64(condition.value as string), semverLte);
238-
}
239-
return compareNumber(
240-
value,
241-
Number(decodeBase64(condition.value as string)),
242-
(a, b) => a <= b,
243-
);
244217
case ObfuscatedOperatorType.LT:
218+
const conditionValue = decodeBase64(condition.value);
219+
const conditionValueType = targetingRuleConditionValuesTypesFromValues(conditionValue);
245220
if (conditionValueType === OperatorValueType.SEM_VER) {
246-
return compareSemVer(value, decodeBase64(condition.value as string), semverLt);
221+
const comparator =
222+
condition.operator === ObfuscatedOperatorType.GTE ? semverGte :
223+
condition.operator === ObfuscatedOperatorType.GT ? semverGt :
224+
condition.operator === ObfuscatedOperatorType.LTE ? semverLte :
225+
semverLt;
226+
return compareSemVer(value, conditionValue, comparator);
247227
}
228+
229+
const comparator = (a: number, b: number) =>
230+
condition.operator === ObfuscatedOperatorType.GTE ? a >= b :
231+
condition.operator === ObfuscatedOperatorType.GT ? a > b :
232+
condition.operator === ObfuscatedOperatorType.LTE ? a <= b :
233+
a < b;
248234
return compareNumber(
249235
value,
250-
Number(decodeBase64(condition.value as string)),
251-
(a, b) => a < b,
236+
Number(conditionValue),
237+
comparator,
252238
);
253239
case ObfuscatedOperatorType.MATCHES:
254240
return new RegExp(decodeBase64(condition.value as string)).test(value as string);

0 commit comments

Comments
 (0)