Browse thread
Re: About array
- Anton Moscal
[
Home
]
[ Index:
by date
|
by threads
]
[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: | 1999-10-12 (14:24) |
From: | Anton Moscal <msk@p...> |
Subject: | Re: About array |
> On Sun, 10 Oct 1999, skaller wrote: > > > > > > Assignment to array element can be very ineffictive in O'Caml due to the > > > > following reasons: > > > > > > > > 1)O'Caml uses generational GC. > > This is only true for array containning pointer, not array of float or integer. This is true for array, which CAN contains pointer (i.e. for polymorphic type 'a array this is also true). > > But this raise the following question: > Is the function Array.init implemented to solve the GC problem mentioned above > ? I saw in array.ml sources and found the following implementations of Array.init: ======================== let init l f = if l = 0 then [||] else let res = create l (f 0) in for i = 1 to pred l do unsafe_set res i (f i) done; res ======================= I.e. answer is "No". Good implementation (even in assembly) is not so simple: immediately after memory allocation we can write to array without `modify' function call until first minor GC call. Evaluation `f i' can cause GC call -> we must use modify function. Really we can check address of our fresh array after each `f i'. While this address remains unchanged we have no need to call `modify'. I think this will be good. I made the following experiment: ============================== let inc a = Array.init (Array.length a) (fun i->a.(i)+1);; let rec test (a:int array) = function 0 -> a | n -> test (inc a) (n-1) ;; test (Array.create 1000 0) 2000;; ============================== runs 1.44 sec (on 586/133 mHz) (with -unsafe option). `init' is exact copy of Array.init. When I replace standard `init' function by the following code: ============================== let init l f = if l = 0 then [||] else let res = Array.create l (f 0) in let addr = ((Obj.magic res):int) lsr 1 in let res' = ((Obj.magic res):(int array)) in for i = 1 to pred l do let x = f i in if addr = ((Obj.magic res):int) lsr 1 then Array.unsafe_set res' i x else Array.unsafe_set res i x done; res ============================== time became 0.97 sec (but this version will not work with float arrays) Regards, Anton Moscal