- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
Note: I may have chosen the wrong word in the title; perhaps I'm really talking about polynomial growth here. See the benchmark result at the end of this question.
interface IStack<T>
{
INonEmptyStack<T, IStack<T>> Push(T x);
}
interface IEmptyStack<T> : IStack<T>
{
new INonEmptyStack<T, IEmptyStack<T>> Push(T x);
}
interface INonEmptyStack<T, out TStackBeneath> : IStack<T>
where TStackBeneath : IStack<T>
{
T Top { get; }
TStackBeneath Pop();
new INonEmptyStack<T, INonEmptyStack<T, TStackBeneath>> Push(T x);
}
EmptyStack<T>
,
NonEmptyStack<T,TStackBeneath>
.
Update #1: See the code below.
EmptyStack<int>
第一次需要超过 7 秒。 EmptyStack<int>
之后几乎不需要任何时间。 Update #2:
I've finally performed a more precise measurement. See the benchmark code and results below.
I've only discovered during these tests that .NET 3.5 doesn't seem to allow generic types with a recursion depth ≥ 100. .NET 4 doesn't seem to have this restriction.
EmptyStack<int>
NonEmptyStack<int, EmptyStack<int>>
NonEmptyStack<int, NonEmptyStack<int, EmptyStack<int>>>
NonEmptyStack<int, NonEmptyStack<int, NonEmptyStack<int, EmptyStack<int>>>>
T<U>
, T<T<U>>
, T<T<T<U>>>
,等等它们嵌套得越深,速度就越慢? †) Off-topic footnote: These types are quite interesting btw. because they allow the compiler to catch certain errors such as:
stack.Push(item).Pop().Pop();
// ^^^^^^
// causes compile-time error if 'stack' is not known to be non-empty.Or you can express requirements for certain stack operations:
TStackBeneath PopTwoItems<T, TStackBeneath>
(INonEmptyStack<T, INonEmptyStack<T, TStackBeneath> stack)
internal class EmptyStack<T> : IEmptyStack<T>
{
public INonEmptyStack<T, IEmptyStack<T>> Push(T x)
{
return new NonEmptyStack<T, IEmptyStack<T>>(x, this);
}
INonEmptyStack<T, IStack<T>> IStack<T>.Push(T x)
{
return Push(x);
}
}
// ^ this could be made into a singleton per type T
internal class NonEmptyStack<T, TStackBeneath> : INonEmptyStack<T, TStackBeneath>
where TStackBeneath : IStack<T>
{
private readonly T top;
private readonly TStackBeneath stackBeneathTop;
public NonEmptyStack(T top, TStackBeneath stackBeneathTop)
{
this.top = top;
this.stackBeneathTop = stackBeneathTop;
}
public T Top { get { return top; } }
public TStackBeneath Pop()
{
return stackBeneathTop;
}
public INonEmptyStack<T, INonEmptyStack<T, TStackBeneath>> Push(T x)
{
return new NonEmptyStack<T, INonEmptyStack<T, TStackBeneath>>(x, this);
}
INonEmptyStack<T, IStack<T>> IStack<T>.Push(T x)
{
return Push(x);
}
}
Console.WriteLine("N, t [ms]");
int outerN = 0;
while (true)
{
outerN++;
var appDomain = AppDomain.CreateDomain(outerN.ToString());
appDomain.SetData("n", outerN);
appDomain.DoCallBack(delegate {
int n = (int)AppDomain.CurrentDomain.GetData("n");
var stopwatch = new Stopwatch();
stopwatch.Start();
IStack<int> s = new EmptyStack<int>();
for (int i = 0; i < n; ++i)
{
s = s.Push(i); // <-- this "creates" a new type
}
stopwatch.Stop();
long ms = stopwatch.ElapsedMilliseconds;
Console.WriteLine("{0}, {1}", n, ms);
});
AppDomain.Unload(appDomain);
}
NonEmptyStack<EmptyStack<T>>
NonEmptyStack<NonEmptyStack<EmptyStack<T>>>
最佳答案
访问新类型会导致运行时将其从 IL 重新编译为 native 代码(x86 等)。运行时还会优化代码,这也会为值类型和引用类型产生不同的结果。
和List<int>
显然会以不同于 List<List<int>>
的方式进行优化.
因此也是EmptyStack<int>
和 NonEmptyStack<int, EmptyStack<int>>
等等将作为完全不同的类型处理,并且都将被“重新编译”和优化。
(据我所知!)
通过嵌套更多层,生成的类型的复杂性会增加,优化需要更长的时间。
因此,添加一层需要 1 步来重新编译和优化,下一层需要 2 步加上第一步(左右),第 3 层需要 1 + 2 + 3 步等。
关于.net - 递归泛型类型的实例化速度越慢,嵌套越深。为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7059900/
我是一名优秀的程序员,十分优秀!