Fix orderbook speed issues

This commit is contained in:
Philippe Maes 2020-09-22 16:14:51 +02:00
parent c81e6a3239
commit af2d28e805
3 changed files with 31 additions and 34 deletions

View File

@ -52,9 +52,7 @@ export default function Orderbook({ smallScreen, depth = 7, onPrice, onSize }) {
const currentOrderbookData = useRef(null); const currentOrderbookData = useRef(null);
const lastOrderbookData = useRef(null); const lastOrderbookData = useRef(null);
const [asksToDisplay, setAsksToDisplay] = useState([]); const [orderbookData, setOrderbookData] = useState(null);
const [bidsToDisplay, setBidsToDisplay] = useState([]);
const [totalSize, setTotalSize] = useState(0);
useInterval(() => { useInterval(() => {
if ( if (
@ -65,24 +63,19 @@ export default function Orderbook({ smallScreen, depth = 7, onPrice, onSize }) {
let bids = orderbook?.bids || []; let bids = orderbook?.bids || [];
let asks = orderbook?.asks || []; let asks = orderbook?.asks || [];
let [asksToDisplay, totalAskSize] = getCumulativeOrderbookSide( let sum = (total, [, size], index) =>
asks, index < depth ? total + size : total;
true, let totalSize = bids.reduce(sum, 0) + asks.reduce(sum, 0);
);
let [bidsToDisplay, totalBidSize] = getCumulativeOrderbookSide(
bids,
false,
);
let totalSize = totalAskSize + totalBidSize;
setAsksToDisplay(asksToDisplay); let bidsToDisplay = getCumulativeOrderbookSide(bids, totalSize, false);
setBidsToDisplay(bidsToDisplay); let asksToDisplay = getCumulativeOrderbookSide(asks, totalSize, true);
setTotalSize(totalSize);
currentOrderbookData.current = { currentOrderbookData.current = {
bids: orderbook?.bids, bids: orderbook?.bids,
asks: orderbook?.asks, asks: orderbook?.asks,
}; };
setOrderbookData({ bids: bidsToDisplay, asks: asksToDisplay });
} }
}, 250); }, 250);
@ -93,23 +86,23 @@ export default function Orderbook({ smallScreen, depth = 7, onPrice, onSize }) {
}; };
}, [orderbook]); }, [orderbook]);
function getCumulativeOrderbookSide(orders, backwards = false) { function getCumulativeOrderbookSide(orders, totalSize, backwards = false) {
let cumulative = orders let cumulative = orders
.slice(0, depth) .slice(0, depth)
.reduce((cumulative, [price, size], i) => { .reduce((cumulative, [price, size], i) => {
const cumulativeSize = (cumulative[i - 1]?.cumulativeSize || 0) + size;
cumulative.push({ cumulative.push({
price, price,
size, size,
cumulativeSize: (cumulative[i - 1]?.cumulativeSize || 0) + size, cumulativeSize,
sizePercent: Math.round((cumulativeSize / (totalSize || 1)) * 100),
}); });
return cumulative; return cumulative;
}, []); }, []);
if (backwards) { if (backwards) {
cumulative = cumulative.reverse(); cumulative = cumulative.reverse();
} }
let totalSize = return cumulative;
cumulative[backwards ? 0 : cumulative.length - 1]?.cumulativeSize || 0;
return [cumulative, totalSize];
} }
return ( return (
@ -127,27 +120,27 @@ export default function Orderbook({ smallScreen, depth = 7, onPrice, onSize }) {
Price ({quoteCurrency}) Price ({quoteCurrency})
</Col> </Col>
</SizeTitle> </SizeTitle>
{asksToDisplay.map(({ price, size, cumulativeSize }) => ( {orderbookData?.asks.map(({ price, size, sizePercent }) => (
<OrderbookRow <OrderbookRow
key={price + ''} key={price + ''}
price={price} price={price}
size={size} size={size}
side={'sell'} side={'sell'}
sizePercent={(cumulativeSize / (totalSize || 1)) * 100} sizePercent={sizePercent}
onSizeClick={() => onSize(size)}
onPriceClick={() => onPrice(price)} onPriceClick={() => onPrice(price)}
onSizeClick={() => onSize(size)}
/> />
))} ))}
<MarkPriceComponent markPrice={markPrice} /> <MarkPriceComponent markPrice={markPrice} />
{bidsToDisplay.map(({ price, size, cumulativeSize }) => ( {orderbookData?.bids.map(({ price, size, sizePercent }) => (
<OrderbookRow <OrderbookRow
key={price + ''} key={price + ''}
price={price} price={price}
size={size} size={size}
side={'buy'} side={'buy'}
sizePercent={(cumulativeSize / (totalSize || 1)) * 100} sizePercent={sizePercent}
onSizeClick={() => onSize(size)}
onPriceClick={() => onPrice(price)} onPriceClick={() => onPrice(price)}
onSizeClick={() => onSize(size)}
/> />
))} ))}
</FloatingElement> </FloatingElement>
@ -168,7 +161,7 @@ const OrderbookRow = React.memo(
() => () =>
element.current?.classList.contains('flash') && element.current?.classList.contains('flash') &&
element.current?.classList.remove('flash'), element.current?.classList.remove('flash'),
500, 250,
); );
}, [price, size]); }, [price, size]);
@ -202,7 +195,7 @@ const OrderbookRow = React.memo(
); );
}, },
(prevProps, nextProps) => (prevProps, nextProps) =>
isEqual(prevProps, nextProps, ['side', 'price', 'size', 'sizePercent']), isEqual(prevProps, nextProps, ['price', 'size', 'sizePercent']),
); );
const MarkPriceComponent = React.memo( const MarkPriceComponent = React.memo(

View File

@ -77,7 +77,7 @@ export default function TradeForm({ style, setChangeOrderRef }) {
}, [setChangeOrderRef]); }, [setChangeOrderRef]);
useEffect(() => { useEffect(() => {
onSliderChange(sizeFraction); baseSize && price && onSliderChange(sizeFraction);
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [side]); }, [side]);
@ -221,7 +221,7 @@ export default function TradeForm({ style, setChangeOrderRef }) {
style={{ textAlign: 'right', paddingBottom: 8 }} style={{ textAlign: 'right', paddingBottom: 8 }}
addonBefore={<div style={{ width: '30px' }}>Price</div>} addonBefore={<div style={{ width: '30px' }}>Price</div>}
suffix={ suffix={
<span style={{ fontSize: 10, opacity: 0.5 }}>{baseCurrency}</span> <span style={{ fontSize: 10, opacity: 0.5 }}>{quoteCurrency}</span>
} }
value={price} value={price}
type="number" type="number"

View File

@ -58,10 +58,14 @@ export default function TradePage() {
const width = dimensions?.width; const width = dimensions?.width;
const componentProps = { const componentProps = {
onChangeOrderRef: (ref) => (changeOrderRef.current = ref), onChangeOrderRef: (ref) => (changeOrderRef.current = ref),
onPrice: (price) => onPrice: useCallback(
changeOrderRef.current && changeOrderRef.current({ price }), (price) => changeOrderRef.current && changeOrderRef.current({ price }),
onSize: (size) => [],
changeOrderRef.current && changeOrderRef.current({ size }), ),
onSize: useCallback(
(size) => changeOrderRef.current && changeOrderRef.current({ size }),
[],
),
}; };
const getComponent = useCallback(() => { const getComponent = useCallback(() => {
if (handleDeprecated) { if (handleDeprecated) {