fast_able/
stock_pool.rs

1use std::{
2    cell::UnsafeCell,
3    ops::{Index, IndexMut},
4};
5
6/// 设计一个高性能股票池, 数据全部以数组的形式存储, 通过数组的下标来获取数据; 此下标是股票代码转换而来;
7/// 4个数组, 一个存储上海主板股票, 一个存储深圳主板股票, 一个存储创业板股票; 还有一个数组存储科创板股票;
8/// 每个数组的长度是固定的, 都根据A股市场的股票数量来确定; 例如上海主板股票数量是1500, 则数组的长度是1500;
9pub struct StockPool<T> {
10    stock_list: [Vec<UnsafeCell<Option<Box<T>>>>; 10],
11}
12
13impl<T: Default> StockPool<T> {
14
15    #[must_use]
16    pub fn new_default() -> StockPool<T> {
17        let get = || {
18            let mut add_v = Vec::with_capacity(10_0000);
19            for _ in 0..10_0000 {
20                add_v.push(UnsafeCell::new(Some(Box::new(T::default()))));
21            }
22            add_v
23        };
24        StockPool {
25            stock_list: [
26                get(),
27                get(),
28                get(),
29                get(),
30                get(),
31                get(),
32                get(),
33                get(),
34                get(),
35                get(),
36            ],
37        }
38    }
39}
40
41impl<T> StockPool<T> {
42    // 初始化股票池; 调用此方法则必须调用insert方法来插入数据;
43    #[must_use]
44    pub fn new_empty() -> StockPool<T> {
45        let get = || {
46            let mut add_v = Vec::with_capacity(10_0000);
47            for _ in 0..10_0000 {
48                add_v.push(UnsafeCell::new(None));
49            }
50            add_v
51        };
52        StockPool {
53            stock_list: [
54                get(),
55                get(),
56                get(),
57                get(),
58                get(),
59                get(),
60                get(),
61                get(),
62                get(),
63                get(),
64            ],
65        }
66    }
67
68    #[must_use]
69    pub fn len(&self) -> usize {
70        self.all_items().len()
71    }
72
73    #[inline(always)]
74    fn _get<'a>(&'a self, i7: i32) -> &'a mut Option<Box<T>> {
75        // 高性能写法
76        let i7 = i7 as usize;
77        let i6 = i7 % 1_000_000;
78        let i = i6 / 1000_00;
79        let i5 = i6 % 1000_00;
80        let r = &self.stock_list[i]
81            .get(i5)
82            .unwrap_or_else(|| unreachable!("股票代码在股票池中不存在: {i7}({i}-{i5})"));
83        unsafe { &mut *r.get() }
84    }
85
86    pub fn all_items(&self) -> Vec<&T> {
87        let mut items = Vec::new();
88        for ele in self.stock_list.iter() {
89            for ele in ele {
90                if let Some(item) = unsafe { &*ele.get() } {
91                    items.push(item.as_ref());
92                }
93            }
94        }
95
96        items
97    }
98
99    #[inline(always)]
100    pub fn is_empty(&self, i7: i32) -> bool {
101        self._get(i7).is_none()
102    }
103
104    /// 获取股票数据; 股票代码是7位数字, 1开头说明是上海票, 2开头说明是深圳票; 其它6位数与常规股票代码一样;
105    #[inline(always)]
106    pub fn get(&self, i7: i32) -> Option<&T> {
107        self._get(i7).as_ref().map(|x| x.as_ref())
108    }
109
110    #[inline(always)]
111    pub fn get_unchecked(&self, i7: i32) -> &T {
112        self._get(i7)
113            .as_ref()
114            .unwrap_or_else(|| unreachable!("股票数据为空: {i7}"))
115    }
116
117    #[inline(always)]
118    pub fn get_mut(&self, i7: i32) -> Option<&mut T> {
119        self._get(i7).as_mut().map(|x| x.as_mut())
120    }
121
122    #[inline(always)]
123    pub fn insert(&self, i7: i32, val: T) -> Option<Box<T>> {
124        self._get(i7).replace(Box::new(val))
125    }
126
127    #[inline(always)]
128    pub fn remove(&self, i7: i32) -> Option<Box<T>> {
129        self._get(i7).take()
130    }
131}
132
133impl<T: Default> Index<i32> for StockPool<T> {
134    type Output = T;
135    fn index(&self, i7: i32) -> &Self::Output {
136        self.get(i7)
137            .unwrap_or_else(|| unreachable!("股票代码在股票池中不存在: {}", i7))
138    }
139}
140
141impl<T: Default> IndexMut<i32> for StockPool<T> {
142    fn index_mut(&mut self, i7: i32) -> &mut Self::Output {
143        self.get_mut(i7)
144            .unwrap_or_else(|| unreachable!("股票代码在股票池中不存在: {}", i7))
145    }
146}
147
148unsafe impl<T: Sync> Sync for StockPool<T> {}
149unsafe impl<T: Send> Send for StockPool<T> {}
150
151// impl iter
152// impl <T> Iterator for StockPool<T> {
153//     type Item = T;
154//     fn next(&mut self) -> Option<Self::Item> {
155//         todo!()
156//     }
157// }
158
159// impl<T: Default + Debug> IndexMut<i32> for StockPool<T> {
160//     type Output = T;
161//     fn index_mut(&mut self, index: i32) -> &mut Self::Output {
162//         self.get(i7)
163//             .expect(format!("股票代码在股票池中不存在: {}", i7).as_str())
164//     }
165// }
166
167#[test]
168fn test_stock_pool() {
169    unsafe { std::env::set_var("RUST_LOG", "debug") };
170    env_logger::init();
171
172    let pool = StockPool::<i32>::new_empty();
173    pool.insert(1000001, 100);
174    println!("pool.all_items().len {}", pool.all_items().len());
175    assert_eq!(pool[1000001], 100);
176
177    let pool = StockPool::<i32>::new_default();
178    assert_eq!(pool[1000001], 0);
179
180    let pool = StockPool::<String>::new_empty();
181    assert_eq!(pool.get(1000001), None);
182    // assert_eq!(pool[1000001], ""); // panic, because the stock code is not exist. please use fn insert to insert data.
183
184    let pool = StockPool::<String>::new_default();
185    assert_eq!(pool[1000001], "".to_string());
186
187    let pool = StockPool::<i32>::new_default();
188    println!("pool.all_items().len {}", pool.all_items().len());
189
190    let pool = StockPool::<String>::new_default();
191    assert_eq!(pool[1000001], "".to_string());
192}
193
194#[test]
195fn test_stock_pool_2() {
196    unsafe { std::env::set_var("RUST_LOG", "debug") };
197    env_logger::init();
198
199    let pool = StockPool::<i32>::new_empty();
200    for i in 1..=99999 {
201        pool.insert(1_600_000 + i, i + 100000);
202    }
203    for i in 1..=99999 {
204        pool.insert(2_000_000 + i, i + 300000);
205    }
206    for i in 1..=99999 {
207        pool.insert(2_300_000 + i, i + 300000);
208    }
209    for i in 1..=99999 {
210        pool.insert(400_000 + i, i + 400000);
211    }
212
213    for i in 1..=99999 {
214        pool.insert(1_200_000 + i, i + 220000);
215    }
216
217    for i in 1..=99999 {
218        pool.insert(1_500_000 + i, i + 550000);
219    }
220
221    for i in 1..=99999 {
222        let ii = 1_600_000 + i;
223        assert_eq!((ii, pool[ii]), (ii, i + 100000));
224    }
225    for i in 1..=99999 {
226        assert_eq!(pool[2_000_000 + i], i + 300000);
227    }
228    for i in 1..=99999 {
229        let ii = 2_300_000 + i;
230        assert_eq!((ii, pool[ii]), (ii, i + 300000));
231    }
232    for i in 1..=99999 {
233        let ii = 400_000 + i;
234        assert_eq!((ii, pool[ii]), (ii, i + 400000));
235    }
236
237    for i in 1..=99999 {
238        assert_eq!(pool[1_500_000 + i], i + 550000);
239    }
240    for i in 1..=99999 {
241        assert_eq!(pool[1_200_000 + i], i + 220000);
242    }
243}