type Expr =
| Lit of int
| Add of Expr * Expr
let rec intr = function
| Lit _ as x -> x
| Add(Lit a,Lit b) -> Lit <| a + b
| Add(a,b) -> intr <| Add(intr a, intr b)
let rec intr_cps x ret =
match x with
| Lit _ as x -> ret x
| Add(Lit a,Lit b) -> Lit (a + b) |> ret
| Add(a,b) ->
intr_cps a <| fun a ->
intr_cps b <| fun b ->
intr_cps (Add(a, b)) ret
let rec add n =
if n > 1 then Add(Lit 1, add (n-1))
else Lit 1
open System.Threading
let mem = 1024*1024*512 // ~536mb
// It stack overflows without being spun on a separate thread.
// By default, the program only has a few mb of stack memory at its disposal.
let run f = Thread(ThreadStart f,mem).Start()
run <| fun _ ->
let f n =
let x = add n
let stopwatch = System.Diagnostics.Stopwatch.StartNew()
printfn "%A" (intr x)
printfn "n_%i_std = %A" n stopwatch.Elapsed
stopwatch.Restart()
printfn "%A" (intr_cps x id)
printfn "n_%i_cps = %A" n stopwatch.Elapsed
f <| 1000*1000/2
f <| 1000*1000
f <| 1000*1000*2
//Lit 500000
//n_500000_std = 00:00:00.7764730
//Lit 500000
//n_500000_cps = 00:00:00.0800371
//Lit 1000000
//n_1000000_std = 00:00:02.9531043
//Lit 1000000
//n_1000000_cps = 00:00:00.1941828
//Lit 2000000
//n_2000000_std = 00:00:13.7823780
//Lit 2000000
//n_2000000_cps = 00:00:00.2767752
Performans davranışlarımı daha iyi anlamaya çalıştığım daha büyük bir yorumlayıcım var. Eminim ki, bazı örneklerde gördüğüm süper lineer zaman ölçeklendirmesi, yığının kullanıldığı yöntemle ilgilidir, ancak bunun neden böyle olduğundan emin değilim, bu yüzden burada sormak istedim.Yığının derin kullanımı neden basit bir tercüman için süper-doğrusal zaman davranışına yol açıyor?
Gördüğünüz gibi, n
'u 2x değiştirdiğimde, zaman bundan çok daha fazla değişiyor ve ölçeklendirme üssel olarak bana benziyor. Ayrıca CPS'd yorumlayıcısının yığına dayalı olandan daha hızlı olması şaşırtıcıdır. Neden?
Ayrıca, .NET ile aynı olmayan bir dilde veya hatta C'de yukarıdakilerin eşdeğerini kodlarsam aynı davranışı görüp görmeyeceğimi de sormak isterim.
Vay, bu iyi bir şekilde görülüyor. Kesinlikle ağacın inşasını ölçmek istemedim. Bu soruyu şimdi gönderdiğime sevindim. Ayrıca çevirmenimi CPS'ye dönüştürerek daha iyi bir performans elde edebileceğimi fark ettim. Yığın versiyonunun neden bu kadar uzun sürdüğü sorusu hala kapmak içindir. –