mongodb核心原始碼實現、效能調優、最佳運維實踐系列-command命令處理模組原始碼實現三
關於作者
前滴滴出行技術專家,現任OPPO 文件資料庫 mongodb 負責人,負責 oppo 千萬級峰值 TPS/ 十萬億級資料量文件資料庫 mongodb 核心研發及運維工作,一直專注於分散式快取、高效能服務端、資料庫、中介軟體等相關研發。後續持續分享《 MongoDB 核心原始碼設計、效能優化、最佳運維實踐》, Github 賬號地址 : https://github.com/y123456yz
1. command 預設介面類核心程式碼實現及基本介面功能說明
每個命令都對應一個command 基類,該類中完成命令的一些基本介面功能初始化,核心介面實現如下 :
1. //命令模組基類基礎介面初始化實現 2. class Command : public CommandInterface { 3. public: 4. //獲取集合名collection 5. static std::string parseNsFullyQualified(...); 6. //獲取DB.COLLECTION 7. static NamespaceString parseNsCollectionRequired(...); 8. //map表結構 9. using CommandMap = StringMap<Command*>; 10. ...... 11. //獲取命令名 12. const std::string& getName() const final { 13. return _name; 14. } 15. ...... 16. //應答保留填充欄位長度 17. std::size_t reserveBytesForReply() const override { 18. return 0u; 19. } 20. //該命令是否只能在admin庫執行,預設不可以 21. bool adminOnly() const override { 22. return false; 23. } 24. //該命令是否需要許可權認證檢查?預設不需要 25. bool localHostOnlyIfNoAuth() override { 26. return false; 27. } 28. //該命令執行後是否進行command操作計數 29. bool shouldAffectCommandCounter() const override { 30. return true; 31. } 32. //該命令是否需要認證 33. bool requiresAuth() const override { 34. return true; 35. } 36. //help幫助資訊 37. void help(std::stringstream& help) const override; 38. //執行計劃資訊 39. Status explain(...) const override; 40. //日誌資訊相關 41. void redactForLogging(mutablebson::Document* cmdObj) override; 42. BSONObj getRedactedCopyForLogging(const BSONObj& cmdObj) override; 43. //該命令是否為maintenance模式,預設false 44. bool maintenanceMode() const override { 45. return false; 46. } 47. //maintenance是否支援,預設支援 48. bool maintenanceOk() const override { 49. return true; 50. } 51. //本地是否支援非本地ReadConcern,預設不支援 52. bool supportsNonLocalReadConcern(...) const override { 53. return false; 54. } 55. //是否允許AfterClusterTime,預設允許 56. bool allowsAfterClusterTime(const BSONObj& cmdObj) const override { 57. return true; 58. } 59. //3.6版本預設opCode=OP_MSG,所以對應邏輯操作op為LogicalOp::opCommand 60. LogicalOp getLogicalOp() const override { 61. return LogicalOp::opCommand; 62. } 63. //例如find就是kRead,update delete insert就是kWrite,非讀寫操作就是kCommand 64. ReadWriteType getReadWriteType() const override { 65. return ReadWriteType::kCommand; 66. } 67. //該命令執行成功統計 68. void incrementCommandsExecuted() final { 69. _commandsExecuted.increment(); 70. } 71. 72. //該命令執行失敗統計 73. void incrementCommandsFailed() final { 74. _commandsFailed.increment(); 75. } 76. 77. //真正得命令執行 78. bool publicRun(OperationContext* opCtx, const OpMsgRequest& request, BSONObjBuilder& result); 79. 80. //獲取支援的所有命令資訊 ListCommandsCmd獲取所有支援的命令 db.listCommands() 81. static const CommandMap& allCommands() { 82. return *_commands; 83. } 84. 85. //沒用 86. static const CommandMap& allCommandsByBestName() { 87. return *_commandsByBestName; 88. } 89. 90. //收到不支援命令的統計,例如mongo shell敲一個mongodb無法識別得命令,這裡就會統計出來 91. static Counter64 unknownCommands; 92. //根據命令字串名查詢對應命令 93. static Command* findCommand(StringData name); 94. //執行結果 95. static void appendCommandStatus(...); 96. //是否啟用了command test功能 97. static bool testCommandsEnabled; 98. //help幫助資訊 99. static bool isHelpRequest(const BSONElement& helpElem); 100. static const char kHelpFieldName[]; 101. //認證檢查,檢查是否有執行該命令得許可權 102. static Status checkAuthorization(Command* c, 103. OperationContext* opCtx, 104. const OpMsgRequest& request); 105. ...... 106. private: 107. //新增地方見Command::Command( 108. //所有的command都在_commands中儲存 109. static CommandMap* _commands; 110. //暫時沒用 111. static CommandMap* _commandsByBestName; 112. //執行對應命令run介面 113. virtual bool enhancedRun(OperationContext* opCtx, 114. const OpMsgRequest& request, 115. BSONObjBuilder& result) = 0; 116. //db.serverStatus().metrics.commands命令檢視,本命令的執行統計,包括執行成功和執行失敗的 117. Counter64 _commandsExecuted; 118. Counter64 _commandsFailed; 119. //命令名,如"find" "insert" "update" "createIndexes" "deleteIndexes" 120. const std::string _name; 121. 122. //每個命令執行是否成功通過MetricTree管理起來,也就是db.serverStatus().metrics.commands統計資訊 123. //通過MetricTree特殊二叉樹管理起來 124. ServerStatusMetricField<Counter64> _commandsExecutedMetric; 125. ServerStatusMetricField<Counter64> _commandsFailedMetric; };
command 作為預設介面類,主要完成一些命令基本介面初始化操作及預設配置設定,該類最基本的介面主要如下:
l reserveBytesForReply
ReserveBytesForReply() 介面主要完成該命令應答填充欄位長度,預設值為 0 。對應命令可以在具體命令類中修改。
l adminOnly
該命令是否只能在admin 庫操作,預設為 false 。也可以在對應命令繼承類中修改,例如 "moveChunk" 命令則在 MoveChunkCommand 繼承類中設定為 true ,也就是該命令只能在 admin 庫操作。
l localHostOnlyIfNoAuth
該命令是否支援在例項所在本機不認證操作,預設值false 。對應命令可以在具體繼承類中修改。
l shouldAffectCommandCounter
該命令是否需要command 統計,也就是 mongostat 中的 command 統計計數是否需要使能。預設值 true ,也就是該命令會進行 command 計數統計。對應命令可以在具體繼承類中修改。
l requiresAuth
該命令是否需要認證,預設為true 。對應命令可以在具體繼承類中修改。
l allowsAfterClusterTime
該命令是否支援AfterClusterTime ,預設為 true 。對應命令可以在具體繼承類中修改。
l getLogicalOp
該命令是否為邏輯opCommand 命令。 3.6 版本預設 opCode=OP_MSG, 所以對應邏輯操作 op 為 LogicalOp::opCommand 。
l getReadWriteType
如果為讀命令則type 對應 kRead ,寫命令 type 對應 kWrite ,其他讀寫以外的命令對應 kCommand 。
l incrementCommandsExecuted
該命令執行成功統計,通過db.serverStatus().metrics.commands 獲取該命令統計。
l _commandsFailed
該命令執行失敗統計,通過db.serverStatus().metrics.commands 獲取該命令統計。
以上列舉除了command 基類的幾個核心功能預設值資訊,如果繼承類中沒有修改這些介面值,則該命令對應功能就是這些預設值。
說明:各種不同命令如果不適用command 基類的預設介面,則可以在繼承類中修改對應介面值即可更改對應功能。
命令除了上面提到的基本功能是否支援外,command 類還有其他幾個核心介面功能。例如,該命令是否認證成功、是否有操作許可權、允許對應 run 命令等。 command 類函式介面功能總結如下表所示:
2. 命令run
結合《命令處理模組原始碼實現一》和本章節對command 處理流程可以得出, runCommandImpl 介面通過如下呼叫流程最終執行特定命令的run 介面,這裡以 insert 寫入和讀取流程為例, mongod 例項寫入呼叫過程如下圖所示 :
最終,mongod 和 mongos 例項呼叫相關命令得 run 介面完成具體的 command 命令處理操作。 mongos 、 mongod(shardServer) 、 mongod(configServer) 相關常用的操作命令 ( 以最基本的讀寫命令為例 ) 入口及功能說明總結如下表所示:
3. command 模組統計資訊
mongodb command 命令處理模組相關統計包含三類:單個命令統計、彙總型統計、讀寫時延統計。其中,單個命令統計針對所有接受到的命令名字串進行統計,彙總型統計則是把同一型別的命令總結為一個整體統計 ( 例如 commands 統計 ) 。
3.1 單個命令統計
mongodb 會收集所有操作命令執行結果,如果本次命令執行成功,則該命令成功統計自增加 1 ,同理如果該命令執行過程失敗,則失敗統計自增加 1 ,這些統一歸類為 ” 單個命令統計資訊 ” 。
單個命令統計由command 類的 _commandsExecuted 和 _commandsFailed 實現命令執行成功統計和失敗統計,相關核心程式碼實現如下:
1. //該命令執行成功統計 2. void incrementCommandsExecuted() final { 3. _commandsExecuted.increment(); 4. } 5. 6. //該命令執行失敗統計 7. void incrementCommandsFailed() final { 8. _commandsFailed.increment(); 9. } 1. //命令入口 2. void execCommandDatabase(...) 3. { 4. ...... 5. //該命令執行次數統計 db.serverStatus().metrics.commands可以獲取統計資訊 6. command->incrementCommandsExecuted(); 7. ...... 8. //真正的命令執行在這裡面 9. retval = runCommandImpl(opCtx, command, request, replyBuilder, startOperationTime); 10. 11. //該命令失敗次數統計 12. if (!retval) { 13. command->incrementCommandsFailed(); 14. } 15. ...... }
mongodb 預設會統計每個客戶端發往服務端的命令,即使是無法識別的命令也會統計,命令統計可以通過 db.serverStatus().metrics.commands 獲取,如下圖所示:
3.2 彙總型 commands 命令統計
從前面的單個命令統計可以看出,單個命令會記錄所有傳送給mongodb 的命令資訊。 mongodb 支援的命令百餘個,由於命令眾多,因此 mongodb 為了更加直觀明瞭的獲取統計資訊,除了提供單個命令統計外,還對外提供彙總型命令統計。
彙總型命令統計可以通過db.serverStatus().opcounters 命令獲取, mongostat 中的增刪改查等資訊也來自於該統計,如下圖:
從上圖可以看出,整個mongostat 監控統計可以歸類為小表:
insert 、 delete 、 update 、 find 分別對應增刪改查四個命令操作, getMore 對應批量遊標操作命令。這五個命令,對應命令執行的時候統計資訊自增,核心程式碼實現如下:
3.2.1 insert 操作統計
insert 操作統計在代理 mongos 和分片儲存節點 mongod 都會統計,兩種角色的 insert 統計核心程式碼如下:
1. 代理mongos insert 統計核心程式碼實現
1. bool insertBatchAndHandleErrors(...) { 2. ...... 3. //一次性一條一條插入,上面的固定集合是一次性插入 4. for (auto it = batch.begin(); it != batch.end(); ++it) { 5. //insert操作計數 6. globalOpCounters.gotInsert(); 7. } 8. ...... 9. }
2. 分片儲存節點mongod insert 統計核心程式碼實現
1. //mongod代理insert統計核心流程 2. bool ClusterWriteCmd::enhancedRun(...) { 3. ...... 4. if (_writeType == BatchedCommandRequest::BatchType_Insert) { 5. //insert計數 6. for (size_t i = 0; i < numAttempts; ++i) { 7. globalOpCounters.gotInsert(); 8. } 9. } 10. ...... 11. }
3.2.2 query 操作統計
1. 代理mongos query 統計核心程式碼實現:
1. bool ClusterFindCmd::run(...) { 2. //find操作統計,也就是query統計 3. globalOpCounters.gotQuery(); 4. ...... 5. }
2. 分片儲存節點mongod query 統計核心程式碼實現:
1. bool FindCmd::run(...) { 2. //find操作統計,也就是query統計 3. globalOpCounters.gotQuery(); 4. ...... 5. }
3.2.3 update 操作統計
1. 代理mongos update 統計核心程式碼實現 :
1. bool ClusterWriteCmd::enhancedRun(...) { 1. //update操作統計 2. globalOpCounters.gotUpdate(); 3. ...... 4. }
2. 分片儲存節點mongod update 統計核心程式碼實現 :
1. //mongod代理update統計核心流程 2. bool ClusterWriteCmd::enhancedRun(...) { 3. ...... 4. if (_writeType == BatchedCommandRequest::BatchType_Update) { 5. //insert計數 6. for (size_t i = 0; i < numAttempts; ++i) { 7. globalOpCounters.gotUpdate(); 8. } 9. } 10. ...... 11. }
3.2.4 delete 操作統計
1. 代理mongos delete 統計核心程式碼實現 :
1. //mongos代理update統計核心流程 2. bool ClusterWriteCmd::enhancedRun(...) { 3. ...... 4. if (_writeType == BatchedCommandRequest::BatchType_Update) { 5. //insert計數 6. for (size_t i = 0; i < numAttempts; ++i) { 7. globalOpCounters.gotUpdate(); 8. } 9. } 10. ...... 11. }
2. 分片儲存節點mongod delete 統計核心程式碼實現 :
1. static SingleWriteResult performSingleDeleteOp(...) { 2. ...... 3. //分片mongod例項delete操作統計 4. globalOpCounters.gotDelete(); 5. ...... 6. }
3.2.5 getMore 操作統計
1. 代理mongos getMore 統計核心程式碼實現 :
1. //mongos代理getMore統計核心流程 2. bool ClusterGetMoreCmd::enhancedRun(...) { 3. //代理getMore統計 4. globalOpCounters.gotGetMore(); 5. ...... 6. }
2. 分片儲存節點mongod getMore 統計核心程式碼實現 :
1. //mongod分片儲存節點getMore統計
2. bool ClusterGetMoreCmd::enhancedRun(...) {
3. //儲存節點mongod getMore統計
4. globalOpCounters.gotGetMore();
5. ......
6. }
3.2.6 command 操作統計
前面五種操作統計都很好理解,commands 統計由那些命令操作組成,本節將重點分析 commands 如何實現統計。 commands 統計核心程式碼實現如下:
1. 代理mongos commands 統計核心程式碼實現 :
1. //mongos代理commands統計 2. void execCommandDatabase(...) { 3. ...... 4. if (command->shouldAffectCommandCounter()) { 5. OpCounters* opCounters = &globalOpCounters; 6. opCounters->gotCommand(); 7. } 8. ...... 9. }
2. 儲存節點mongod commands 統計核心程式碼實現:
1. void execCommandDatabase(...) { 2. ...... 3. //是否進行command統計 4. if (command->shouldAffectCommandCounter()) { 5. OpCounters* opCounters = &globalOpCounters; 6. //commands計數自增 7. opCounters->gotCommand(); 8. } 9. ...... 10. }
從上面的程式碼可以看出,只有對應命令類中 shouldAffectCommandCounter () 為 true 的命令才會進行 commands 計數。前面章節中我們提到,所有命令都有一個對應類實現相應功能,所有命令實現類都繼承一個功能 class command {} 類,該類對 shouldAffectCommandCounter () 介面進行初始化。程式碼實現如下:
1. class Command : { 2. ...... 3. //該命令是否進行command操作計數,預設需要。如果不需要進行command統計,可在命令繼承類中置為false 4. bool shouldAffectCommandCounter() const override { 5. return true; 6. } 7. ...... 8. }
該介面預設為true ,如果對應命令不需要進行 commands 計數統計,則需要在對應命令實現類中把該介面置為 false 。通過分析程式碼,可以看出,只有以下命令子類把 shouldAffectCommandCounter () 介面設定為 false ,搜尋結果如下 :
分析程式碼可以得出如下結論:
1) mongos 代理中的 clase Cluster_find_cmd { } 類和 class Cluster_getmore_cmd {} 類的 shouldAffectCommandCounter () 介面置為 false ,這兩個類分別對應代理的“ find ”和“ getMore ”命令操作,也就說明 mongos 代理 de 這兩個命令操作不會統計到 commands 中。
2) mongod 分片儲存節點的 clase Find_cmd{} 、 class Getmore_cmd {} 、 class Write_commands{} 三個類中把 shouldAffectCommandCounter () 介面置為 false 。這三個類分別對應 mongod 儲存例項的如下幾個命令:“ find ”、“ getMore ”、“ insert ”、“ update ”、“ delete ”五個命令。
mongos 和 mongod 例項 commands 統計資訊總結如下:
3.3 慢日誌、時延統計
每次客戶端請求執行實踐如果超過了log level 配置的最大慢日誌時間,則會把該操作詳細資訊記錄下來,同時把本操作執行時間新增到對應的讀或者寫計數及時延統計中。命令處理模組中,時延相關統計包括以下兩種統計:
① 慢日誌統計
② 讀寫計數及時延統計
3.3.1 慢日誌統計
當啟用了慢日誌記錄功能後,mongod 會把執行時間超過指定閥值的慢日誌記錄下來。慢日誌預設記錄到服務日誌檔案 ( systemLog.path 配置項設定) ,同時會記錄日誌到 ”system.profile” 集合中。慢日誌核心程式碼實現如下:
1. DbResponse ServiceEntryPointMongod::handleRequest(...) { 2. ...... 3. //記錄開始時間 4. //獲取當前操作對應curop 5. CurOp& currentOp = *CurOp::get(opCtx); 6. 7. ...... 8. //執行請求對應命令 9. runCommands(opCtx, m); 10. ...... 11. 12. //記錄結束時間 13. currentOp.ensureStarted(); 14. currentOp.done(); 15. //獲取開始和結束時間差,也就是命令執行時間 16. debug.executionTimeMicros = durationCount<Microseconds> 17. (currentOp.elapsedTimeExcludingPauses()); 18. //記錄超過閥值的慢日誌到日誌檔案 19. if (shouldLogOpDebug || (shouldSample && debug.executionTimeMicros > logThresholdMs * 1000LL)) { 20. ...... 21. //記錄慢日誌到日誌檔案 22. log() << debug.report(&c, currentOp, lockerInfo.stats); 23. } 24. //記錄慢日誌到system.profile集合 25. if (currentOp.shouldDBProfile(shouldSample)) { 26. ...... 27. //記錄慢日誌到system.profile集合中 28. profile(opCtx, op); 29. } 30. ...... 31. }
3.3.2 讀寫操作計數及時延統計
根據請求command 命令型別 ( 包含讀命令、寫命令、 command 命令 ) ,以及命令執行時間,可以計算出不同型別命令的讀寫執行時間,從而計算出叢集的讀時延、寫時延、 command 時延。 mongodb 所有命令可以歸納為讀、寫、 command 三類,核心程式碼如下:
1. //獲取操作型別 2. Command::ReadWriteType CurOp::getReadWriteType() const { 3. ...... 4. switch (_logicalOp) { 5. //getmore find歸納為讀 6. case LogicalOp::opGetMore: 7. case LogicalOp::opQuery: 8. return Command::ReadWriteType::kRead; 9. //增刪改統一歸納為寫 10. case LogicalOp::opUpdate: 11. case LogicalOp::opInsert: 12. case LogicalOp::opDelete: 13. return Command::ReadWriteType::kWrite; 14. //增刪改以外的歸納為command 15. default: 16. return Command::ReadWriteType::kCommand; 17. } 18. }
從上面的程式碼可以看出,讀、寫、command 分別對應以下命令:
讀(read) :包含getMore 、 find 。
寫(write) :包含insert 、 delete 、 update 。
command :讀和寫以外的所有命令。
命令執行完計算出命令執行時間後,mongod 例項會記錄下這個時延,累加到歷史統計 OperationLatencyHistogram 中,讀、寫、 command 操作計數及時延統計分別記錄到 _reads 、 _writes 、 _commands 三個變數成員中。該統計核心程式碼實現如下:
1. //Top::_incrementHistogram呼叫 2. //操作和時延計數操作 3. void OperationLatencyHistogram::increment(uint64_t latency, Command::ReadWriteType type) { 4. int bucket = _getBucket(latency); 5. switch (type) { 6. //讀時延累加,讀計數自增 7. case Command::ReadWriteType::kRead: 8. _incrementData(latency, bucket, &_reads); 9. break; 10. //寫時延累加,寫計數自增 11. case Command::ReadWriteType::kWrite: 12. _incrementData(latency, bucket, &_writes); 13. break; 14. //command時延累加,command計數自增 15. case Command::ReadWriteType::kCommand: 16. _incrementData(latency, bucket, &_commands); 17. break; 18. default: 19. MONGO_UNREACHABLE; 20. } 21. }
命令請求執行過程及其對應的讀寫請求操作計數、時延累加銜接程式碼實現如下:
1. DbResponse ServiceEntryPointMongod::handleRequest(...) { 2. ...... 3. //記錄開始時間 4. //獲取當前操作對應curop 5. CurOp& currentOp = *CurOp::get(opCtx); 6. 7. ...... 8. //執行請求對應命令 9. runCommands(opCtx, m); 10. ...... 11. 12. //記錄結束時間 13. currentOp.ensureStarted(); 14. currentOp.done(); 15. //獲取開始和結束時間差,也就是命令執行時間 16. debug.executionTimeMicros = durationCount<Microseconds> 17. (currentOp.elapsedTimeExcludingPauses()); 18. ...... 19. //記錄慢日誌到system.profile集合 20. //mongod讀寫的時間延遲統計 db.serverStatus().opLatencies獲取 21. Top::get(opCtx->getServiceContext()) 22. .incrementGlobalLatencyStats( //讀寫統計 23. opCtx, 24. //時延 25. durationCount<Microseconds>(currentOp.elapsedTimeExcludingPauses()), 26. currentOp.getReadWriteType()); //讀寫型別 27. ...... 28. }
mongod 例項讀、寫、 command 操作計數及其各自時延統計可以通過 db.serverStatus() 介面獲取,使用者可用取樣來計算對應的 tps 和平均時延資訊。獲取操作統計和時延統計的命令如下 :
db.serverStatus().opLatencies
4. 問題回顧
《Mongodb command 命令處理模組原始碼實現一》一文中提到的 commands 統計資訊到這裡就可以得到答案了,如下表所示:
mongos 和 mongod 例項 commands 統計資訊總結如下:
mongos 代理 mongostat 統計可以彙總為下圖所示:
mongod 代理 mongostat 統計可以彙總為下圖所示:
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69984922/viewspace-2738326/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- mongodb核心原始碼實現、效能調優、最佳運維實踐系列-command命令處理模組原始碼實現一MongoDB原始碼運維
- mongodb核心原始碼實現、效能調優、最佳運維實踐系列-command命令處理模組原始碼實現二MongoDB原始碼運維
- mongodb核心原始碼實現、效能調優、最佳運維實踐系列-mongodb網路傳輸層模組原始碼實現三MongoDB原始碼運維
- mongodb核心原始碼實現、效能調優、最佳運維實踐系列-網路傳輸層模組原始碼實現三MongoDB原始碼運維
- mongodb核心原始碼實現、效能調優、最佳運維實踐系列-網路傳輸層模組原始碼實現四MongoDB原始碼運維
- mongodb核心原始碼實現、效能調優、最佳運維實踐系列-網路傳輸層模組原始碼實現二MongoDB原始碼運維
- mongodb核心原始碼實現及效能優化系列:Mongodb write寫(增、刪、改)模組原始碼實現MongoDB原始碼優化
- mongodb原始碼實現、調優、最佳實踐系列-數百萬行mongodb核心原始碼閱讀經驗分享MongoDB原始碼
- mongodb核心原始碼實現及效能最佳化:transport_layer網路傳輸層模組原始碼實現二MongoDB原始碼
- mongodb核心原始碼實現及效能最佳化系列:Mongodb特定場景效能數十倍提升最佳化實踐MongoDB原始碼
- 萬字長文 | MongoDB絡傳輸處理原始碼實現及效能調優MongoDB原始碼
- mongodb網路傳輸處理原始碼實現及效能調優-體驗核心效能極致設計MongoDB原始碼
- mongodb核心transport_layer網路傳輸層模組原始碼實現三MongoDB原始碼
- mongodb核心原始碼實現、效能調優系列-為何要對開源mongodb資料庫核心做二次開發MongoDB原始碼資料庫
- Mongodb write寫(增、刪、改)模組原始碼實現MongoDB原始碼
- mongodb核心transport_layer 網路傳輸層模組原始碼實現四MongoDB原始碼
- mongodb核心原始碼實現及效能最佳化:常用高併發執行緒模型設計及mongodb執行緒模型最佳化實踐MongoDB原始碼執行緒模型
- 70行實現Promise核心原始碼Promise原始碼
- FPGA排序模組與verilog實現【含原始碼!!!】FPGA排序原始碼
- QT Widgets模組原始碼解析與實踐QT原始碼
- Vue原始碼探究-核心類的實現Vue原始碼
- 最佳實踐 | 原始碼升級gcc原始碼GC
- Promise原始碼實現Promise原始碼
- 影片直播系統原始碼,非同步處理實現程式碼分析原始碼非同步
- 讀書APP原始碼,搜尋欄模糊處理實現APP原始碼
- Axios 原始碼解讀 —— 原始碼實現篇iOS原始碼
- 婚戀app原始碼開發,如何實現介面效能優化?APP原始碼優化
- webpack Hmr 原始碼實現Web原始碼
- HashMap原始碼實現分析HashMap原始碼
- 仿Express原始碼實現(-)Express原始碼
- Redis核心原理與實踐--事務實踐與原始碼分析Redis原始碼
- 實現語音社交原始碼介面效能優化,從索引入手原始碼優化索引
- Dubbo 實現原理與原始碼解析系列 —— 精品合集原始碼
- Spark 原始碼系列(七)Spark on yarn 具體實現Spark原始碼Yarn
- 原始碼|ThreadLocal的實現原理原始碼thread
- Promise實現原理(附原始碼)Promise原始碼
- Vue.js 原始碼實現Vue.js原始碼
- Vue.watche 原始碼實現Vue原始碼