ARTS-week01
Algorithm
数据结构与算法之美 — 数组
- 要点1.栈上的数据按地址从大到小进行分配空间
- 要点2.数组元素按地址从小到大进行分配空间
- 要点3.警惕数组遍历时访问越界
上代码
// compile command: gcc -lstdc++ -std=c++11 test.cc -o test -lm
#include <iostream>
int main(int argc, char* argv[]) {
int i = 0;
int arr[3] = {0};
for (; i <=3; i++) {
arr[i] = 0;
std::cout << "hello:" << &i << " " << &arr[i]<< std::endl;
}
return 0;
}
预期将进入死循环,持续打印"hello:…"
原理分析:
// compile command: gcc -lstdc++ -std=c++11 test.cc -o test -lm
#include <iostream>
int main(int argc, char* argv[]) {
int i = 0;
int arr[3] = {0};
std::cout << "hello:" << &i << " " << &arr[0] << std::endl;
std::cout << "hello:" << &i << " " << &arr[1] << std::endl;
std::cout << "hello:" << &i << " " << &arr[2] << std::endl;
std::cout << "hello:" << &i << " " << &arr[3] << std::endl;
//for (; i <=3; i++) {
// arr[i] = 0; //此处arr[3]与i地址相同,越界访问后,修改了i的值,导致死循环。
// std::cout << "hello:" << &i << " " << &arr[i]<< std::endl;
//}
return 0;
}
/* print
hello:0x7fff92efeeec 0x7fff92efeee0
hello:0x7fff92efeeec 0x7fff92efeee4
hello:0x7fff92efeeec 0x7fff92efeee8
hello:0x7fff92efeeec 0x7fff92efeeec
*/
数据结构与算法之美 — 链表(上)
#include <iostream>
#include <vector>
#include <string>
class Node {
public:
Node() : _value(0), _next(nullptr) {}
~Node() {}
public:
int32_t _value;
Node* _next;
};
class LinkedList {
private:
Node* head;
int pos;
int length;
public:
LinkedList() {
// 头结点不参与计数
head = new Node();
head->_value = 0;
head->_next = nullptr;
pos = 0;
length = 0;
}
~LinkedList() { delete head; }
void create(std::vector<int32_t>& input);
void insert(int32_t pos, int32_t value);
void print(); // 遍历打印
bool is_empty();
int32_t get_length() { return length; }
void delete_node(int32_t pos);
void delete_list();
};
void LinkedList::create(std::vector<int32_t>& input) {
if (input.size() == 0) {
return;
}
Node* p_tmp = head;
for (auto& it : input) {
Node* p_new = new Node();
p_new->_value = it;
head->_next = p_new;
head = head->_next;
length++;
}
head = p_tmp;
return;
}
void LinkedList::print() {
std::string print_log;
print_log.append("head->");
if (head->_next == nullptr) {
print_log.append("tail");
std::cout << print_log << std::endl;
return;
}
Node* tmp = head;
while (tmp->_next != nullptr) {
print_log.append(std::to_string(tmp->_next->_value)).append("->");
tmp = tmp->_next;
}
print_log.append("tail");
std::cout << print_log << std::endl;
return;
}
bool LinkedList::is_empty() {
if (head->_next == nullptr) {
return true;
} else {
return false;
}
}
void LinkedList::insert(int32_t pos, int32_t value) {
if (pos < 0 || pos > length + 1) {
std::cout << "invalid pos" << std::endl;
return;
}
Node* p_new = new Node();
p_new->_value = value;
Node* tmp = head;
while (pos-- > 1) { // 当pos=0/1时,均表示插在head后的第1个位置
tmp = tmp->_next;
}
p_new->_next = tmp->_next;
tmp->_next = p_new;
length++;
}
void LinkedList::delete_node(int32_t pos) {
if (pos <= 0 || pos > get_length()) {
std::cout << "invalid pos" << std::endl;
return;
}
Node* tmp = head;
while (pos-- > 1 ) { // 遍历获取指定pos的上一个node
tmp = tmp->_next;
}
Node* tmp_next = tmp->_next->_next;
delete tmp->_next;
tmp->_next = tmp_next;
length--;
}
void LinkedList::delete_list() {
Node* p_delete = head->_next;
while(p_delete != nullptr) {
Node* tmp = p_delete->_next;
delete p_delete;
p_delete = tmp;
head->_next = tmp;
}
}
// 测试
int main(int argc, char* argv[]) {
LinkedList list;
std::vector<int32_t> input = {3, 2, 8, 6, 5, 9};
list.create(input);
list.print();
std::cout << "length:" << list.get_length() << std::endl;
list.insert(7, 10);
list.print();
std::cout << "length:" << list.get_length() << std::endl;
list.delete_node(7);
list.print();
list.delete_list();
list.print();
return 0;
}
/*
* head->3->2->8->6->5->9->tail
* length:6
* head->3->2->8->6->5->9->10->tail
* length:7
* head->3->2->8->6->5->9->tail
* head->tail
*/
// gcc -g -lstdc++ -std=c++11 main_test.cc -o test -lm
Review
What every computer science major should know
每一个计算机专业的学生应该了解的知识,文章里面列举了很多,感觉一下子是干不完的,主要写一下自己感触深刻的几点:
- 个人主页比简历更重要。要建立起自己的个人主页,更新自己做过的项目、开源社区贡献的代码、同时提炼自己的思考。
- 技术交流。要学会逻辑清晰、有说服力地将自己的观点、想法跟非计算机专业人员沟通。学会做好presentation很重要。
- 基本数据结构和算法知识。
Tip
linux性能优化实践
cpu性能优化-01
平均负载:简单来说,平均负载是指单位时间内,系统处于可运行状态和不可中断状态的平均进程数,也就是平均活跃进程数,它和 CPU 使用率并没有直接关系。
uptime # 查看cpu平均负载
pidstat -u 5 1 # 查看各线程cpu使用率 间隔5秒输出一组数据 -u 标识cpu指标
mpstat -P ALL 5 1 # 显示所有 CPU 的指标,并在间隔 5 秒输出一组数据
vmstat # 用来分析系统内存使用情况、CPU上下文切换、中断的次数
uptime
02:34:03 up 2 days, 20:14, 1 user, load average: 0.63, 0.83, 0.88
# 每隔 5 秒输出 1 组数据
$ vmstat 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
0 0 0 7005360 91564 818900 0 0 0 0 25 33 0 0 100 0 0
# cs(context switch): 每秒上下文切换次数
# in(interrupt): 每秒中断次数
# r(Running): 就绪队列的长度,也就是正在运行和等待CPU的进程数
# b(Blocked): 处于不可中断睡眠状态的进程数
# 每隔 5 秒输出 1 组数据
$ pidstat -w 5
Linux 4.15.0 (ubuntu) 09/23/18 _x86_64_ (2 CPU)
08:18:26 UID PID cswch/s nvcswch/s Command
08:18:31 0 1 0.20 0.00 systemd
08:18:31 0 8 5.40 0.00 rcu_sched
...
# cswch: 每秒自愿上下文切换次数。所谓自愿上下文切换,是指进程无法获取所需资源,导致的上下文切换。比如说,IO,内存等系统资源不足时,就会发生自愿上下文切换。
# nvcswch: 每秒非自愿上下文切换次数。是指进程由于时间片已到等原因,被系统强制调度,进而发生的上下文切换。比如大量进程争抢cpu时,就容易发生非自愿上下文切换。
# 每隔 1 秒输出 1 组数据(需要 Ctrl+C 才结束)
# -w 参数表示输出进程切换指标,而 -u 参数则表示输出 CPU 使用指标
$ pidstat -w -u 1
08:06:33 UID PID %usr %system %guest %wait %CPU CPU Command
08:06:34 0 10488 30.00 100.00 0.00 0.00 100.00 0 sysbench
08:06:34 0 26326 0.00 1.00 0.00 0.00 1.00 0 kworker/u4:2
08:06:33 UID PID cswch/s nvcswch/s Command
08:06:34 0 8 11.00 0.00 rcu_sched
08:06:34 0 16 1.00 0.00 ksoftirqd/1
08:06:34 0 471 1.00 0.00 hv_balloon
08:06:34 0 1230 1.00 0.00 iscsid
08:06:34 0 4089 1.00 0.00 kworker/1:5
08:06:34 0 4333 1.00 0.00 kworker/0:3
08:06:34 0 10499 1.00 224.00 pidstat
08:06:34 0 26326 236.00 0.00 kworker/u4:2
08:06:34 1000 26784 223.00 0.00 sshd
# 每隔 1 秒输出一组数据(需要 Ctrl+C 才结束)
# -wt 参数表示输出线程的上下文切换指标 -t 表示输出线程信息
$ pidstat -wt 1
08:14:05 UID TGID TID cswch/s nvcswch/s Command
...
08:14:05 0 10551 - 6.00 0.00 sysbench
08:14:05 0 - 10551 6.00 0.00 |__sysbench
08:14:05 0 - 10552 18911.00 103740.00 |__sysbench
08:14:05 0 - 10553 18915.00 100955.00 |__sysbench
08:14:05 0 - 10554 18827.00 103954.00 |__sysbench
...
# -d 参数表示高亮显示变化的区域
$ watch -d cat /proc/interrupts
CPU0 CPU1
...
RES: 2450431 5279697 Rescheduling interrupts
...
Share
学习baidu-rpc的DoublyBufferedData实现
应用场景:
- reload词典。大部分时候词典都是只读的,不同线程同时查询时不应互斥。
- 可替换的全局callback。像butil/logging.cpp支持配置全局LogSink以重定向日志,这个LogSink就是一个带状态的callback。如果只是简单的全局变量,在替换后我们无法直接删除LogSink,因为可能还有都写线程在用。用DBD可以解决这个问题。