0

我正在为企业解决方案编写数据适配器。

为了使其可扩展,我将其设计为:

  1. 有一个接口定义了所有数据方法的签名
  2. 该接口在各种低级适配器中实现,方法在这些适配器中实现,这些适配器如 SqlAdapter、OracleAdapter、MySqlAdapter、XmlAdapter 等。它们在 2MB 左右并不是很大。
  3. 我创建了一个外观层,它在运行时使用配置调用与底层适配器绑定并调用它的方法。
  4. 这个外观在消费者之间共享,他们可以在不知道底层适配器的情况下调用使用它的方法。
  5. 要创建一个门面,我必须创建这个门面单吨。

为了使其可扩展,我采用了以下方法

  1. 将这种单吨模式更改为基于多实例(工厂模式),使实例数量可配置(对象池)。使用异步执行底层方法(使用异步等待)。

  2. 仅使用 Single Ton 实例,但使用 Semaphore 处理并发请求数。异步执行底层方法(使用异步等待),使用连接池,以便对底层方法的异步调用可以使用到数据库的多个连接。

问题:1)如果我选择创建多个实例的第一种方法,它会更快吗?加载底层适配器不会花费更多时间,因此它会比第二种方法慢吗?如果我克隆对象怎么办?

2)如果我选择第二种方法会更快吗?由于 Single Ton 对象仅中继请求和响应,因此后台的所有工作都将是异步的。

考虑到对象重新/加载,哪种方法在性能方面更好?还是有其他好的方法?假设每秒向服务器发送 1000 个请求。

4

2 回答 2

1

我会用一个静态类来包装我对工厂的调用,可能是“FactoryInitializer”,它有一个接受适配器类型的通用方法,例如:

public interface IDataAdapter
{
    //Your methods
}

internal class SqlAdapter : IDataAdapter
{
    //This is your concrete class where a specific adapter related stuff goes
    //You can create more of these concrete types as separate classes.
}

internal class BaseFactory
{
    public virtual IDataAdapter GetDataAdapter()
    {
        return null;
    }
}

internal class SqlFactory : BaseFactory
{
    public override IDataAdapter GetDataAdapter()
    {
        return new SqlFactory();
    }
}

internal static class FactoryInitializer
{
    public static IDataAdapter LoadAdapterOf<T>() where T : BaseFactory, new()
    {
        var factory = new T();
        return factory.GetDataAdapter();
    }
}

然后将其用作:

var sqlAdapter = FactoryInitializer.LoadAdapterOf<SqlFactory>();
于 2013-05-28T12:33:05.743 回答
1

为了更快和更可预测的实例化,应预加载包含适配器实现的所有程序集。这是相当昂贵的操作。在此之后,您基本上有三个选择:

  1. 重用适配器实例。对每种适配器类型使用池。如果适配器的内存占用很大并且频繁分配新实例会很快使您的堆碎片化,则此选项是可取的。
  2. 为每个请求创建新的适配器实例。如果适配器具有一些内部状态但内存占用相对较小,则此选项更可取。这些适配器将是第 0 代垃圾收集的良好候选者,在 .NET 4.5 中速度更快,甚至更快。
  3. 重用适配器实例。根本没有汇集。仅当您的适配器根本没有任何状态时,此选项才可能。这意味着没有竞争条件和同步。

更新:如果您选择第一个选项并且会因为太多和/或太大的适配器实例工作时间过长而出现内存问题,那么您可能需要考虑从“实时”处理模型切换到延迟处理。创建一个请求队列,实时推送请求,并使用某种调度程序将它们分批提取以进行处理。

于 2013-05-28T13:01:10.850 回答