Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Natasha 预热优化 #69

Closed
NMSAzulX opened this issue Sep 7, 2021 · 5 comments
Closed

Natasha 预热优化 #69

NMSAzulX opened this issue Sep 7, 2021 · 5 comments

Comments

@NMSAzulX
Copy link
Collaborator

NMSAzulX commented Sep 7, 2021

我原本是使用NatashaInitializer.Initialize();
使用是正常的,但是我每次调用构建都要2秒的时间,感觉太费时间了。
所以就想到了InitializeAndPreheating();,可是我调用这个就报错。

Natasha版本:3.1.0.0
测试代码和错误信息如下:

测试代码:

using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using Natasha.CSharp;
using System.Threading.Tasks;

namespace MyNameSpace
{
    [TestClass()]
    public class MyClassTest
    {
        [TestMethod()]
        public void Natasha_测试()
        {
            //仅仅注册组件 这个初始化是可以正常使用的,就是每次都要2秒左右,很耗费时间。
            NatashaInitializer.Initialize();
            for (int i = 0; i < 10; i++)
            {
                var start = DateTime.Now;
                Natasha测试一次();
                Console.WriteLine($"第{i}次查询用时:{(DateTime.Now - start).TotalSeconds}秒");
            }
        }
        [TestMethod()]
        public async Task Natasha_测试Async()
        {
            //注册+预热组件 , 之后编译会更加快速 可是这个调用报错了,想知道我应该怎么做
            await NatashaInitializer.InitializeAndPreheating();
            for (int i = 0; i < 10; i++)
            {
                var start = DateTime.Now;
                Natasha测试一次();
                Console.WriteLine($"第{i}次查询用时:{(DateTime.Now - start).TotalSeconds}秒");
            }
        }
        private void Natasha测试一次()
        {
            var newClassName = $"{nameof(BaseModel)}_{new Random().Next(int.MaxValue)}";
            var action = FastMethodOperator.DefaultDomain(option =>
            {
                option.Add($@"
                namespace MyNameSpace
                {{
                    public class {newClassName} : {nameof(BaseModel)}
                    {{
                        public override string Name => ""OveName"";
                    }}
                }}");
            })
            .Param(typeof(string), "inValue")
            .Body($@"
                var obj = new {newClassName}();
                return obj.Show(inValue);
                ")
            .Return<string>()
            .Compile<Func<string, string>>();
            var result = action("aaabbb");
            Console.WriteLine($"result:{result}");
        }
    }
    public class BaseModel
    {
        public virtual string Name => "BaseName";
        public string Show(string inValue)
        {
            Console.WriteLine($"ClassName:{this.GetType().Name},Name:{Name},InValue:{inValue}");
            return $"Result {inValue}";
        }
    }
}

错误信息:

 Natasha_测试Async
   源: ZzwTest.cs 行 24
   持续时间: 2.1 秒

  消息: 
    Test method MyNameSpace.MyClassTest.Natasha_测试Async threw exception: 
    Natasha.Error.NatashaException: 编译错误 : CS8021 找不到 RuntimeMetadataVersion 的值。找不到包含 System.Object 的程序集,或未通过选项为 RuntimeMetadataVersion 指定值。
  堆栈跟踪: 
    AssemblyCSharpBuilder.GetAssembly()
    AssemblyBuilderExtension.GetTypeFromShortName(AssemblyCSharpBuilder builder, String typeName)
    AssemblyBuilderExtension.GetMethodFromShortName(AssemblyCSharpBuilder builder, String typeName, String methodName)
    AssemblyBuilderExtension.GetDelegateFromShortName(AssemblyCSharpBuilder builder, String typeName, String methodName, Type delegateType, Object target)
    AssemblyBuilderExtension.GetDelegateFromShortName[T](AssemblyCSharpBuilder builder, String typeName, String methodName, Object target)
    MethodBuilder`1.Compile[S](Object target)
    DelegateOperator`1.Delegate(String content, AssemblyCSharpBuilder builder, Action`1 option, Func`2 methodAction, Func`2 oopAction, NamespaceConverter[] usings)
    NDelegate.Action(String content)
    NatashaInitializer.InitializeAndPreheating(Boolean initializeReference)
    MyClassTest.Natasha_测试Async() 行 27
    ThreadOperations.ExecuteWithAbortSafety(Action action)

Originally posted by @zhangzw218 in #68

@NMSAzulX
Copy link
Collaborator Author

NMSAzulX commented Sep 7, 2021

image
初步排查的耗时情况.

Core3.1 Debug.exe 运行:
image

@NMSAzulX
Copy link
Collaborator Author

NMSAzulX commented Sep 7, 2021

阶段 活动项目 使用内存
预热 默认域程序集扫描与缓存 21M
预热 Natasha模板拼接及脚本生成 11M
预热 Roslyn 脚本到语法树转换 7M
预热 语法格式化环境创建 16M
预热 向编译单元添加语法树 19M
预热 编译输出程序集 3M

@NMSAzulX
Copy link
Collaborator Author

NMSAzulX commented Sep 8, 2021

空引用已修复,参见新版.

@NMSAzulX
Copy link
Collaborator Author

今日我们使用了最新语法树格式化函数, 它为 Natasha 减少了 520ms 的耗时, 减少了近 15M 的内存占用.

@NMSAzulX
Copy link
Collaborator Author

截至目前, 性能优化结果: 预热需要 1400ms 左右, 编译一次需要 380ms 左右(其中无用 using 语义简化处理占用约 100ms).

@NMSAzulX NMSAzulX changed the title InitializeAndPreheating() 耗时较多且内部报错. Natasha 预热优化 Nov 19, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant