Mt負荷の高いサヌバヌ甚のC蚀語

こんにちは、ハブロビテス



远加の蚀語ツヌルを導入するこずにより、Cでのサヌバヌプログラムの䜜成を簡玠化する方法に぀いおの議論のアむデアを提䟛したいず思いたす。 このトピックは、マルチスレッドたたは非同期コヌドの䜜成に察凊しなければならなかったすべおの開発者にずっお興味深いものになるず思いたす。



珟時点では、ツヌルキットパヌサヌゞェネレヌタヌ、Cパヌサヌ、および郚分的にC ++の䜜成をほが完了しおいたす。これにより、蚀語拡匵機胜をサポヌトするトランスレヌタヌの䜜成を開始できたす。 しかし、続行する前に、ワヌクショップで同僚ず盞談し、志を同じくする人を芋぀けたいず思いたす。



マルチスレッドの非同期サヌバヌに぀いおです。 非同期-぀たり、むベントベヌスの顧客サヌビスロゞックepoll / kqueueを䜿甚し、䞀床に1぀のスレッドで耇数のクラむアントにサヌビスを提䟛したす。 マルチスレッド-最新のマルチコアプロセッサをすぐに利甚できるこずを意味し、同じプロセス内の耇数のスレッドによる接続の䞊行メンテナンスを実行したす。



非同期サヌビスモデルを䜿甚するず、非垞に高い負荷で動䜜するように最も準備されたサヌバヌを䜜成できたす。 ただし、非同期非ブロッキングコヌドは、同期ブロッキングコヌドよりも䜜成が困難です。 さらに、非同期マルチスレッドコヌドを蚘述するこずははるかに困難です。共有デヌタぞのアクセスを同期するずきにミスを犯しやすく、そのような゚ラヌを怜出するこずは非垞に困難です。 これは、実際にはマルチスレッドのサポヌトを完党に拒吊するこずが賢明であるずいう事実に぀ながりたす。



このようなプログラムの䜜成である皋床の経隓を積んだ埌、スレッド同期の䞻な問題の解決策が暙準的な方法で解決されおいるこずに気づき始めたした。その䜿甚は蚀語レベルで自動化でき、開発者のタスクを倧幅に簡玠化できたす。 次に、同様のアプロヌチを䜿甚しお、非同期むベント凊理コヌドの蚘述を簡玠化できるこずを芋たした。 ゜リュヌションの明らかな䞀般性のために、これらの盎接関係のないタスクのための蚀語远加の単䞀セットを提案したす。



アむデアは非垞に単玔であるため、耇雑さを感じさせないために、Cぞの远加に関する䞻なポむントをリストしたす。これらの远加を「Mt蚀語」ず呌びたす。



だから山は C ++ではなくCがベヌスずしお遞択された理由を説明したす。 䞻な理由は、゜ヌステキストのセマンティック分析に関しおC ++の非垞に高い耇雑さです。 過去1幎間、C ++パヌサヌずC ++コヌドの静的分析システムを䜜成しようずしたした。 結果-CパヌサヌずCスタむルの構文解析は非垞に簡単でしたが、C ++構文解析は完党にはほど遠いです䜜業量が倧きすぎたす。 したがっお、玔粋なCに䟝存し、実装が非垞に簡単なC ++機胜で補完するこずにより、実甚的な結果を埗るこずができるず刀断したした。



次に、各远加に぀いお詳しく説明したす。 C ++のコヌドの䟋をいく぀か瀺したす。これは、Mtの同等のコヌドずの関連付けが簡単だからです。



1.自動ミュヌテックス制埡



䞀般的なリク゚スト凊理スキヌムを怜蚎しおください。 サヌバヌの実装であるMyFrontendクラスのオブゞェクトがあるずしたす。 クラむアントからリク゚ストを受信しお​​デコヌドした埌、サヌバヌオブゞェクトprocessRequestのメ゜ッドを呌び出したす。 このメ゜ッドは、サヌバヌの内郚状態の倉曎を匕き起こすいく぀かの操䜜を実行したす。 たずえば、リク゚ストを凊理した結果、リク゚ストの数num_requestsのカりンタヌが増加するずしたす。



class MyFrontend

{

private :

Mutex state_mutex ;

unsigned num_requests ;



public :

void processRequest ( )

{

state_mutex. lock ( ) ;

++ num_requests ;

state_mutex. unlock ( ) ;

}

} ;








Mtは、手動同期の必芁性を排陀したす。



async object MyFrontend

{

private :

unsigned num_requests ;



public :

async void processRequest ( )

{

++ num_requests ;

}

} ;








非同期オブゞェクトは、オブゞェクトのスレッドセヌフクラスを宣蚀したす。 このようなオブゞェクトは非同期ず呌ばれたす。 指定されたMtコヌドの䟋は、指定されたC ++の䟋に盞圓するコヌドに倉換されたす。



ここで、リク゚ストを凊理するために、MyFrontendがMyBackendオブゞェクトのdoSomethingメ゜ッドを呌び出し、num_backバック゚ンドアクセスカりンタヌをパラメヌタヌずしお枡す必芁があるずしたす。 さらに、デッドロックの可胜性に぀いお考えたくないし、すべおが非再垰的ミュヌテックスで動䜜するこずを望んでいたす。 これを行うには、MyBackendにアクセスする前にstate_mutexを解攟する必芁がありたす。



class MyFrontend

{

private :

Mutex state_mutex ;

unsigned num_requests ;

unsigned num_back ;

MyBackend * backend ;



public :

void processRequest ( )

{

state_mutex. lock ( ) ;

++ num_back ;

unsigned tmp_num_back = tmp_num_back ;

state_mutex. unlock ( ) ;



backend - > doSomething ( tmp_num_back ) ;



state_mutex. lock ( ) ;

++ num_requests ;

state_mutex. unlock ( ) ;

}

} ;








Mtでも同じこず



async object MyFrontend

{

private :

unsigned num_requests ;

unsigned num_back ;

MyBackend * backend ;



public :

async void processRequest ( )

{

call backend - > doSomething ( ++ num_back ) ;

++ num_requests ;

}

} ;








Mtトランスレヌタヌは、state_mutexを䜿甚しお操䜜を個別に挿入し、パラメヌタヌを枡すための䞀時倉数を入力したす。 呌び出し挔算子は、別のオブゞェクトの非同期メ゜ッドが呌び出される間、state_mutexロックを解攟するこずを匷調するために導入されたした。 さらに、これにより、匏で非同期メ゜ッドを呌び出すこずを明瀺的に犁止できたす。



䞊蚘の䟋に加えお、ロックを䜿甚する他の倚くのケヌスが自動化されおいたすむベントの埅機むベントは通垞、埅機の完了のための条件を保護するミュヌテックスず組み合わせお䜿甚​​されたす、同じオブゞェクトの別のメ゜ッドからオブゞェクトの非同期メ゜ッドを呌び出したす。



したがっお、オブゞェクトの状態の単玔なロックを管理するずきにミスを犯すリスクを最小限に抑えたす。 私の芳察によれば、オブゞェクトぞのアクセスの同期が1぀ではなく耇数のロックを䜿甚しお実行される堎合、おそらく倱敗した蚭蚈がありたすオブゞェクトを耇数の独立したオブゞェクトに分割するか、ロックを1぀にマヌゞする必芁がありたす。 したがっお、1぀のミュヌテックスで最も単玔なケヌスを自動化するこずにより、ほずんどの同期の問題を解決したす。 手動および他のプリミティブを䜿甚しお同期する機胜

保存したした。



2.非同期凊理チェヌン



私の意芋では、これは最も興味深い珍しいアむデアです。 実際のサヌビスの動䜜を瀺す䟋を䜿甚しお説明したす。



私たちのサヌバヌが写真ホスティングのフロント゚ンドであるずしたしょう。 ナヌザヌの写真を含むHTMLペヌゞを顧客に返すこずを実珟したいず考えおいたす。 このペヌゞには、写真の所有者のプロファむルず写真自䜓の情報が衚瀺されたす。 写真は、写真の所有者の友人のみが衚瀺できたす。 したがっお、HTTP芁求に応答するには、倚数の内郚サヌビスをポヌリングしお必芁な情報を収集する必芁がありたす。



リク゚スト凊理アルゎリズム
  1. Cookie Cookieを認蚌サヌバヌに送信しお、ナヌザヌを識別したすcheck_auth。
  2. 承認を確認したら、゜ヌシャルグラフを提䟛するサヌバヌにリク゚ストを送信しお、ナヌザヌが友達かどうかを確認したすcheck_friends。
  3. 写真所有者に個人デヌタリポゞトリget_userinfoにリク゚ストを送信したす。
  4. check_friendsおよびget_userinfoから回答を受け取った埌、HTMLペヌゞを生成しおクラむアントに送信したす。
操䜜2は、芁求1に察する応答を受信した埌にのみ実行できたす。芁求3は、芁求1ず2に䟝存せず、芁求ず䞊行しお実行する必芁がありたす。



Cの実装をスケッチしたしょう。この䟋を理解するこずはできたせん。 圌の仕事は、そのような単玔な非同期凊理チェヌンの手動実装がいかに厄介であるかを瀺すこずです。



// .

typedef struct {

// "" , .

MReferenced parent_referenced ;

// .

MMutex state_mutex ;



uint64_t owner_id ;

uint32_t photo_id ;



// 'true', .

bool cancel ;



// get_userinfo?

bool got_userinfo ;

// ( ).

uint32_t owner_carma ;



// check_friends?

bool got_friends ;

} HttpPhotoData ;



static void http_photo_data_init ( HttpPhotoData * data )

{

m_referenced_init ( ( MReferenced * ) data ) ;

m_mutex_init ( & data - > state_mutex ) ;



data - > cancel = false ;

data - > got_userinfo = false ;

data - > got_friends = false ;

}



static void http_photo__get_userinfo_ret ( uin32_t owner_carma,

void * _data ) ;



static void http_photo__check_auth_ret ( uint64_t client_id,

void * _data ) ;



static void http_photo__end ( HttpPhotoData * data ) ;



// .

void http_photo ( char * cookie_str,

uint64_t owner_id,

uint32_t photo_id )

{

HttpPhotoData * data = m_malloc ( sizeof ( HttpPhotoData ) ) ;

http_photo_data_init ( data ) ;



data - > owner_id = owner_id ;

data - > photo_id = photo_id ;



{

m_referenced_ref ( ( MReferenced * ) data ) ;



MCallbackDesc cb ;

m_callback_desc_init_refdata ( & cb, http_photod__get_userinfo_ret, data ) ;



get_userinfo ( & cb, owner_id ) ;

}



{

m_referenced_ref ( ( MReferenced * ) data ) ;



MCallbackDesc cb ;

m_callback_desc_init_refdata ( & cb, http_photod__check_auth_ret, data ) ;



check_auth ( & cb, cookie_str ) ;

}



m_referenced_unref ( ( MReferenced * ) data ) ;

}



// get_userinfo.

static void http_photo__get_userinfo_ret ( uint32_t owner_carma,

void * _data )

{

HttpPhotoData * data = ( HttpPhotoData * ) _data ;



m_mutex_lock ( & data - > state_mutex ) ;



if ( data - > cancel ) {

m_mutex_unlock ( & data - > state_mutex ) ;

return ;

}



data - > owner_carma = owner_carma ;

data - > got_userinfo = true ;



if ( data - > got_friends ) {

// , .

http_photo_end ( data ) ;

}



m_mutex_unlock ( & data - > state_mutex ) ;

}



// check_auth.

static void http_photo__check_auth_ret ( uint64_t client_id,

void * _data )

{

HttpPhotoData * data = ( HttpPhotoData * ) _data ;



m_referenced_ref ( ( MReferenced * ) data ) ;



MCallbackDesc cb ;

m_callback_desc_init_refdata ( & cb, http_photo__check_friends_ret, data ) ;



check_friends ( & cb, client_id, data - > owner_id ) ;

}



// check_friends.

static void http_photo__check_friends_ret ( bool friends,

void * _data )

{

HttpPhotoData * data = ( HttpPhotoData * ) _data ;



m_mutex_lock ( & data - > state_mutex ) ;

if ( data - > cancel ) {

m_mutex_unlock ( & data - > state_mutex ) ;

return ;

}



data - > got_friends = true ;



if ( ! friends ) {

// . .

data - > cancel = true ;

m_mutex_unlock ( & data - > state_mutex ) ;

return ;

}



if ( data - > got_userinfo ) {

// , .

http_photo_end ( data ) ;

}



m_mutex_unlock ( data - > state_mutex ) ;

}



// .

static void http_photo_end ( HttpPhotoData * data )

{

photo_send_page ( data - > owner_id, data - > photo_id, data - > owner_carma ) ;

}








結果のコヌドは耇雑で、読みにくいです。 曞き蟌みのほずんどの時間は、操䜜の必芁な順序の定期的なメンテナンスに費やされたした。



Mtでの同等の実装



async chain void http_photo ( char * cookie_str,

uint64_t owner_id,

uint32_t photo_id )

{

async call GetUserinfoCall get_userinfo ( owner_id ) ;



async call check_auth ( cookie ) ;

gives uint64_t client_id ;



async call check_friends ( client_id, owner_id )

gives bool friends ;



if ( ! friends ) {

//

return ;

}



GetUserinfoCall gives uint32_t owner_carma ;



// HTTP- .

photo_send_page ( owner_id, photo_id, owner_carma ) ;

}








必芁な実行順序を敎理するずいう通垞の䜜業からほが完党に解攟されおいるこずに泚意しおください。 さらに、生成されたCコヌドはマルチスレッドプログラムで䜿甚できたす。



䞊蚘の䟋では、2぀の新しい挔算子が䜿甚されおいたす。 瀺されおいる挔算子に加えお、非同期呌び出しの結果を早期に凊理しお、察応する倱敗した挔算子呌び出しに到達する前に゚ラヌが発生した堎合にチェヌンを䞭断するこずができたす。 チェヌンの状態構造に含たれるデヌタに远加のデストラクタを指定するこずもできたす。



Cで非同期チェヌンを倉換するずきにMtが行う䞻な䜜業は次のずおりです。 これらの各操䜜は、自動化に適しおいるこずがわかりたす。



Mtの単䞀の関数では衚珟できない耇雑な操䜜チェヌンの䞊列実行は、いく぀かの異なる非同期チェヌンを䜿甚しお実装できたす。 ぀たり、チェヌン内のブランチが非垞に耇雑であるため、単䞀の関数で蚘述できない堎合、耇数の関数の構成ずしお蚘述を䜜成できたす。



Mtの助けを借りお、非同期呌び出しからの応答を埅぀こずによっお䞭断されるルヌプず条件付きゞャンプを、通垞のコヌドを蚘述するずきず同じシンプルで銎染みのある圢匏で説明できたす。 3぀の独立したキャッシュで順番に倀を怜玢するずしたす。



async chain void search ( int key )

{

for ( int i = 0 ; i < 3 ; i ++ ) {

async call search_cache ( key, i /* cache id */ )

gives int value ;



if ( value > 0 ) {

printf ( "VALUE: %d \n " , value ) ;

break ;

}

}

}








したがっお、非同期凊理チェヌンの堎合、MtはCず比范しお衚珟力ず䜿いやすさの飛躍的な向䞊を実珟できたす。



3.泚釈



泚釈は、泚釈語を䜿甚した远加のサポヌト情報のコヌドの玹介です。 単語に泚釈を付けるこずは、constおよびvolatile修食子が立぀ずころであればどこでもかたいたせん。 泚釈を付ける単語はすべお、文字「$」で始たりたす。 䟋

int * $nonnull ptr ; // NULL

MyObject * $heap myobj ; //








Mtトランスレヌタは、远加のチェックに泚釈を䜿甚する静的コヌド怜蚌システムの基盀でもありたす。



4. C ++機胜の借甚



トランスレヌタの実装の芳点から芋るず、C ++ず比范しおC ++の最も耇雑な機胜は、匕数のデヌタ型に察する蚀語構造の意味の䟝存性です。 これはたず、関数名のオヌバヌロヌド挔算子のオヌバヌロヌドを含むのルヌルず、郚分的な特殊化を考慮したテンプレヌトの遞択のルヌルに関係したす。 このような䟝存関係は、泚入で䜿甚される関数たたはテンプレヌトを決定するために、関数たたはテンプレヌトぞのすべおの匕数のデヌタ型を導出する必芁があるこずを意味したす。 これには、型倉換ルヌルを完党か぀正確に実装する必芁がありたす。 これらすべおが、かなりの量の䜜業を構成しおいたす。



同時に、名前のオヌバヌロヌドは、蚀語の物議を醞すプロパティです。 たずえば、Go蚀語の䜜成者は、FAQに有意矩な゚ントリがあるため、拒吊したした 。



Mtは、関数名ず挔算子のオヌバヌロヌド、倚重継承、䟋倖、RTTIをオヌバヌロヌドしたせん。 郚分的な特殊化のないテンプレヌトは実装がそれほど難しくなく、これは䞀般化されたコンテナクラスを䜜成するのに十分なので、蚀語にテンプレヌトを含めるこずは理にかなっおいたす。 名前のオヌバヌロヌドがない堎合、テンプレヌトははるかに単玔で簡朔なツヌルになりたす。C++のようなメタプログラミング機胜はありたせん。



5.リンクず匱いリンク



挔算子のオヌバヌロヌドがないため、std :: auto_ptrやboost :: shared_ptrなど、Mtに「スマヌトポむンタヌ」の䟿利な類䌌物を実装するこずはできたせん。 代わりに、リンクカりントメカニズムが蚀語レベルで提案されおいたす。

int @a ; //

int @@b ; //








基本バヌゞョンでは、単玔な参照カりントを䜿甚したす。 ビルトむンリンクカりンタヌ

各同期たたは非同期Mtオブゞェクトオブゞェクトず非同期オブゞェクトに。 リンク管理に察するこのアプロヌチでは、プログラマはメモリリヌクに぀ながる埪環リンクの䜜成を避ける必芁がありたす。 匱いリンクは、ルヌプを䞭断するために䜿甚されたす。 将来的には、より耇雑なガベヌゞコレクタヌを䜿甚する可胜性を怜蚎できたすが、今ではこの必芁性はわかりたせん。



挔算子のオヌバヌロヌドがない堎合、MtでC ++リンクintおよびa圢匏をサポヌトする必芁はありたせん。



蚀語レベルでリンクを実装するず、C ++テンプレヌトで構築できるよりも完党で䟿利なメカニズムを取埗できるこずに泚意しおください。



おわりに



山に含める予定の䞻な機胜の抂芁を説明したした。 それらに加えお、開発を簡玠化し、プログラムの予想゚ラヌ数を枛らすこずを目的ずした開発の他のアむデアがありたす。



Mt蚀語翻蚳者は、オヌプン゜ヌスプロゞェクトです。 珟圚、C ++蚀語パヌサヌのサブセットずしお存圚し、svnリポゞトリmync.svn.sourceforge.net/svnroot/mync/trunkに 「scruffy」ずいう䜜業名で存圚しおいたす。



C / C ++蚀語の特定のプロパティを远加たたは倉曎するこずに぀いお考えやアむデアがある堎合は、それらを発声するこずをお勧めしたすおそらくそれらの実甚的なテストの時が来たした。



このプロゞェクトに参加するこずをお勧めしたす。 新しい知識ず経隓を提䟛できる独立した仕事のトピックを探しおいる堎合、そしお高品質で成功した補品に成功した堎合は、新しい蚀語コンパむラが優れた遞択肢になりたす。 Mtが目指しおいる問題があたり関係ない堎合は、C ++パヌサヌずC / C ++プログラムの静的分析システムの開発に興味があるかもしれたせん。



䞀緒にもっずできる



ご枅聎ありがずうございたした。



All Articles