Skip to content

Commit aff0bbc

Browse files
feat(perf): HFT memory array & compiler optimizations
1 parent 51566cf commit aff0bbc

4 files changed

Lines changed: 49 additions & 24 deletions

File tree

.github/workflows/pipeline.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ jobs:
1717
languages: cpp
1818

1919
- run: |
20-
g++ -o engine_test main.cpp
20+
g++ -O3 -march=native -flto -o engine_test main.cpp
2121
./engine_test --test
2222
2323
- uses: github/codeql-action/analyze@v3

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@ FROM ubuntu:22.04
22
RUN apt-get update && apt-get install -y g++
33
WORKDIR /app
44
COPY main.cpp .
5-
RUN g++ -o engine main.cpp
5+
RUN g++ -O3 -march=native -flto -o engine main.cpp
66
USER 1001
77
CMD ["./engine"]

engine_test.exe

131 KB
Binary file not shown.

main.cpp

Lines changed: 47 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,74 @@
11
#include <iostream>
2-
#include <queue>
32
#include <vector>
43
#include <cassert>
54
#include <thread>
65
#include <chrono>
76
#include <string>
7+
#include <cstdint>
8+
#include <algorithm>
89

9-
struct Order {
10+
// Phase 4: Cache Line Optimization
11+
// 64-byte alignment and tightly packed variables.
12+
// Fits perfectly into L1 cache lines.
13+
struct alignas(64) Order {
1014
double price;
11-
int quantity;
15+
uint32_t quantity;
1216
bool is_buy;
1317
};
1418

15-
struct CompareBuy {
16-
bool operator()(const Order& a, const Order& b) { return a.price < b.price; }
19+
// Phase 4 & Phase 2: Align arrays to cache lines
20+
struct alignas(64) LevelData {
21+
uint32_t buy_quantity = 0;
22+
uint32_t sell_quantity = 0;
1723
};
1824

19-
struct CompareSell {
20-
bool operator()(const Order& a, const Order& b) { return a.price > b.price; }
21-
};
25+
// Phase 2 & 3: O(1) Array with Pre-allocated Memory
26+
constexpr size_t MAX_PRICE_LEVELS = 1000000;
2227

2328
class OrderBook {
24-
std::priority_queue<Order, std::vector<Order>, CompareBuy> buys;
25-
std::priority_queue<Order, std::vector<Order>, CompareSell> sells;
26-
int trades_executed = 0;
29+
// Phase 2: Reserving this once keeps dynamic allocations OUT of the trading path
30+
std::vector<LevelData> book;
31+
uint32_t trades_executed = 0;
32+
33+
int max_buy_price = 0;
34+
int min_sell_price = static_cast<int>(MAX_PRICE_LEVELS);
2735

2836
public:
37+
OrderBook() {
38+
book.resize(MAX_PRICE_LEVELS);
39+
}
40+
2941
void addOrder(const Order& order) {
30-
if (order.is_buy) buys.push(order);
31-
else sells.push(order);
42+
// Phase 3: Array Index represents price level (O(1) access)
43+
int price_index = static_cast<int>(order.price * 100);
44+
45+
if (order.is_buy) {
46+
book[price_index].buy_quantity += order.quantity;
47+
if (price_index > max_buy_price) max_buy_price = price_index;
48+
} else {
49+
book[price_index].sell_quantity += order.quantity;
50+
if (price_index < min_sell_price) min_sell_price = price_index;
51+
}
3252
match();
3353
}
3454

3555
void match() {
36-
while (!buys.empty() && !sells.empty() && buys.top().price >= sells.top().price) {
37-
Order b = buys.top(); buys.pop();
38-
Order s = sells.top(); sells.pop();
39-
int traded = std::min(b.quantity, s.quantity);
56+
while (max_buy_price >= min_sell_price) {
57+
while (max_buy_price >= 0 && book[max_buy_price].buy_quantity == 0) {
58+
max_buy_price--;
59+
}
60+
while (min_sell_price < static_cast<int>(MAX_PRICE_LEVELS) && book[min_sell_price].sell_quantity == 0) {
61+
min_sell_price++;
62+
}
63+
64+
if (max_buy_price < min_sell_price || max_buy_price < 0 || min_sell_price >= static_cast<int>(MAX_PRICE_LEVELS)) {
65+
break;
66+
}
4067

41-
b.quantity -= traded;
42-
s.quantity -= traded;
68+
uint32_t traded = std::min(book[max_buy_price].buy_quantity, book[min_sell_price].sell_quantity);
69+
book[max_buy_price].buy_quantity -= traded;
70+
book[min_sell_price].sell_quantity -= traded;
4371
trades_executed++;
44-
45-
if (b.quantity > 0) buys.push(b);
46-
if (s.quantity > 0) sells.push(s);
4772
}
4873
}
4974

0 commit comments

Comments
 (0)