You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by pt...@apache.org on 2022/10/03 06:33:27 UTC

[ignite-3] branch main updated: IGNITE-17794 .NET: Fix source generators performance (#1148)

This is an automated email from the ASF dual-hosted git repository.

ptupitsyn pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git


The following commit(s) were added to refs/heads/main by this push:
     new c6b73457fa IGNITE-17794 .NET: Fix source generators performance (#1148)
c6b73457fa is described below

commit c6b73457fa0865b525d8dcc9179b7e70e5f4665e
Author: Pavel Tupitsyn <pt...@apache.org>
AuthorDate: Mon Oct 3 09:33:21 2022 +0300

    IGNITE-17794 .NET: Fix source generators performance (#1148)
    
    Generate code only on build. Do not generate when C# code changes, because the logic is based only on Java code. Fixes potentially degraded IDE performance due to unnecessary processing.
---
 .../ErrorGroupsGenerator.cs                        | 13 ++---
 .../ExceptionsGenerator.cs                         | 18 +++----
 .../JavaToCsharpGeneratorBase.cs                   | 59 ++++++++++++++++++++++
 3 files changed, 69 insertions(+), 21 deletions(-)

diff --git a/modules/platforms/dotnet/Apache.Ignite.Internal.Generators/ErrorGroupsGenerator.cs b/modules/platforms/dotnet/Apache.Ignite.Internal.Generators/ErrorGroupsGenerator.cs
index 764ecc3cd5..f975e22274 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Internal.Generators/ErrorGroupsGenerator.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Internal.Generators/ErrorGroupsGenerator.cs
@@ -18,6 +18,7 @@
 namespace Apache.Ignite.Internal.Generators
 {
     using System;
+    using System.Collections.Generic;
     using System.Globalization;
     using System.IO;
     using System.Linq;
@@ -30,16 +31,10 @@ namespace Apache.Ignite.Internal.Generators
     /// Generates error groups source from ErrorGroups.java.
     /// </summary>
     [Generator]
-    public sealed class ErrorGroupsGenerator : ISourceGenerator
+    public sealed class ErrorGroupsGenerator : JavaToCsharpGeneratorBase
     {
         /// <inheritdoc/>
-        public void Initialize(GeneratorInitializationContext context)
-        {
-            // No-op.
-        }
-
-        /// <inheritdoc/>
-        public void Execute(GeneratorExecutionContext context)
+        protected override IEnumerable<(string Name, string Code)> ExecuteInternal(GeneratorExecutionContext context)
         {
             var javaErrorGroupsFile = Path.GetFullPath(Path.Combine(
                 context.GetJavaModulesDirectory(),
@@ -144,7 +139,7 @@ namespace Apache.Ignite.Internal.Generators
             sb.AppendLine("    }");
             sb.AppendLine("}");
 
-            context.AddSource("ErrorGroups.g.cs", sb.ToString());
+            yield return ("ErrorGroups.g.cs", sb.ToString());
         }
 
         private static string SnakeToCamelCase(string str) =>
diff --git a/modules/platforms/dotnet/Apache.Ignite.Internal.Generators/ExceptionsGenerator.cs b/modules/platforms/dotnet/Apache.Ignite.Internal.Generators/ExceptionsGenerator.cs
index 0bd353f5a0..a4cfc4b558 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Internal.Generators/ExceptionsGenerator.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Internal.Generators/ExceptionsGenerator.cs
@@ -31,16 +31,10 @@ namespace Apache.Ignite.Internal.Generators
     /// Generates exception classes from Java exceptions.
     /// </summary>
     [Generator]
-    public sealed class ExceptionsGenerator : ISourceGenerator
+    public sealed class ExceptionsGenerator : JavaToCsharpGeneratorBase
     {
         /// <inheritdoc/>
-        public void Initialize(GeneratorInitializationContext context)
-        {
-            // No-op.
-        }
-
-        /// <inheritdoc/>
-        public void Execute(GeneratorExecutionContext context)
+        protected override IEnumerable<(string Name, string Code)> ExecuteInternal(GeneratorExecutionContext context)
         {
             var javaModulesDirectory = context.GetJavaModulesDirectory();
 
@@ -88,12 +82,12 @@ namespace Apache.Ignite.Internal.Generators
                     .Replace("XMLDOC", GetXmlDoc(className, javaException.Value.Source))
                     .Replace("NAMESPACE", dotNetNamespace);
 
-                context.AddSource(className + ".g.cs", src);
+                yield return (className + ".g.cs", src);
 
                 classMap.Add((javaPackage + "." + className, dotNetNamespace + "." + className));
             }
 
-            EmitClassMap(context, classMap);
+            yield return EmitClassMap(classMap);
 
             bool IsIgniteException(string? ex) =>
                 ex != null &&
@@ -101,7 +95,7 @@ namespace Apache.Ignite.Internal.Generators
                  IsIgniteException(javaExceptionsWithParents.TryGetValue(ex, out var parent) ? parent.Parent : null));
         }
 
-        private static void EmitClassMap(GeneratorExecutionContext context, List<(string JavaClass, string DotNetClass)> classMap)
+        private static (string Name, string Code) EmitClassMap(List<(string JavaClass, string DotNetClass)> classMap)
         {
             var sb = new StringBuilder();
 
@@ -127,7 +121,7 @@ namespace Apache.Ignite.Internal.Generators
             sb.AppendLine("    }");
             sb.AppendLine("}");
 
-            context.AddSource("ExceptionMapper.g.cs", sb.ToString());
+            return ("ExceptionMapper.g.cs", sb.ToString());
         }
 
         private static string GetXmlDoc(string javaClassName, string javaSource)
diff --git a/modules/platforms/dotnet/Apache.Ignite.Internal.Generators/JavaToCsharpGeneratorBase.cs b/modules/platforms/dotnet/Apache.Ignite.Internal.Generators/JavaToCsharpGeneratorBase.cs
new file mode 100644
index 0000000000..8ca75a8a3d
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Internal.Generators/JavaToCsharpGeneratorBase.cs
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Apache.Ignite.Internal.Generators;
+
+using System.Collections.Generic;
+using System.Linq;
+using Microsoft.CodeAnalysis;
+
+/// <summary>
+/// Base class for Java -> C# source generators.
+/// <para />
+/// <c>IIncrementalGenerator</c> is not used because it makes directory detection too hard.
+/// <see cref="GeneratorInitializationContext.RegisterForPostInitialization"/> is not used for the same reason.
+/// </summary>
+public abstract class JavaToCsharpGeneratorBase : ISourceGenerator
+{
+    private List<(string Name, string Code)>? _generatedCode;
+
+    /// <inheritdoc/>
+    public void Initialize(GeneratorInitializationContext context)
+    {
+        // No-op.
+    }
+
+    /// <inheritdoc/>
+    public void Execute(GeneratorExecutionContext context)
+    {
+        // Execute the generator only once during full build.
+        // Do not execute otherwise (while C# code is being changed).
+        _generatedCode ??= ExecuteInternal(context).ToList();
+
+        foreach (var (name, code) in _generatedCode)
+        {
+            context.AddSource(name, code);
+        }
+    }
+
+    /// <summary>
+    /// Called to perform source generation.
+    /// </summary>
+    /// <param name="context">The <see cref="GeneratorExecutionContext"/> to add source to.</param>
+    /// <returns>Generated code.</returns>
+    protected abstract IEnumerable<(string Name, string Code)> ExecuteInternal(GeneratorExecutionContext context);
+}