[<Struct>]
type Vector3(x: float32, y: float32, z: float32) =
member this.X = x
member this.Y = y
member this.Z = z
type Data(n: int) =
let positions = System.Collections.Generic.List<Vector3>()
let add j = positions.Add (Vector3(j, j, j))
let add1 j = positions.Add (Vector3(j, j, j));()
member this.UseAdd() = for i = 1 to n do add (float32 i)
member this.UseAdd1() = for i = 1 to n do add1 (float32 i)
let timeIt name (f: unit -> unit) =
let timer = System.Diagnostics.Stopwatch.StartNew()
f()
printfn "%s: %ims" name (int timer.ElapsedMilliseconds)
let test() =
for i = 1 to 3 do timeIt "ADD" (fun() -> Data(1000000).UseAdd())
for i = 1 to 3 do timeIt "ADD1" (fun() -> Data(1000000).UseAdd1())
[<EntryPoint>]
let main argv =
test()
0
add
ve add1
arasındaki fark, sondaki fazladan ()
. Ben add
ve add1
aynı şekilde davranması gerektiğini beklenebilir
ADD: 461ms
ADD: 457ms
ADD: 450ms
ADD1: 25ms
ADD1: 26ms
ADD1: 16ms
List<T>.Add
tipine yana T -> unit
edilir: Ben .NET 4.5.1 F # 3.1 kullanarak x64 sürüm oluşturma olarak inşa
Bu çıktıyı almak .
ben add
için (sadece ilgili kısmı dahil) derler olduğunu tespit ettik ildasm kullanma
IL_000a: newobj instance void Program/Vector3::.ctor(float32,
float32,
float32)
IL_000f: tail.
IL_0011: callvirt instance void class [mscorlib]System.Collections.Generic.List`1<valuetype Program/Vector3>::Add(!0)
ise add1
"kuyruk çağrısı" olmadan
IL_000a: newobj instance void Program/Vector3::.ctor(float32,
float32,
float32)
IL_000f: callvirt instance void class [mscorlib]System.Collections.Generic.List`1<valuetype Program/Vector3>::Add(!0)
yani
içine. Yani kuyruk arama optimizasyonunu kapattığımda, hemadd
hem de
add1
aynı hızda çalışır.
tail.
yönergesi, işlev çağrısının neden bu kadar yavaş olmasına neden oluyor? Ayrıca, bu bir hata mı yoksa bir özellik mi?
DÜZENLEME: Bu orijinal kod burada, bu davranışı fark ettim. Sonunda true
değeri düştüğünde, yukarıdaki kodla aynı performans düşüşünü gösterir.
let makeAtom (ctx: CleanCifContext) (element: CleanCifAtomSiteElement) =
let residue = getResidue ctx element
let position =
Vector3(float32 (element.PositionX.ValueOrFail()), float32 (element.PositionY.ValueOrFail()), float32 (element.PositionZ.ValueOrFail()))
let atom =
CifAtom(id = ctx.Atoms.Count, element = element.ElementSymbol.ValueOrFail(),
residue = residue, serialNumber = element.Id.ValueOrFail(),
name = element.Name.ValueOrFail(), authName = element.AuthName.Value(), altLoc = element.AltLoc.Value(),
occupancy = float32 (element.Occupancy.ValueOrFail()), tempFactor = float32 (element.TempFactor.ValueOrFail()))
ctx.Atoms.Add atom
ctx.Positions.Add position
true
İlginçtir, yalnızca .NET 4 + 'da oluşur ve tutarsızlık x86'da veya "List" içindeki diğer veri türlerini kullanırken daha küçüktür. –
@DaxFohl Evet, x86'da da düşük olduğunu fark ettim.Ama kodumun 64-bit olması gerekiyor, bu yüzden bu veriyi ekledim. – Dave
Bunu RyuJIT veya normal eski JIT'de mi çalıştırdınız? Bağladığınız makale eskisiyle ilgili gibi görünüyor. –