デスクトップフローの Power FxとRobinの処理速度をチョットだけ比較してみた

# Microsoft Power Automate Advent Calendar 2024

本記事は、Microsoft Power Automate Advent Calendar 2024:gift: の12月21日担当分の記事です。

この記事では、2024年11月のアップデートにてGA（一般公開）された、Power Fxを有効化したデスクトップフローと、Power Fxを無効化（従来のRobin）したデスクトップフローの比較を紹介します。
※Robin：Power Automate for desktop の内部言語

**:warning:注意点1**：記述式やフローの組み方に関する違い、比較は主に本記事内では触れません。記述式の違いなどは他の方の記事や、公開情報を参考にしてください。

**:warning:注意点2**：本記事の内容は2024年12月時点の情報に基づいています。今後のアップデートや変更により、情報が変わる可能性がありますのでご注意ください。

### 参考リンク

- :link: [Microsoft 公式ドキュメント](https://learn.microsoft.com/ja-jp/power-platform/power-fx/formula-reference-desktop-flows)
- デスクトップフローのPower Fxに関する参考記事
  - :link: [形式張らない Power Fx を有効化したデスクトップフローの紹介](https://zenn.dev/ksh365/articles/b9f1c359e2382f)
  - :link: [Power Fx を有効化したデスクトップフローで、従来のデスクトップフローの Datetime のプロパティと同じ値を取得する方法](https://zenn.dev/ksh365/articles/99ab42c9a038e5)
  - :link: [Power Fx を有効化したデスクトップフローで、従来のデスクトップフローのテキスト値のプロパティと同じ値を取得する方法](https://zenn.dev/ksh365/articles/bf3af3cf4829ab)
  - :link: [Power Fx を有効化したデスクトップフローでテキストに変数を埋め込む方法](https://zenn.dev/ksh365/articles/9c7046d6c42097)


## 背景
「よし！デスクトップフローのPower Fx も遂にGAしたし、今後本格的に使っていこう :grinning:！」  
←:bulb:あれ？そういえば、記述式（フローの開発方法）が違うのわかるけど、実運用を考えたとき、実行速度とか同じ？問題ない？
という思いから検証しよう！と思い立ったのがきっかけ。

## 目的
Power Fxを有効化したデスクトップフローと、Robin（従来）のデスクトップフローの実行速度の差を計測し、Power Fxを有効化したフローも運用に耐えうるかを確認する。

## 検証する処理
- １．テキストの処理：Text
- ２．日付の処理：DateTime
- ３．データテーブルの処理：DataTable

### 実行環境:robot:
- Power Automate for desktop: 2.51 (2024年12月アップデート)
- Windows 11 Pro 64bit / Mem: 32GB / SSD: 1TB

## 検証フローの用意

### 処理時間測定のための仕組み
1. 処理の頭に「現在の日時を取得」アクションを配置して現在日時を取得する。
2. 各種処理を実装する。
3. 各種処理の実装の後に、再度「現在の日時を取得」アクションを配置して、現在の日時を取得する。
4. 1で取得した日時と、3で取得した日時を「日付の減算」アクションで差分を取得する。
5. 結果を変数に追加。

### サンプル：Power Fx版
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1064310/2258daa8-608e-aa75-c2ce-10d945432f32.png)

```PowerFx
# 開始時間取得
DateTime.GetCurrentDateTime.Local DateTimeFormat: DateTime.DateTimeFormat.DateAndTime CurrentDateTime=> CurrentDateTime
SET Year TO $fx'=Year(CurrentDateTime)'

# 終了時間取得
DateTime.GetCurrentDateTime.Local DateTimeFormat: DateTime.DateTimeFormat.DateAndTime CurrentDateTime=> CurrentDateTimeTo

# 処理時間計算
DateTime.Subtract FromDate: CurrentDateTimeTo SubstractDate: CurrentDateTime TimeUnit: DateTime.DifferenceTimeUnit.Seconds TimeDifference=> TimeDifference
```

### １．テキストの処理
以下のアクションの構成を用意。

1. サンプルのテキストを変数に格納
2. 文字数を取得
3. 空か空白か判断する値を取得
4. 大文字のテキストを取得
5. 小文字のテキストを取得

#### Robin式
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1064310/3063e70f-7e6f-1c71-3d5a-7fad0fcc4d88.png)

サブフロー名：Text
```Robin
DateTime.GetCurrentDateTime.Local DateTimeFormat: DateTime.DateTimeFormat.DateAndTime CurrentDateTime=> CurrentDateTime
SET sampleText TO $'''Power Automateで効率化！'''
SET Length TO sampleText.Length
SET isEmpty TO sampleText.IsEmpty
SET ToUpper TO sampleText.ToUpper
SET ToLower TO sampleText.ToLower
DateTime.GetCurrentDateTime.Local DateTimeFormat: DateTime.DateTimeFormat.DateAndTime CurrentDateTime=> CurrentDateTimeTo
DateTime.Subtract FromDate: CurrentDateTimeTo SubstractDate: CurrentDateTime TimeUnit: DateTime.DifferenceTimeUnit.Seconds TimeDifference=> TimeDifference
Text.AppendLine Text: Result LineToAppend: $'''DataTable：%TimeDifference%''' Result=> Result
```

#### Power Fx式
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1064310/1d58d701-c39f-dfc8-7db6-70cf56fb76a4.png)

サブフロー名：Text
```PowerFx
DateTime.GetCurrentDateTime.Local DateTimeFormat: DateTime.DateTimeFormat.DateAndTime CurrentDateTime=> CurrentDateTime
SET sampleText TO $'''Power Automateで効率化！'''
SET Length TO $fx'=Len(sampleText)'
SET isEmpty TO $fx'=IsBlank(sampleText)'
SET ToUpper TO $fx'=Upper(sampleText)'
SET ToLower TO $fx'=Lower(sampleText)'
DateTime.GetCurrentDateTime.Local DateTimeFormat: DateTime.DateTimeFormat.DateAndTime CurrentDateTime=> CurrentDateTimeTo
DateTime.Subtract FromDate: CurrentDateTimeTo SubstractDate: CurrentDateTime TimeUnit: DateTime.DifferenceTimeUnit.Seconds TimeDifference=> TimeDifference
Text.AppendLine Text: $fx'=Result' LineToAppend: $fx'DateTime：${TimeDifference}' Result=> Result
```

### ２．日付の処理
以下のアクションの構成を用意。

1. 現在の日時を取得する
2. 年を取得
3. 月を取得
4. 日を取得
5. 時間を取得
6. 分を取得
7. 秒を取得

#### Robin式
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1064310/060ba7db-65bf-90dd-ac17-f684cf13b16c.png)

サブフロー名：DateTime
```Robin
DateTime.GetCurrentDateTime.Local DateTimeFormat: DateTime.DateTimeFormat.DateAndTime CurrentDateTime=> CurrentDateTime
SET Year TO CurrentDateTime.Year
SET Month TO CurrentDateTime.Month
SET Day TO CurrentDateTime.Day
SET Hour TO CurrentDateTime.Hour
SET Minute TO CurrentDateTime.Minute
SET Second TO CurrentDateTime.Second
DateTime.GetCurrentDateTime.Local DateTimeFormat: DateTime.DateTimeFormat.DateAndTime CurrentDateTime=> CurrentDateTimeTo
DateTime.Subtract FromDate: CurrentDateTimeTo SubstractDate: CurrentDateTime TimeUnit: DateTime.DifferenceTimeUnit.Seconds TimeDifference=> TimeDifference
Text.AppendLine Text: Result LineToAppend: $'''DataTable：%TimeDifference%''' Result=> Result
```

#### Power Fx式
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1064310/9ca48f55-9c9e-d391-1c32-3b067c5beafa.png)

サブフロー名：DateTime
```PowerFx
DateTime.GetCurrentDateTime.Local DateTimeFormat: DateTime.DateTimeFormat.DateAndTime CurrentDateTime=> CurrentDateTime
SET Year TO $fx'=Year(CurrentDateTime)'
SET Month TO $fx'=Month(CurrentDateTime)'
SET Day TO $fx'=Day(CurrentDateTime)'
SET Hour TO $fx'=Hour(CurrentDateTime)'
SET Minute TO $fx'=Minute(CurrentDateTime)'
SET Second TO $fx'=Second(CurrentDateTime)'
DateTime.GetCurrentDateTime.Local DateTimeFormat: DateTime.DateTimeFormat.DateAndTime CurrentDateTime=> CurrentDateTimeTo
DateTime.Subtract FromDate: CurrentDateTimeTo SubstractDate: CurrentDateTime TimeUnit: DateTime.DifferenceTimeUnit.Seconds TimeDifference=> TimeDifference
Text.AppendLine Text: $fx'=Result' LineToAppend: $fx'DateTime：${TimeDifference}' Result=> Result
```

### ３．データテーブルの処理
以下のアクションの構成を用意。

1. 現在の日時を取得する
2. 年を取得
3. 月を取得
4. 日を取得
5. 時間を取得
6. 分を取得
7. 秒を取得

#### Robin式
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1064310/798d68dd-7d26-7f7b-8f8d-ad47720be455.png)

サブフロー名：DataTable
```Robin
DateTime.GetCurrentDateTime.Local DateTimeFormat: DateTime.DateTimeFormat.DateAndTime CurrentDateTime=> CurrentDateTime
Variables.CreateNewDatatable InputTable: { ^['No', 'Name', 'price', 'quantity'], ['1', 'りんご', '100', '10'], ['2', 'バナナ', '150', '30'], ['3', 'みかん', '50', '100'], ['4', 'いちご', '600', '5'] } DataTable=> DataTable
SET Name TO DataTable[2]['Name']
SET price TO DataTable[2]['price']
SET quantity TO DataTable[2]['quantity']
SET Name2 TO DataTable[3]['Name']
SET price2 TO DataTable[3]['price']
SET quantity2 TO DataTable[3]['quantity']
DateTime.GetCurrentDateTime.Local DateTimeFormat: DateTime.DateTimeFormat.DateAndTime CurrentDateTime=> CurrentDateTimeTo
DateTime.Subtract FromDate: CurrentDateTimeTo SubstractDate: CurrentDate
```

#### Power Fx式
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1064310/e1f39cbc-ace0-d3f9-0b5b-91ac642bfe9a.png)

サブフロー名：DataTable

```PowerFx
DateTime.GetCurrentDateTime.Local DateTimeFormat: DateTime.DateTimeFormat.DateAndTime CurrentDateTime=> CurrentDateTime
Variables.CreateNewDatatable InputTable: { ^['No', 'Name', 'price', 'quantity'], [$fx'1', $fx'りんご', $fx'100', $fx'10'], [$fx'2', $fx'バナナ', $fx'150', $fx'30'], [$fx'3', $fx'みかん', $fx'50', $fx'100'], [$fx'4', $fx'いちご', $fx'600', $fx'5'] } DataTable=> DataTable
SET Name TO $fx'=ReadCell(DataTable, 2, 2)'
SET price TO $fx'=ReadCell(DataTable, 2, 3)'
SET quantity TO $fx'=ReadCell(DataTable, 2, 4)'
SET Name2 TO $fx'=ReadCell(DataTable, 3, 2)'
SET price2 TO $fx'=ReadCell(DataTable, 3, 3)'
SET quantity2 TO $fx'=ReadCell(DataTable, 3, 4)'
DateTime.GetCurrentDateTime.Local DateTimeFormat: DateTime.DateTimeFormat.DateAndTime CurrentDateTime=> CurrentDateTimeTo
DateTime.Subtract FromDate: CurrentDateTimeTo SubstractDate: CurrentDateTime TimeUnit: DateTime.DifferenceTimeUnit.Seconds TimeDifference=> TimeDifference
Text.AppendLine Text: $fx'=Result' LineToAppend: $fx'DateTime：${TimeDifference}' Result=> Result
```

### Mainサブフロー

1. 処理結果を格納する変数を作成する
2. Loopアクションで10/100/1000回処理するように設定
3. 各サブフローを設定
4. 「メッセージを表示」アクションで処理結果を出力

#### Robin式
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1064310/26f401a9-ff74-c845-873a-b21d86549393.png)

```Robin
SET Result TO $'''【処理結果】'''
LOOP LoopIndex FROM 0 TO 99 STEP 1
    CALL Text
    CALL DateTime
    CALL DataTable
END
Display.ShowMessageDialog.ShowMessage Title: $'''結果''' Message: $'''ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
%Result%''' Icon: Display.Icon.None Buttons: Display.Buttons.OK DefaultButton: Display.DefaultButton.Button1 IsTopMost: False
```

#### Power Fx式
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1064310/dceb8077-10cc-fff9-3156-b2de21ea2c27.png)

```PowerFx
SET Result TO $'''【処理結果】'''
LOOP LoopIndex FROM $fx'=0' TO $fx'=99' STEP $fx'=1'
    CALL Text
    CALL DateTime
    CALL DataTable
END
Display.ShowMessageDialog.ShowMessage Title: $fx'結果' Message: $fx'ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
${Result}' Icon: Display.Icon.None Buttons: Display.Buttons.OK DefaultButton: Display.DefaultButton.Button1 IsTopMost: False
```

## 検証結果

### 実行方法
- コンソール画面から実行：10回、100回、1000回のパターンを実施
- Excelに貼り付けしてピポットで平均値や最大値、最小値を各項目ごと算出

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1064310/e5717e25-b466-aace-0772-44ec7b487454.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1064310/c0eb36c9-a642-871e-c3b2-573b8d1b3e14.png)


Robin（処理結果例）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1064310/f00081d4-c92a-9da8-b281-204b93d9b254.png)


Power Fx（処理結果例）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1064310/0b7cd24f-6e21-bb2d-cdb7-eece33189eb1.png)

### 結果
10回の繰り返し処理の結果を確認した際には、平均値的にRobinが優勢だが、100回、1000回と繰り返しの数が多くなると結果平均値もRobin/Power Fxいずれも大差ない結果に。

#### 10回

##### Robin
| 行ラベル  | 平均 / Result | 最大 / Result | 最小 / Result |
|-----------|----------------|---------------|---------------|
| DataTable | 0.02066657     | 0.0317785     | 0.0140079     |
| DateTime  | 0.01702213     | 0.0215287     | 0.0141931     |
| Text      | 0.01556457     | 0.0244214     | 0.0091521     |

##### Power Fx
| 行ラベル  | 平均 / Result | 最大 / Result | 最小 / Result |
|-----------|----------------|---------------|---------------|
| DataTable | 0.02176279     | 0.0298417     | 0.0167217     |
| DateTime  | 0.01927922     | 0.0226739     | 0.0152767     |
| Text      | 0.02396511     | 0.0920747     | 0.0117632     |

#### 100回

##### Robin
| 行ラベル  | 平均 / Result | 最大 / Result | 最小 / Result |
|-----------|----------------|---------------|---------------|
| DataTable | 0.023396935    | 0.0377812     | 0.0119186     |
| DateTime  | 0.019351007    | 0.0314656     | 0.0063211     |
| Text      | 0.017110962    | 0.0457964     | 0.0059414     |

##### Power Fx
| 行ラベル  | 平均 / Result | 最大 / Result | 最小 / Result |
|-----------|----------------|---------------|---------------|
| DataTable | 0.019823345    | 0.0323444     | 0.0068156     |
| DateTime  | 0.017555247    | 0.0318828     | 0.0073968     |
| Text      | 0.016781544    | 0.0952108     | 0.0026494     |

#### 1000回

##### Robin
| 行ラベル  | 平均 / Result | 最大 / Result | 最小 / Result |
|-----------|----------------|---------------|---------------|
| DataTable | 0.022469879    | 0.0479839     | 0             |
| DateTime  | 0.019291238    | 0.0471052     | 0             |
| Text      | 0.016778406    | 0.0340195     | 0             |

##### Power Fx
| 行ラベル  | 平均 / Result | 最大 / Result | 最小 / Result |
|-----------|----------------|---------------|---------------|
| DataTable | 0.022107727    | 0.0475319     | 0.0060216     |
| DateTime  | 0.019481452    | 0.0465129     | 0             |
| Text      | 0.016405282    | 0.089016      | 0             |
---


## まとめと考察
### 考察:thinking:

今回の検証結果から、以下の点を考察として挙げました。

1. **短期的パフォーマンス**:
   - 10回の繰り返し処理では、Robinの方が若干優勢な結果が見られました。Robinがシンプルなタスクに対して効率的であると推測できますが、結果からみても誤差レベルと考えています

2. **長期的パフォーマンス**:
   - 100回、1000回の繰り返し処理では、RobinとPower Fxのパフォーマンスに大きな差は見られませんでした。これにより、長期的な処理においてはどちらの言語も同等のパフォーマンスを発揮すると考えます

3. **処理の安定性**:
   - 両言語ともに、繰り返し回数が増えるにつれて、処理時間のばらつきが少なくなり、安定したパフォーマンスを示しました。特に、Power Fxは大規模なデータ処理においても安定した結果を提供することがわかりました。**←この結果を得られたのが重要:bangbang:**

※今回はシンプルな処理の処理時間比較をターゲットにしましたが、PCリソースの利用状況や他の処理（UI要素を扱う処理）など、比較したい項目が他にもあります。これらは今後の課題としたいと考えています。

###  まとめ:pencil2:

今回の検証では、Power FxよりもRobinのほうが処理がシンプルで、処理時間も短くなると考えていましたが、実際には大差ない結果となりました。Power Fxは従来のRobinとは記述式が異なるため、慣れるまでに時間が必要です。しかし、Power AppsやPower Automateのクラウドフローなどで言語が統一されている点から、状況に応じて活用したいと考えています。

2024年11月にGAしたばかりのPower Automate for desktopのPower Fxですが、問題なく業務にも耐えうると感じました。ただし、検証結果から見てもパフォーマンスに大差がないため、従来のRobinで開発し稼働しているフローを無理に移行する必要はまだないと感じています。
今後も、Power Fxの動向を注視していきたいと思います！

おわり。