$ grep -n 'Hummingbird' hummingbird_encyclopedia.txt 16:''''Hummingbirds'''' are [[bird]]s native to the… 22:Hummingbirds have the highest… 24:Hummingbirds split from their [[Sister taxon|sister group]]… // 輸出繼續
CPU 分析工具會追蹤程式在執行時花費時間的地方。為了提供最有效率的 CPU 分析體驗,Dart 虛擬機器 (VM)(為 Dart CLI 和 Flutter 應用程式提供動力)使用 取樣 CPU 分析器。當與 Dart DevTools 等工具一起使用時,您可以識別 Dart 程式中的效能瓶頸。
取樣 CPU 分析器採用統計方法來收集應用程式效能資料。它透過定期中斷執行緒並擷取當前呼叫堆疊和其他相關執行狀態的快照來收集樣本。這些樣本可以被處理,以便找出大約有多少時間花費在執行特定函數上,以及函數在不同呼叫堆疊上出現的頻率。
收集樣本的頻率稱為 取樣速率,以每秒樣本數(也稱為赫茲或 Hz)衡量。大多數取樣分析器具有 1000 Hz 或更高的取樣速率。更高的取樣速率會產生更詳細的 CPU 分析,但代價是在目標流程中更高的取樣負擔。在合理的取樣速率下,取樣 CPU 分析器非常有效,並且對被分析應用程式的效能特徵沒有影響。額外的優勢是,與追蹤分析器相比,收集的資料通常在分析方面計算成本更低。
深入探討:取樣分析器是如何運作的?
這部分將詳細介紹 Dart VM 的取樣 CPU 分析器的工作原理。在分析 CPU 分析時,您不需要了解這些細節。如果您不關心取樣 CPU 分析器的詳細資訊,請跳過此部分。
Dart VM 的取樣 CPU 分析器具有三個重要的元件:執行緒中斷器、樣本收集器和樣本處理器。
執行緒中斷器
執行緒中斷器 在一個專用的執行緒上運行,並在 VM 管理的每個執行緒上觸發表 CPU 樣本收集。執行緒中斷器通常處於非活動狀態,只在每個取樣間隔後喚醒一次。在每個取樣間隔之後,中斷器會遍歷執行緒列表,通知每個執行緒暫停並收集樣本。執行緒中斷器在不同平台上的行為略有不同,因為作業系統有特定的細節。
在大多數支援 基於訊號的控制流(Android 和 Linux)的平台上,SIGPROF 訊號會發送到每個執行緒。這會觸發一個 中斷,該中斷會呼叫 CPU 分析器在目標執行緒上註冊的訊號處理器,然後在繼續工作之前收集 CPU 樣本。
在其他不支持訊號(Windows 和 Fuchsia)或在某些情況下使用 SIGPROF 時效能不佳(MacOS 和 iOS)的平台上,執行緒中斷器使用系統呼叫在收集 CPU 樣本後顯式地暫停和恢復每個執行緒。在這種情況下,樣本收集是在執行緒中斷器執行緒上進行,而不是在被取樣的執行緒上進行。
當客戶端透過 VM 服務協定 請求 CPU 樣本分析時,CPU 分析器需要在將樣本發送給客戶端之前處理收集的樣本。分析器:
遍歷樣本緩衝區,使用篩選器只擷取客戶端指定的隔離區和時間範圍內的樣本。
符號化,或將 PC 對映到函數名稱,樣本集中每個堆疊框架。
將整個處理後的樣本緩衝區序列化為 JSON。
將 JSON 傳回給客戶端。
即使在分析器完成處理之後,CPU 樣本回應 仍然是低階的,需要開發人員工具進行額外的處理才能變得有用。例如,Dart DevTools 可以將 CPU 樣本列表轉換為各種結構表示,這些表示允許識別昂貴的函數(自下而上)、昂貴的呼叫路徑(呼叫樹 和 CPU 火焰圖),以及檢查個別方法的呼叫者和被呼叫者統計資料(方法表)。
使用 Dart DevTools 分析 Dart 和 Flutter 應用程式
現在您已經熟悉了取樣 CPU 分析器是什麼以及它們的工作原理,讓我們除錯 grep 實作的效能。讓我們使用 --observe 再次運行程式碼,並打開 Dart DevTools CPU 分析器標籤:
// 開啟檔案並讀取其內容。 final lines = file.readAsLinesSync();
// 將 '文字配對' 標記設定為目前的使用者標記。 textMatchTag.makeCurrent(); final output = StringBuffer(); int lineNum = 1; // 檢查每一行,看看它是否與 `樣式` 匹配。 for (final line in lines) { final matcher = RegExp(pattern); if (matcher.hasMatch(line)) { final foundMessage = '$lineNum:$line'; // 將匹配項加入到緩衝區中,而不建立副本。 output.writeln(foundMessage); } lineNum++; }
$ dart grep.dart hummingbird_encyclopedia.txt 'Hummingbird' 16:''''Hummingbirds'''' are [[bird]]s native to the… 22:Hummingbirds have the highest… 24:Hummingbirds split from their [[Sister taxon|sister group]]… // 輸出繼續
結合 AI 生成的文字和圖片,為這款使用 Flutter、Firebase 和 Google Cloud 建立的紙牌遊戲增添趣味
I/O FLIP 是一款由 Google 支援並使用 Flutter 建立的 AI 設計紙牌遊戲。它結合了許多 Google 產品和技術,包括 Flutter、Firebase、生成式 AI 工具、Muse 上的 Dreambooth、PaLM API 和 MakerSuite。玩家可以進行多場比賽,並將遊戲中的牌分享到社群媒體。
I/O FLIP 中的每張牌都是獨特的,因為它包含 AI 生成的圖片和描述。在遊戲開始時,玩家會回答兩個提示。這些提示有助於填充一副包含 12 張牌的牌組,這些牌組的圖片和描述是 AI 模型預先生成的。
Google 團隊使用了兩種技術來預先生成圖片:Muse,一個 Transformer 文字轉圖片模型,以及 Dreambooth。Dreambooth 使得能夠在不同的場景、姿勢、視角和光照條件下合成一個主體。每張牌都包含四個 Google 吉祥物之一:Dash、Sparky、Android 或 Dino,以及一個地點。吉祥物還有一個物品,用來指定他們的隊伍。「隊伍類型」提示在遊戲開始時就會被覆蓋,用於建立這個物品。例如,選擇「巫師」可能會導致一個角色戴著巫師帽、魔杖,或其他巫師般的事物!
Google 團隊使用 PaLM API 來預先生成牌的描述。PaLM API 訪問 Google 的大型語言模型。遊戲開始時的提示包含團隊類型和他們團隊的力量類型。假設您選擇了「巫師」團隊和「磁力」力量。當您的牌生成時,一張牌的描述包含與生成的圖片相關的上下文,包括角色的特殊力量。例如,「Dash 巫師和他的寵物龍住在一座城堡裡。他喜歡施法,讓大家開心。」
String whatDoesItSay(Animal a) => switch (a) { Cow c => '$c says moo', Sheep s => '$s says baa' };
這將返回以下錯誤,提醒我們漏掉了對最後一個可能的子類型 Pig 的處理:
1 2
line 6 • The type 'Animal'is not exhaustively matched by the switch cases since it doesn't match 'Pig()'.
最後,if 語句也可以使用模式。在下面的示例中,我們正在使用 if-case 匹配一個映射模式來分解 JSON 映射。在其中,我們根據常量值(字串,例如 'name' 和 'Michael')和類型測試模式 int h 進行匹配,以讀取 JSON 值。如果模式匹配失敗,Dart 將執行 else 語句。
1 2 3 4 5 6 7 8
final json = {'name': 'Michael', 'height': 180};
// Find Michael's height. if (json case {'name': 'Michael', 'height': int h}) { print('Michael is $h cm tall.'); } else { print('Error: json contains no height info for Michael!'); }