Is startsWith Faster Than RegExp?
Tags: webdev, javascript, programming
Published: 2023-07-04 15:17:21

Today when writing conditional statements, I used String startsWith because I believed it would be the fastest way. Let me prove it!

### Test

> Device Information:
>
> - AMD Ryzen 5 5600X 6-Core Processor 3.70 GHz
> - 16.0 GB
> - node v18.12.1

```js
const loopTimes = 10 ** 2

console.log('loop times:', loopTimes)
for (let j = 0; j < 10; j++) {
	{
		console.time('startsWith')

		for (let i = 0; i < loopTimes; i++) {
			'Performance-Comparison-Regular-Expression-vs-StartsWith'.startsWith('Performance-Compa')
		}

		console.timeEnd('startsWith')
	}

	{
		console.time('reg')

		for (let i = 0; i < loopTimes; i++) {
			;/^Performance-Compa/.test('Performance-Comparison-Regular-Expression-vs-StartsWith')
		}

		console.timeEnd('reg')
	}
}
```
### Loop 10 \*\* 2 times

output:

```bash
$ node startsWith.js
loop times: 100
startsWith: 0.062ms
reg: 0.074ms
startsWith: 0.006ms
reg: 0.01ms
startsWith: 0.005ms
reg: 0.012ms
startsWith: 0.005ms
reg: 0.008ms
startsWith: 0.005ms
reg: 0.016ms
startsWith: 0.004ms
reg: 0.008ms
startsWith: 0.004ms
reg: 0.009ms
startsWith: 0.004ms
reg: 0.009ms
startsWith: 0.004ms
reg: 0.006ms
startsWith: 0.004ms
reg: 0.006ms
```

### Loop 10 \*\* 3 times

```bash
$ node startsWith.js
loop times: 1000
startsWith: 0.086ms
reg: 0.148ms
startsWith: 0.033ms
reg: 0.08ms
startsWith: 0.113ms
reg: 0.077ms
startsWith: 0.048ms
reg: 0.063ms
startsWith: 0.032ms
reg: 0.072ms
startsWith: 0.027ms
reg: 0.065ms
startsWith: 0.03ms
reg: 0.065ms
startsWith: 0.026ms
reg: 0.065ms
startsWith: 0.03ms
reg: 0.062ms
startsWith: 0.036ms
reg: 0.459ms
```

### Loop 10 \*\* 4 times

```bash
$ node startsWith.js
loop times: 10000
startsWith: 0.393ms
reg: 1.562ms
startsWith: 0.241ms
reg: 5.237ms
startsWith: 0.343ms
reg: 0.564ms
startsWith: 0.342ms
reg: 0.153ms
startsWith: 0.342ms
reg: 0.262ms
startsWith: 0.347ms
reg: 0.223ms
startsWith: 0.352ms
reg: 0.152ms
startsWith: 0.341ms
reg: 0.229ms
startsWith: 0.341ms
reg: 0.191ms
startsWith: 0.341ms
reg: 0.227ms
```

### Loop 10 \*\* 5 times

```bash
$ node startsWith.js
loop times: 100000
startsWith: 5.24ms
reg: 4.092ms
startsWith: 6.891ms
reg: 1.875ms
startsWith: 3.795ms
reg: 1.794ms
startsWith: 3.414ms
reg: 1.943ms
startsWith: 3.408ms
reg: 2.265ms
startsWith: 3.472ms
reg: 1.938ms
startsWith: 4.231ms
reg: 1.762ms
startsWith: 3.602ms
reg: 1.791ms
startsWith: 3.639ms
reg: 2.002ms
startsWith: 3.435ms
reg: 1.768ms
```

### Loop 10 \*\* 6 times

```bash
$ node startsWith.js
loop times: 1000000
startsWith: 36.477ms
reg: 20.72ms
startsWith: 39.39ms
reg: 17.669ms
startsWith: 34.748ms
reg: 17.519ms
startsWith: 35.174ms
reg: 17.366ms
startsWith: 35.09ms
reg: 17.527ms
startsWith: 34.822ms
reg: 17.597ms
startsWith: 34.615ms
reg: 17.87ms
startsWith: 35.453ms
reg: 17.855ms
startsWith: 35.786ms
reg: 17.613ms
startsWith: 34.706ms
reg: 17.6ms
```

### Loop 10 \*\* 7 times

```bash
$ node startsWith.js
loop times: 10000000
startsWith: 355.577ms
reg: 180.706ms
startsWith: 354.726ms
reg: 180.558ms
startsWith: 347.955ms
reg: 175.675ms
startsWith: 348.327ms
reg: 174.522ms
startsWith: 346.228ms
reg: 175.619ms
startsWith: 347.943ms
reg: 175.331ms
startsWith: 346.146ms
reg: 177.439ms
startsWith: 349.308ms
reg: 175.06ms
startsWith: 347.434ms
reg: 175.234ms
startsWith: 348.574ms
reg: 175.179ms
```

## Research

Things don't seem to have developed as expected. When the loop is increased to 10**4 times, the situation starts to reverse, and the consumption time of `reg` becomes shorter instead. By the time it reaches 10**7, there is a significant difference.

### Shorter String

Change the code as follows:

```js
'Suni123'.startsWith('Suni')
;/^Suni/.test('Suni123')
```

10 \*\* 7 loops, output

```bash
$ node startsWith.js
loop times: 10000000
startsWith: 94.856ms
reg: 164.667ms
startsWith: 92.53ms
reg: 159.685ms
startsWith: 86.074ms
reg: 158.927ms
startsWith: 84.894ms
reg: 159.14ms
startsWith: 91.335ms
reg: 166.805ms
startsWith: 85.942ms
reg: 159.383ms
startsWith: 84.433ms
reg: 159.253ms
startsWith: 85.166ms
reg: 161.083ms
startsWith: 85.391ms
reg: 158.424ms
startsWith: 85.856ms
reg: 161.31ms
```

At this point, `startsWith` is obviously faster.

### Longer String

```js
'Performance Comparison: Regular Expression vs. StartsWith; Performance Comparison: Regular Expression vs. StartsWith'.startsWith(
	'Performance Comparison: Regular Expression '
)
;/^Performance Comparison: Regular Expression /.test(
	'Performance Comparison: Regular Expression vs. StartsWith; Performance Comparison: Regular Expression vs. StartsWith'
)
```

output

```bash
$ node startsWith.js
loop times: 10000000
startsWith: 892.246ms
reg: 206.517ms
startsWith: 901.182ms
reg: 203.149ms
startsWith: 902.196ms
reg: 202.142ms
startsWith: 897.693ms
reg: 203.393ms
startsWith: 890.596ms
reg: 223.431ms
startsWith: 894.55ms
reg: 204.961ms
startsWith: 896.698ms
reg: 203.099ms
startsWith: 901.242ms
reg: 202.968ms
startsWith: 902.59ms
reg: 202.787ms
startsWith: 909.052ms
reg: 214.305ms
```

### Long String, Short Condition

```js
'Performance Comparison: Regular Expression vs. StartsWith; Performance Comparison: Regular Expression vs. StartsWith'.startsWith(
	'Performance'
)
;/^Performance/.test(
	'Performance Comparison: Regular Expression vs. StartsWith; Performance Comparison: Regular Expression vs. StartsWith'
)
```

```bash
$ node startsWith.js
loop times: 10000000
startsWith: 228.98ms
reg: 173.04ms
startsWith: 234.776ms
reg: 167.778ms
startsWith: 228.642ms
reg: 168.327ms
startsWith: 228.746ms
reg: 174.96ms
startsWith: 228.663ms
reg: 168.228ms
startsWith: 229.287ms
reg: 167.576ms
startsWith: 227.067ms
reg: 168.668ms
startsWith: 228.117ms
reg: 168.955ms
startsWith: 227.062ms
reg: 169.838ms
startsWith: 228.28ms
reg: 168.242ms
```

### Long String, Long Condition

```js
'Performance Comparison: Regular Expression vs. StartsWith; Performance Comparison: Regular Expression vs. StartsWith'.startsWith(
	'Performance Comparison: Regular Expression vs. StartsWith; Performance'
)
;/^Performance Comparison: Regular Expression vs. StartsWith; Performance/.test(
	'Performance Comparison: Regular Expression vs. StartsWith; Performance Comparison: Regular Expression vs. StartsWith'
)
```

```bash
$ node startsWith.js
loop times: 10000000
startsWith: 1.439s
reg: 237.275ms
startsWith: 1.432s
reg: 242.409ms
startsWith: 1.437s
reg: 238.463ms
startsWith: 1.425s
reg: 232.626ms
startsWith: 1.423s
reg: 234.199ms
startsWith: 1.426s
reg: 234.651ms
startsWith: 1.440s
reg: 235.122ms
startsWith: 1.429s
reg: 234.676ms
startsWith: 1.444s
reg: 234.071ms
startsWith: 1.439s
reg: 235.936ms
```

### Reduce the Number of Loops

```js
'Performance Comparison: Regular Expression vs. StartsWith; Performance Comparison: Regular Expression vs. StartsWith'.startsWith(
	'Performance Comparison: Regular Expression vs. StartsWith; Performance'
)
;/^Performance Comparison: Regular Expression vs. StartsWith; Performance/.test(
	'Performance Comparison: Regular Expression vs. StartsWith; Performance Comparison: Regular Expression vs. StartsWith'
)
```

output

```bash
$ node startsWith.js
loop times: 1000
startsWith: 0.114ms
reg: 0.159ms
startsWith: 0.061ms
reg: 0.08ms
startsWith: 0.138ms
reg: 0.064ms
startsWith: 0.056ms
reg: 0.059ms
startsWith: 0.059ms
reg: 0.071ms
startsWith: 0.059ms
reg: 0.064ms
startsWith: 0.058ms
reg: 0.062ms
startsWith: 0.056ms
reg: 0.069ms
startsWith: 0.058ms
reg: 0.062ms
startsWith: 0.143ms
reg: 0.431ms
```

10\*\*4

```bash
$ node startsWith.js
loop times: 10000
startsWith: 0.735ms
reg: 1.016ms
startsWith: 0.674ms
reg: 3.743ms
startsWith: 1.498ms
reg: 0.575ms
startsWith: 1.404ms
reg: 0.211ms
startsWith: 1.408ms
reg: 0.313ms
startsWith: 1.425ms
reg: 0.28ms
startsWith: 1.727ms
reg: 0.337ms
startsWith: 1.724ms
reg: 0.303ms
startsWith: 1.404ms
reg: 0.21ms
startsWith: 1.408ms
reg: 0.282ms
```

### Conclusion

When dealing with short string, it is better to use `startsWith`. For longer string, it is better to use _regular expression_. When handling a long string with a short _condition_, `startsWith` is still a good choice.

In daily development, when the number of operations is less than 10^3, it is better to use `startsWith`. This also improves readability. However, when the number of operations exceeds this magnitude and the _condition string_ is long, using _regular expression_ will have better performance.

## How will the browser behave?

> chrome v114.0.5735.199

![Chrome Console](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e4kf4xvh3eea1hmdi4ca.png)

Essentially the same as Node, it could lead to the same conclusions.

## Other
During this test, I discovered that `console.time` can be used for timing, which is more convenient than using `Date.now` because it doesn't require recording the difference. It's a new discovery, haha ^o^.

`console.clear` can manually clear logs, `console.assert` can assert in the browser, `console.trace` can directly view the call stack, and `console.count` can be used to print the number of updates in a React FC. These are all quite useful.