check1
Structure and Design
这里主要就是需要维护一个区间,来表示每一次插入的时候插入的data是什么以及有效的 first_index
和 last_index
所以首先有一个类
1 | class section |
有了这个类之后,使用一个 std::set<section> sections
来按照第一个字母排序,维护一个有序的集合,这样每次新加入一段的时候,其前后的 index
只有
- 小于
section.first_index
- 大于等于
section.first_index
且小于等于section.last_index
- 大于
section.last_index
那么根据首位index
的这三种情况组合起来,一共有 9 种,但是其中某些不可能出现,于是处理的框架就是:其中所有以1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51void Reassembler::dummy_insert( uint64_t first_index, std::string& data, bool is_last_substring )
{
uint64_t last_index = first_index + data.size() - 1;
bool is_inserted = false;
for ( auto it = sections.begin(); it != sections.end(); it++ ) {
uint64_t first = it->get_first_index();
uint64_t last = it->get_last_index();
int relative_position_first = get_relative_position( first, last, first_index );
int relative_position_last = get_relative_position( first, last, last_index );
std::pair<int, int> cases( relative_position_first, relative_position_last );
if ( cases == make_pair( 1, 1 ) ) {
section new_section( first_index, last_index, data );
sections.insert( new_section );
bytes_pending_ += new_section.get_size();
is_inserted = true;
break;
} else if ( cases == make_pair( 1, 2 ) ) {
string push_data = data.substr( 0, first - first_index );
section new_section( first_index, first - 1, push_data );
sections.insert( new_section );
bytes_pending_ += new_section.get_size();
is_inserted = true;
break;
} else if ( cases == make_pair( 1, 3 ) ) {
string push_data = data.substr( 0, first - first_index );
string remaining_data = data.substr( last - first_index + 1 );
section new_section( first_index, first - 1, push_data );
bytes_pending_ += new_section.get_size();
sections.insert( new_section );
dummy_insert( last + 1, remaining_data, is_last_substring );
is_inserted = true;
break;
} else if ( cases == make_pair( 2, 2 ) ) {
return;
} else if ( cases == make_pair( 2, 3 ) ) {
string remaining_data = data.substr( last - first_index + 1 );
dummy_insert( last + 1, remaining_data, is_last_substring );
is_inserted = true;
break;
} else if ( cases == make_pair( 3, 3 ) ) {
continue;
} else {
__throw_logic_error( "should not reach here" );
}
}
if ( !is_inserted ) {
section new_section( first_index, last_index, data );
sections.insert( new_section );
bytes_pending_ += new_section.get_size();
}
}3
结尾的情况,都需要考虑多出来的一段与后面的情况,为了省事这里直接采用递归的方式,递归插入剩下多的情况Hint:这里应该并非最佳实践,首先这里的set是可以用lower_bound直接查询第一个插入的位置的,但是因为我不会用遂作罢,第二是,这里的带1的情况我没有直接合并进去,因为set是不能修改的,所以应该用map更好
最后每次插入结束都尝试进行一次push,即
1 | void Reassembler::try_push() |
Implementation Challenges
第一个问题是,这里不允许用指针自己造链表,所以第一次我写了三天的链表过不了编译,遂作罢,摆烂用set了
第二是:
这里一开始忘了迭代器删除之后再++是ub,我以为会自动更新,忘了手动更新过不了测速
Experimental results and performance.
最后测速在 10.07Gbit/s
左右,还有优化空间
All articles on this blog are licensed under CC BY-NC-SA 4.0 unless otherwise stated.