パフォーマンス改善対象のソースコードの難度は高く、1週間くらいかかると当初は見積もっていた作業が、ChatGPTに依頼したら、実行結果の検証も含めて半日でおわりました。
ChatGPTに依頼
「下記C#ソースコードのパフォーマンスを改善して。説明は日本語で。」と依頼。
ChatGPTに依頼した全文。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
下記C#ソースコードのパフォーマンスを改善して。説明は日本語で。 var groupedRecords = outputSource .GroupBy(d => string.Join(",", d.Properties .Where(p => GroupKeys.Any(gk => gk.Sequence == p.Sequence && gk.PropertyName == p.PropertyName)) .OrderBy(p => p.Sequence) .Select(p => p.PropertyName + ":" + p.PropertyValue))) .Select((g, index) => { var groupRecord = new SalesJournalizingOutput(); foreach (var prop in g.First().Properties) { if (!GroupKeys.Any(gk => gk.Sequence == prop.Sequence && gk.PropertyName == prop.PropertyName)) { var totalAmount = g.Sum(r => (decimal?)r.Properties.FirstOrDefault(p => p.PropertyName == prop.PropertyName && p.Sequence == prop.Sequence)?.PropertyValue) ?? 0; groupRecord.AddProperty(new PropertyDefinition() { Sequence = prop.Sequence, PropertyName = prop.PropertyName, PropertyValue = totalAmount.ToString(), FieldName = prop.FieldName, }); } else { if (prop.PropertyName == nameof(SalesJournalizing.GroupingNo)) { groupRecord.AddProperty(new PropertyDefinition() { Sequence = prop.Sequence, PropertyName = prop.PropertyName, PropertyValue = (long)(index + 1), FieldName = prop.FieldName, }); } groupRecord.AddProperty(new PropertyDefinition() { Sequence = prop.Sequence, PropertyName = prop.PropertyName, PropertyValue = prop.PropertyValue, FieldName = prop.FieldName, }); } } return groupRecord; }).ToList(); |
ChatGPTからの回答
ChatGPTの説明全文
1 2 3 4 5 6 7 8 9 10 11 |
このコードにはいくつかのパフォーマンス上の問題点があります。以下にそれらの問題点と改善策を挙げていきます。 繰り返しの線形探索:Any()とFirstOrDefault()の繰り返し使用は、特にネストされたループ内での実行時にコードの複雑さを増加させます。 キーの生成の繰り返し: グルーピングキーは、string.Joinその後のロジックの中で複数回生成されています。 これらの点を考慮して、以下のようにコードをリファクタリングします。 改善の要点: GroupKeysのルックアップテーブルをHashSet作成し、O(1) の時間で存在チェックが可能になりました。 string.Joinでのグルーピングキーの生成を効率的に行うためのフィルタリングを改善しました。 この改善により、特にGroupKeys要素数が多い場合には、素晴らしいパフォーマンスの向上が期待できます。 |
ChatGPTが生成したソースコード全文
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
var groupKeysSet = new HashSet<string>(GroupKeys.Select(gk => gk.Sequence + gk.PropertyName)); var groupedRecords = outputSource .GroupBy(d => string.Join(",", d.Properties .Where(p => groupKeysSet.Contains(p.Sequence + p.PropertyName)) .OrderBy(p => p.Sequence) .Select(p => p.PropertyName + ":" + p.PropertyValue))) .Select((g, index) => { var key = prop.Sequence + prop.PropertyName; foreach (var prop in g.First().Properties) { if (!groupKeysSet.Contains(key)) { var totalAmount = g.Sum(r => (decimal?)r.Properties.FirstOrDefault(p => p.PropertyName == prop.PropertyName && p.Sequence == prop.Sequence)?.PropertyValue) ?? 0; groupRecord.AddProperty(new PropertyDefinition() { Sequence = prop.Sequence, PropertyName = prop.PropertyName, PropertyValue = totalAmount.ToString(), FieldName = prop.FieldName, }); } else { if (prop.PropertyName == nameof(SalesJournalizing.GroupingNo)) { groupRecord.AddProperty(new PropertyDefinition() { Sequence = prop.Sequence, PropertyName = prop.PropertyName, PropertyValue = (long)(index + 1), FieldName = prop.FieldName, }); } groupRecord.AddProperty(new PropertyDefinition() { Sequence = prop.Sequence, PropertyName = prop.PropertyName, PropertyValue = prop.PropertyValue, FieldName = prop.FieldName, }); } } return groupRecord; }).ToList(); |
修正前後のソースコード比較
違いは軽微ですが、処理時間は15分から1秒に短縮しました。生成AI時代すごい!
コメント