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

AOT: skip HOCON-based Type loading for default implementations #7431

Open
Tracked by #7246
Aaronontheweb opened this issue Dec 20, 2024 · 0 comments
Open
Tracked by #7246

AOT: skip HOCON-based Type loading for default implementations #7431

Aaronontheweb opened this issue Dec 20, 2024 · 0 comments
Labels
AOT Ahead-of-Time (AOT) Compilation configuration
Milestone

Comments

@Aaronontheweb
Copy link
Member

Aaronontheweb commented Dec 20, 2024

Consider the following:

var providerType = Type.GetType(ProviderClass);
if (providerType == null)
throw new ConfigurationException($"'akka.actor.provider' is not a valid type name : '{ProviderClass}'");
if (!typeof(IActorRefProvider).IsAssignableFrom(providerType))
throw new ConfigurationException($"'akka.actor.provider' is not a valid actor ref provider: '{ProviderClass}'");

This creates a problem for AOT'd applications because of the type loading across assemblies, which is verbotten under AOT compilation rules. For these types of issues, we have to refer users to the configuration sources such as our Setup classes (which use direct references, not assembly loading - and therefore is kosher.)

But for other cases, such as:

Default Log Formatter

var logFormatType = Type.GetType(loggerFormatterName);
if (logFormatType == null)
throw new ArgumentException($"Could not load type of {loggerFormatterName} for ILogMessageFormatter.");
if(!typeof(ILogMessageFormatter).IsAssignableFrom(logFormatType))
throw new ArgumentException("Log formatter type must inherit from the ILogMessageFormatter interface.");

STD Out Logger

var stdoutLoggerType = Type.GetType(stdoutClassName);
if (stdoutLoggerType == null)
throw new ArgumentException($"Could not load type of {stdoutClassName} for standard out logger.");
if(!typeof(MinimalLogger).IsAssignableFrom(stdoutLoggerType))
throw new ArgumentException("Standard out logger type must inherit from the MinimalLogger abstract class.");

Mailboxes

var requirements = mailboxConfig.GetConfig("requirements").AsEnumerable().ToList();
_mailboxBindings = new Dictionary<Type, string>();
foreach (var kvp in requirements)
{
var type = Type.GetType(kvp.Key);
if (type == null)
{
Warn($"Mailbox Requirement mapping [{kvp.Key}] is not an actual type");
continue;
}
_mailboxBindings.Add(type, kvp.Value.GetString());
}
_defaultMailboxConfig = Settings.Config.GetConfig(DefaultMailboxId);

Scheduler

private void ConfigureScheduler()
{
var schedulerType = Type.GetType(_settings.SchedulerClass, true);
_scheduler = (IScheduler) Activator.CreateInstance(schedulerType, _settings.Config, Log);

Dispatchers

Dispatchers are an example of where we already implement "the fix" I'm going to suggest for making Akka.NET's configuration system more AOT-friendly - skipping reflection and resolving known types when we know the HOCON matches a type that is already part of the core Akka assembly:

switch (type)
{
case "Dispatcher":
dispatcher = new DispatcherConfigurator(cfg, Prerequisites);
break;
case "TaskDispatcher":
dispatcher = new DispatcherConfigurator(TaskExecutorConfig.WithFallback(cfg), Prerequisites);
break;
case "PinnedDispatcher":
dispatcher = new PinnedDispatcherConfigurator(cfg, Prerequisites);
break;
case "ForkJoinDispatcher":
dispatcher = new DispatcherConfigurator(ForkJoinExecutorConfig.WithFallback(cfg), Prerequisites);
break;
case "SynchronizedDispatcher":
dispatcher = new CurrentSynchronizationContextDispatcherConfigurator(cfg, Prerequisites);
break;
case null:
throw new ConfigurationException($"Could not resolve dispatcher for path {id}. type is null");
default:
Type dispatcherType = Type.GetType(type);
if (dispatcherType == null)
{
throw new ConfigurationException($"Could not resolve dispatcher type {type} for path {id}");
}
dispatcher =
(MessageDispatcherConfigurator)Activator.CreateInstance(dispatcherType, cfg, Prerequisites);
break;
}

Custom Mailboxes, Dispatchers, Etc

Doing AOT with customizable components like a user-defined Mailbox or Dispatcher configuration is going to be more challenging. If Akka.Hosting is still AOT-friendly (which I assume it is, beyond the parts of core Akka that are not) then we could probably introduce some custom Setup classes that allow these types to be passed in by reference rather than dynamically loaded from an assembly. That will likely need to be a second phase of AOT support after the core library is cleaned up.

@Aaronontheweb Aaronontheweb changed the title HOCON-based Type loading - this is all dynamic linking, which is strictly verbotten in AOT (100% static linking.) AOT: skip HOCON-based Type loading for default implementations Dec 20, 2024
@Aaronontheweb Aaronontheweb added AOT Ahead-of-Time (AOT) Compilation configuration labels Dec 20, 2024
@Aaronontheweb Aaronontheweb added this to the 1.6.0 milestone Dec 20, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
AOT Ahead-of-Time (AOT) Compilation configuration
Projects
None yet
Development

No branches or pull requests

1 participant