Performance Tips
July 13th, 2018
JavaScript
Big-O notation
f(n)=O(n)
As n→∞, the time ( f(n) ) a function takes takes to execute is bounded above by c⋅n
More Formally f(n)=O(n) means...
f(n)≤c×n
for all n>N
where N is a really big number
and c is some number we choose
Title Text
function sum(arr: number[]) {
let out = 0;
for (const val of arr) {
out += 1;
out += val;
}
return out;
}
What is f(n)?
1 operation
n values in arr
1 operation
1 operation
loops n times
f(n)=2+2n
Time Taken ( f(n) )
n
f(n)=2+2n
f(n)=n
∞
∞
f(n)=6n
f(n)=3+2n2
f(n)=O(n2)
g(n)=3+2n
n
Time Taken ( f(n) )
Title Text
function hasPairWithSum(arr: number[], sum: number) {
for (const a of arr) {
for (const b of arr) {
if (a + b === sum) {
return true;
}
}
}
return false;
}
What is f(n)?
n values in arr
loops n times
What is f(n)?
function hasPairWithSum(arr: number[], sum: number) {
for (const a of arr) {
const need = sum - a;
if (has(arr, need)) {
return true;
}
}
return false;
}
loops n times
?
What is f(n)?
const has1 = (arr, n) => arr.indexOf(n) !== -1;
const has2 = (arr, n) => arr.find(x => n === x);
// assume arr is sorted
const has3 = (arr, n) => {
let low = 0;
let high = arr.length - 1;
while (low < high) {
const mid = Math.floor(low + high);
if (arr[mid] === n) return true;
if (arr[mid] > n) high = mid - 1;
if (arr[mid] < n) low = mid + 1;
}
return false;
};
What is f(n)?
const cache = new WeakMap();
function has4(arr: number[], sum: number) {
if (cache.has(arr)) return cache.get(arr).has(n);
const lookup = new Set(arr);
cache.set(arr, lookup);
return lookup.has(n);
}
Array Methods
- arr.indexOf()
- arr.find()
- arr.map()
- arr.reduce()
- arr.concat()
- arr.shift()
- arr.unshift()
- arr.slice()
Others
- Object.assign
- { ...obj }
- [...arr, ...arr]
arr.reduce((out, val) => {
return { ...out, [val]: true };
}, {});
Memoization
fancy word for caching
Title Text
// 1, 1, 2, 3, 5, 8, 13, ...
function fib(n) {
if (n === 1) return 1;
if (n === 2) return 1;
return fib(n - 1) + fib(n - 2)
}
What is f(n)?
Title Text
// 1, 1, 2, 3, 5, 8, 13, ...
function fibHelper(n) {
if (n === 1) return 1;
if (n === 2) return 1;
return fib(n - 1) + fib(n - 2)
}
const fib = (() => {
const cache = new Map();
return (n) => {
if (cache.has(n)) return cache.get(n);
const a = fibHelper(n - 1);
const b = fibHelper(n - 2);
const result = a + b;
cache.set(n, result);
return result;
};
})();
What is f(n)?
/**
* memoize function using weakmap
*/
export function weakMemoize<K extends object, V>(fn: (key: K) => V) {
const cache = new WeakMap<K, V>();
return (key: K) => {
const cached = cache.get(key);
if (cached) {
return cached;
}
const value = fn(key);
cache.set(key, value);
return value;
};
}
declare function expensive(arr: Task[]): number;
const faster = weakMemoize(expensive);
faster(arr); // -> number;
React
shouldComponentUpdate()
class Task extends React.Component {
shouldComponentUpdate(newProps) {
for (const key in newProps) {
if (newProps[key] !== this.props[key]) {
return true;
}
}
return false;
}
render() {
return (
<div>
...huge amount of stuff
</div>
);
}
}
class Task extends React.PureComponent {
/*
shouldComponentUpdate(newProps) {
for (const key in newProps) {
if (newProps[key] !== this.props[key]) {
return true;
}
}
return false;
}
*/
render() {
return (
<div>
...huge amount of stuff
</div>
);
}
}
class Grid extends React.Component {
render() {
const { resource, children, ids, data, currentSort } = this.props;
return (
<table>
<thead>
<tr>
{React.Children.map(children, (field, index) => (
<DatagridHeaderCell
key={index}
field={field}
currentSort={currentSort}
updateSort={this.updateSort}
/>
))}
</tr>
</thead>
<tbody>
{ids.map(id => (
<tr key={id}>
{React.Children.map(children, (field, index) => (
<DatagridCell
record={data[id]}
key={`${id}-${index}`}
field={field}
resource={resource} />
))}
</tr>
))}
</tbody>
</table>
);
}
}
class Grid extends React.Component {
render() {
const { resource, children, ids, data, currentSort } = this.props;
return (
<table>
<DataGridHead
currentSort={currentSort}
updateSort={this.updateSort}>
{children}
</DataGridHead>
<DataGridBody
ids={ids}
resource={resource}
data={data}>
{children}
</DataGridBody>
</table>
);
}
}
class DataGridBody extends React.PureComponent {
render() {
const { ids, resource, data, children } = this.props;
return (
<tbody>
{ids.map(id => (
<tr key={id}>
{React.Children.map(children, (field, index) => (
<DatagridCell
record={data[id]}
key={`${id}-${index}`}
field={field}
resource={resource} />
))}
</tr>
))}
</tbody>
);
}
}
class DataGridHeader extends React.PureComponent {
render() {
const { currentSort, updateSort, children } = this.props;
return (
<thead>
<tr>
{React.Children.map(children, (field, index) => (
<DatagridHeaderCell
key={index}
field={field}
currentSort={currentSort}
updateSort={updateSort}
/>
))}
</tr>
</thead>
);
}
}
Links
- https://marmelab.com/blog/2017/02/06/react-is-slow-react-is-fast.html#cutting-components-to-optimize-them
- https://medium.com/@joomiguelcunha/react-performance-tips-5fa199a450b2
Performance Tips July 13th, 2018
Performance Tips
By Ben Southgate
Performance Tips
- 659