ÔÚ¿ª·¢C++³ÌÐòʱ£¬Ò»°ãÔÚÍÌÍÂÁ¿¡¢²¢·¢¡¢ÊµÊ±ÐÔÉÏÓнϸߵÄÒªÇó¡£Éè¼ÆC++³ÌÐòʱ£¬×ܽáÆðÀ´¿ÉÒÔ´ÓÈçϼ¸µãÌá¸ßЧÂÊ£º
1.²¢·¢
2.Òì²½
3.»º´æ
ÏÂÃæ½«ÎÒÆ½³£¹¤×÷ÖÐÓöµ½Ò»Ð©ÎÊÌâÀý¾ÙÒ»¶þ£¬ÆäÉè¼ÆË¼ÏëÎÞ·ÇÒÔÉÏÈýµã¡£
1ÈÎÎñ¶ÓÁÐ
1.1 ÒÔÉú²úÕß-Ïû·ÑÕßÄ£ÐÍÉè¼ÆÈÎÎñ¶ÓÁÐ
Éú²úÕß-Ïû·ÑÕßÄ£ÐÍÊÇÈËÃǷdz£ÊìϤµÄÄ£ÐÍ£¬±ÈÈçÔÚij¸ö·þÎñÆ÷³ÌÐòÖУ¬µ±UserÊý¾Ý±»Â߼ģ¿éÐ޸ĺ󣬾ͲúÉúÒ»¸ö¸üÐÂÊý¾Ý¿âµÄÈÎÎñ£¨produce£©£¬Í¶µÝ¸øIOÄ£¿éÈÎÎñ¶ÓÁУ¬IOÄ£¿é´ÓÈÎÎñ¶ÓÁÐÖÐÈ¡³öÈÎÎñÖ´ÐÐsql²Ù×÷£¨consume£©¡£
Éè¼ÆÍ¨ÓõÄÈÎÎñ¶ÓÁУ¬Ê¾Àý´úÂëÈçÏ£º
void task_queue_t::produce(const task_t& task_) {
lock_guard_t lock(m_mutex);
if (m_tasklist->empty()){//! Ìõ¼þÂú×㻽ÐѵȴýÏß³Ì
m_cond.signal();
}
m_tasklist->push_back(task_);
}
int task_queue_t::comsume(task_t& task_){
lock_guard_t lock(m_mutex);
while (m_tasklist->empty())//! µ±Ã»ÓÐ×÷ҵʱ£¬¾ÍµÈ´ýÖ±µ½Ìõ¼þÂú×ã±»»½ÐÑ{
if (false == m_flag){
return -1;
}
m_cond.wait();
}
task_ = m_tasklist->front();
m_tasklist->pop_front();
return 0;
}
|
1.2 ÈÎÎñ¶ÓÁÐʹÓü¼ÇÉ
1.2.1 IO Óë Âß¼·ÖÀë
±ÈÈçÍøÂçÓÎÏ··þÎñÆ÷³ÌÐòÖУ¬ÍøÂçÄ£¿éÊÕµ½ÏûÏ¢°ü£¬Í¶µÝ¸øÂß¼²ãºóÁ¢¼´·µ»Ø£¬¼ÌÐø½ÓÊÜÏÂÒ»¸öÏûÏ¢°ü¡£Âß¼Ïß³ÌÔÚÒ»¸öûÓÐio²Ù×÷µÄ»·¾³ÏÂÔËÐУ¬ÒÔ±£ÕÏʵʱÐÔ¡£Ê¾Àý£º
void handle_xx_msg(long uid, const xx_msg_t& msg){
logic_task_queue->post(boost::bind(&servie_t::proces, uid, msg));
}
|
×¢Ò⣬´ËģʽÏÂΪµ¥ÈÎÎñ¶ÓÁУ¬Ã¿¸öÈÎÎñ¶ÓÁе¥Ï̡߳£
1.2.2 ²¢ÐÐÁ÷Ë®Ïß
ÉÏÃæµÄÖ»ÊÇÍê³ÉÁËio ºÍ cpuÔËËãµÄ²¢ÐУ¬¶øcpuÖÐÂß¼²Ù×÷ÊÇ´®Ðеġ£ÔÚijЩ³¡ºÏ£¬cpuÂß¼ÔËË㲿·ÖÒ²¿ÉʵÏÖ²¢ÐУ¬ÈçÓÎÏ·ÖÐÓû§AÖֲ˺ÍBÖÖ²ËÁ½ÖÖ²Ù×÷ÊÇÍêÈ«¿ÉÒÔ²¢Ðеģ¬ÒòΪÁ½¸ö²Ù×÷ûÓй²ÏíÊý¾Ý¡£×î¼òµ¥µÄ·½Ê½ÊÇA¡¢BÏà¹ØµÄ²Ù×÷±»·ÖÅäµ½²»Í¬µÄÈÎÎñ¶ÓÁÐÖС£Ê¾ÀýÈçÏ£º
void handle_xx_msg(long uid, const xx_msg_t& msg) {
¡¡¡¡logic_task_queue_array[uid % sizeof(logic_task_queue_array)]->post(
¡¡¡¡¡¡¡¡boost::bind(&servie_t::proces, uid, msg));
}
|
×¢Ò⣬´ËģʽÏÂΪ¶àÈÎÎñ¶ÓÁУ¬Ã¿¸öÈÎÎñ¶ÓÁе¥Ï̡߳£
1.2.3 Á¬½Ó³ØÓëÒì²½»Øµ÷
±ÈÈçÂß¼ServiceÄ£¿éÐèÒªÊý¾Ý¿âÄ£¿éÒì²½ÔØÈëÓû§Êý¾Ý£¬²¢×öºóÐø´¦Àí¼ÆËã¡£¶øÊý¾Ý¿âÄ£¿éÓµÓÐÒ»¸ö¹Ì¶¨Á¬½ÓÊýµÄÁ¬½Ó³Ø£¬µ±Ö´ÐÐSQLµÄÈÎÎñµ½À´Ê±£¬Ñ¡ÔñÒ»¸ö¿ÕÏеÄÁ¬½Ó£¬Ö´ÐÐSQL£¬²¢°ÑSQL
ͨ¹ý»Øµ÷º¯Êý´«µÝ¸øÂß¼²ã¡£Æä²½ÖèÈçÏ£º
1.Ô¤ÏÈ·ÖÅäºÃÏ̳߳أ¬Ã¿¸öÏ̴߳´½¨Ò»¸öÁ¬½Óµ½Êý¾Ý¿âµÄÁ¬½Ó
2.ΪÊý¾Ý¿âÄ£¿é´´½¨Ò»¸öÈÎÎñ¶ÓÁУ¬ËùÓÐÏ̶߳¼ÊÇÕâ¸öÈÎÎñ¶ÓÁеÄÏû·ÑÕß
3.Âß¼²ãÏëÊý¾Ý¿âÄ£¿éͶµÝsqlÖ´ÐÐÈÎÎñ£¬Í¬Ê±´«µÝÒ»¸ö»Øµ÷º¯ÊýÀ´½ÓÊÜsqlÖ´Ðнá¹û
ʾÀýÈçÏ£º
void db_t:load(long uid_, boost::function<void (user_data_t&) func_){
//! sql execute, construct user_data_t user
func_(user)
}
void process_user_data_loaded(user_data_t&){
//! todo something
}
db_task_queue->post(boost::bind(&db_t:load, uid, func));
|
×¢Ò⣬´ËģʽÏÂΪµ¥ÈÎÎñ¶ÓÁУ¬Ã¿¸öÈÎÎñ¶ÓÁжàÏ̡߳£
2. ÈÕÖ¾
±¾ÎÄÖ÷Òª½²C++¶àÏ̱߳à³Ì£¬ÈÕ־ϵͳ²»ÊÇΪÁËÌá¸ß³ÌÐòЧÂÊ£¬µ«ÊÇÔÚ³ÌÐòµ÷ÊÔ¡¢ÔËÐÐÆÚÅÅ´íÉÏ£¬ÈÕÖ¾ÊÇÎÞ¿ÉÌæ´úµÄ¹¤¾ß£¬ÏàÐÅ¿ª·¢ºǫ́³ÌÐòµÄÅóÓѶ¼»áʹÓÃÈÕÖ¾¡£³£¼ûµÄÈÕ־ʹÓ÷½Ê½ÓÐÈçϼ¸ÖÖ£º
Á÷ʽ£¬Èçlogstream << "start
servie time[%d]" << time(0) << "
app name[%s]" << app_string.c_str() <<
endl;
Printf ¸ñʽÈ磺logtrace(LOG_MODULE, "start
servie time[%d] app name[%s]", time(0), app_string.c_str());
¶þÕ߸÷ÓÐÓÅȱµã£¬Á÷ʽÊÇḬ̈߳²È«µÄ£¬printf¸ñʽ¸ñʽ»¯×Ö·û´®»á¸üÖ±½Ó£¬µ«È±µãÊÇÏ̲߳»°²È«£¬Èç¹û°Ñapp_string.c_str()
»»³Éapp_string £¨std::string£©£¬±àÒ뱻ͨ¹ý£¬µ«ÊÇÔËÐÐÆÚ»ácrash£¨Èç¹ûÔËÆøºÃÿ´Î¶¼crash£¬ÔËÆø²»ºÃż¶û»ácrash£©¡£ÎÒ¸öÈËÖÓ°®printf·ç¸ñ£¬¿ÉÒÔ×öÈçϸĽø£º
Ôö¼ÓḬ̈߳²È«£¬ÀûÓÃC++Ä£°åµÄtraits»úÖÆ£¬¿ÉÒÔʵÏÖḬ̈߳²È«¡£Ê¾Àý£º
template
void logtrace(const char* module, const char* fmt, ARG1 arg1){
boost::format s(fmt);
f % arg1;
}
|
ÕâÑù£¬³ýÁ˱ê×¼ÀàÐÍ+std::string ´«ÈëÆäËûÀàÐͽ«±àÒë²»ÄÜͨ¹ý¡£ÕâÀïÖ»ÁоÙÁËÒ»¸ö²ÎÊýµÄÀý×Ó£¬¿ÉÒÔÖØÔØ¸Ã°æ±¾Ö§³Ö¸ü¶à²ÎÊý£¬Èç¹ûÄãÔ¸Ò⣬¿ÉÒÔÖ§³Ö9¸ö²ÎÊý»ò¸ü¶à¡£
ΪÈÕÖ¾Ôö¼ÓÑÕÉ«£¬ÔÚprintfÖмÓÈë¿ØÖÆ×Ö·û£¬¿ÉÒÔÔÙÆÁÄ»ÖÕ¶ËÉÏÏÔʾÑÕÉ«£¬LinuxÏÂʾÀý£ºprintf("\033[32;49;1m
[DONE] \033[39;49;0m")
ÿ¸öÏß³ÌÆô¶¯Ê±£¬¶¼Ó¦¸ÃÓÃÈÕÖ¾´òÓ¡¸ÃÏ̸߳ºÔðʲô¹¦ÄÜ¡£ÕâÑù£¬³ÌÐòÅÜÆðÀ´µÄʱºòͨ¹ýtop
¨CH ¨C p pid ¿ÉÒÔµÃÖªÄǸö¹¦ÄÜʹÓÃcpuµÄ¶àÉÙ¡£Êµ¼ÊÉÏ£¬ÎÒµÄÿÐÐÈÕÖ¾¶¼»á´òÓ¡Ïß³Ìid£¬´ËÏß³Ìid·Çpthread_id£¬¶øÆäʵÊÇÏ̶߳ÔÓ¦µÄϵͳ·ÖÅäµÄ½ø³ÌidºÅ¡£
3. ÐÔÄÜ¼à¿Ø
¾¡¹ÜÒѾÓкܶ๤¾ß¿ÉÒÔ·ÖÎöc++³ÌÐòÔËÐÐÐÔÄÜ£¬µ«ÊÇÆä´ó²¿·Ö»¹ÊÇÔËÐÐÔÚ³ÌÐòdebug½×¶Î¡£ÎÒÃÇÐèÒªÒ»ÖÖÊÖ¶ÎÔÚdebugºÍrelease½×¶Î¶¼ÄÜ¼à¿Ø³ÌÐò£¬Ò»·½ÃæµÃÖª³ÌÐòÆ¿¾±Ö®ËùÔÚ£¬Ò»·½Ã澡Ôç·¢ÏÖÄÄЩ×é¼þÔÚÔËÐÐÆÚ³öÏÖÁËÒì³£¡£
ͨ³£¶¼ÊÇʹÓÃgettimeofday À´¼ÆËãij¸öº¯Êý¿ªÏú£¬¿ÉÒÔ¾«È·µ½Î¢Ãî¡£¿ÉÒÔÀûÓÃC++µÄÈ·¶¨ÐÔÎö¹¹£¬·Ç³£·½±ãµÄʵÏÖ»ñÈ¡º¯Êý¿ªÏúµÄС¹¤¾ß,ʾÀýÈçÏÂ
struct profiler{
profiler(const char* func_name){
gettimeofday(&tv, NULL);
m_func_name=func_name;
}
~profiler(){
struct timeval tv2;
gettimeofday(&tv2, NULL);
long cost = (tv.tv_sec - tv.tv_sec) * 1000000 + (tv.tv_usec - tv.tv_usec);
//! post to some manager
}
struct timeval tv;
const char * m_func_name;
};
#define PROFILER() profiler ____profiler_instance##__LINE__(__FUNCTION__)
|
Cost Ó¦¸Ã±»Í¶µÝµ½ÐÔÄÜͳ¼Æ¹ÜÀíÆ÷ÖУ¬¸Ã¹ÜÀíÆ÷¶¨Ê±½²ÐÔÄÜͳ¼ÆÊý¾ÝÊä³öµ½ÎļþÖС£
4 Lambda ±à³Ì
ʹÓÃforeach ´úÌæµü´úÆ÷
ºÜ¶à±à³ÌÓïÑÔÒѾÄÚ½¨ÁËforeach£¬µ«ÊÇc++»¹Ã»ÓС£ËùÒÔ½¨Òé×Ô¼ºÔÚÐèÒª±éÀúÈÝÆ÷µÄµØ·½±àдforeachº¯Êý¡£Ï°¹ßº¯Êýʽ±à³ÌµÄÈËÓ¦¸Ã»á·Ç³£ÖÓÇéʹÓÃforeach£¬Ê¹ÓÃforeachµÄºÃ´¦¶à¶àÉÙÉÙÓÐЩ£¬È磺
ʾÀý£º
void user_mgr_t::foreach(boost::function func_){
for (iterator it = m_users.begin(); it != m_users.end() ++it){
func_(it->second);
}
}
|
±ÈÈçҪʵÏÖdump ½Ó¿Ú£¬²»ÐèÒªÖØÐ´¹ØÓÚµü´úÆ÷µÄ´úÂë
void user_mgr_t:dump(){
struct lambda {
static void print(user_t& user){
//! print(tostring(user);
}
};
this->foreach(lambda::print);
}
|
ʵ¼ÊÉÏ£¬ÉÏÃæµÄ´úÂë±äͨµÄÉú³ÉÁËÄäÃûº¯Êý£¬Èç¹ûÊÇc++ 11 ±ê×¼µÄ±àÒëÆ÷£¬±¾¿ÉÒÔдµÄ¸ü¼ò½àһЩ£º
this->foreach([](user_t& user) {} );
µ«ÊÇÎҴ󲿷Öʱ¼ä±àдµÄ³ÌÐò¶¼ÒªÔËÐÐÔÚcentos ÉÏ£¬ÄãÖªµÀÂðËüµÄgcc°æ±¾ÊÇgcc 4.1.2£¬
ËùÒԴ󲿷Öʱ¼äÎÒ¶¼ÊÇÓñäͨµÄ·½Ê½Ê¹ÓÃlambdaº¯Êý¡£
Lambda º¯Êý½áºÏÈÎÎñ¶ÓÁÐʵÏÖÒì²½
³£¼ûµÄʹÓÃÈÎÎñ¶ÓÁÐʵÏÖÒì²½µÄ´úÂëÈçÏ£º
void service_t:async_update_user(long uid){
task_queue->post(boost::bind(&service_t:sync_update_user_impl, this, uid));
}
void service_t:sync_update_user_impl(long uid){
user_t& user = get_user(uid);
user.update()
}
|
ÕâÑù×öµÄȱµãÊÇ£¬Ò»¸ö½Ó¿ÚÒªÏìÓ¦µÄдÁ½±éº¯Êý£¬Èç¹ûÒ»¸öº¯ÊýµÄ²ÎÊý±äÁË£¬ÄÇôÁíÒ»¸ö²ÎÊýÒ²Òª¸ú×ŸĶ¯¡£²¢ÇÒ´úÂëÒ²²»ÊǺÜÃÀ¹Û¡£Ê¹ÓÃlambda¿ÉÒÔÈÃÒì²½¿´ÆðÀ´¸üÖ±¹Û£¬·Â·ð¾ÍÊÇÔÚ½Ó¿Úº¯ÊýÖÐÁ¢¿ÌÍê³ÉÒ»Ñù¡£Ê¾Àý´úÂ룺
void service_t:async_update_user(long uid){
struct lambda {
static void update_user_impl(service_t* servie, long uid){
user_t& user = servie->get_user(uid);
user.update();
}
};
task_queue->post(boost::bind(&lambda:update_user_impl, this, uid));
}
|
ÕâÑùµ±Òª¸Ä¶¯¸Ã½Ó¿Úʱ£¬Ö±½ÓÔڸýӿÚÄÚÐ޸ĴúÂ룬·Ç³£Ö±¹Û¡£
5. Ææ¼¼ÒùÇÉ
Map/reduceµÄÓïÒåÊÇÏȽ«ÈÎÎñ»®·ÖΪ¶à¸öÈÎÎñ£¬Í¶µÝµ½¶à¸öworkerÖв¢·¢Ö´ÐУ¬Æä²úÉúµÄ½á¹û¾reduce»ã×ܺóÉú³É×îÖյĽá¹û¡£Shared_ptrµÄÓïÒåÊÇÊ²Ã´ÄØ£¿µ±×îºóÒ»¸öshared_ptrÎö¹¹Ê±£¬½«»áµ÷ÓÃÍйܶÔÏóµÄÎö¹¹º¯Êý¡£ÓïÒåºÍmap/reduce¹ý³Ì·Ç³£Ïà½ü¡£ÎÒÃÇÖ»Ðè×Ô¼ºÊµÏÖ½²ÇëÇó»®·Ö¶à¸öÈÎÎñ¼´¿É¡£Ê¾Àý¹ý³ÌÈçÏ£º
¶¨ÒåÇëÇóÍйܶÔÏ󣬼ÓÈëÎÒÃÇÐèÒªÔÚ10¸öÎļþÖÐËÑË÷¡°oh nice¡±×Ö·û´®³öÏֵĴÎÊý£¬¶¨ÒåÍйܽṹÌåÈçÏ£º
struct reducer{
void set_result(int index, long result) {
m_result[index] = result;
}
~reducer(){
long total = 0;
for (int i = 0; i < sizeof(m_result); ++i){
total += m_result[i];
}
//! post total to somewhere
}
long m_result[10];
};
|
¶¨ÒåÖ´ÐÐÈÎÎñµÄ worker
void worker_t:exe(int index_, shared_ptr ret) {
¡¡¡¡ret->set_result(index, 100);
}
|
½«ÈÎÎñ·Ö¸îºó£¬Í¶µÝ¸ø²»Í¬µÄworker
shared_ptr ret(new reducer());
for (int i = 0; i < 10; ++i)
{
task_queue[i]->post(boost::bind(&worker_t:exe, i, ret));
}
|
|