数据库:
1)取大批量数据时尽量不要使用ORDER BY,先取到内存再自行排序速度可以快许多倍。
2)缓解数据库压力的方法:
分表:比如按用户ID每5W分一个表,此时将比一张500W的大表性能高许多倍
分库:比如分为读写、只读、备份数据库,在符合业务需求的前提下选择数据库的优先级为 备份 > 只读 > 读写
linux:
1)不同发行版的linux许多时候对程序是不兼容的,比如ubuntu与CentOS,在前者平台上编译好的代码到后者上运行时偶尔会出现库不兼容的情况;另,用于第三方LIB时要注意32位与64位的区别,许多时候需要重新在目标平台编译一份才可以。
2)itoa函数并非在所有版本的linux都有,为了确保write once & run anywhere,应尽量考虑使用sprintf来代替itoa。
3)查看进程路径的方法:先ps aux | grep 找到进程ID,如8791,然后cd /proc/8791; ls -l | grep cwd,显示的即是全路径名,如cwd -> /usr/magic/php/bin
4)命令重定向的符号是`而不是',即键盘左上角和~在一起那个而非单引号,比如kill -9 `cat x_serv.pid`,纠结ing~
5)rz传输文件加上-be可以有效避免传输大文件或二进制文件时的中断或传输错误
c++:
1)基类的析构函数为了安全起见一定要声明为虚函数,即使派生类使用默认的析构函数,否则当派生类对象被基类指针析构时会内存泄露!千万不要感觉派生类中没有需要手动释放的成员变量就掉以轻心。
2)形如std::map<int, std::set<int>>之类的嵌套容器在VC2005下clear较慢,改为std::map<int, std::set<int> *>可缩短时间到1/4。
3)使用vector时切忌有过多的erase操作,可以new一个vector,将希望保留的元素添加到新vector,之后释放掉原vector,并使用新vector,两者的效率差为O(N^2),N为元素数,在典型的百W元素级时大约为半分钟VS10小时
4)模板函数中使用到的函数一定也要有模板版本,如果逻辑上确定只有某种类型会用到此函数,可只提供此类型的特化版本,泛型版本可以为空,否则无法编译通过。
5)对嵌套依赖类型名(nested dependent type name)前面需要加typename关键字来显示地告诉编译器,否则示编译器不同有可能造成类型不被识别。
6)混合使用STL与BOOST库时有时会出现莫名其妙的一堆编译错误,此时可以尝试调换包含头文件的顺序。
7)函数名与变量名相同时,对此函数递归调用会编译出错。
misc:
1)当一段新添加的逻辑未能得到预期结果时,首先是在各关键分支添加打印,确定一个或几个出错的函数,然后对这些函数分别作单元测试,盲目地反复推敲代码只是浪费时间。我的习惯是把出错的函数添加到一个空的VS工程中,毕竟VS的调试功能比GDB方便太多,然后产生尽可能接近实际情况的模拟数据进行测试。
我的一段噪声过滤代码无效,调试发现n_max_artist_count一直为0,然后发现:
if (n_cur_count > n_max_artist_count)
n_cur_count = n_max_artist_count;
fuck!
2)做底层库时有些是应该帮上层做的,比如提供支持各种容器和指针的接口,但有些是应该留给上层来做的,比如
一个bool set_list(std::string &key, const void *p_begin, const void *p_end)看似某些时候可以省略掉上层的一步强制类型转换,但对比
bool set_list(std::string &key, const T *p_begin, const T *p_end)
后者可以让使用者在做强制类型转换时意识到自己的行为,而前者则自作聪明地把这一切给隐瞒在自己内部,增加了使用者的潜在风险。