Hello,
I'm writing a program using the object facilities provided by Objective Caml.
In this program, I have to write a tree structure, and the class hierarchy is
used to apply functions (which could be overwritten) to the tree nodes.
The program was quick to compile until soon. But when I added a new method in
one of the base class of the tree, the compilation time had been multiplied by
more than 300 (12s to more than one hour).
The inheritance structure is quite complex, so I dropped a lot of lines to make
an example that produce the same problem, but is less complex. I removed virtual
methods and most of methods:
(************** Start of the module ********************)
module OS =
struct
type t = string
let compare (s1 : string) (s2 : string) = Pervasives.compare s1 s2
end
module OSO=
struct
type t = string option
let compare (s1 : string option) (s2 : string option) =
match (s1, s2) with
(None, None) -> 0
| (None, Some _) -> -1
| (Some _, None) -> 1
| (Some v1, Some v2) -> Pervasives.compare v1 v2
end
module MapString = Map.Make OS
module MapStringOption = Map.Make OSO
class virtual node =
object (self)
val mutable children : childNode list = []
method sub_nodes = children
method append_subnode subnode =
children <- children@[subnode]
end
and rootNode =
object (self)
inherit node
end
and virtual childNode (parent : node) =
object (self)
inherit node
method get_parent : node = parent
(***********************************)
(* method that lead to problem when added *)
method collect_environment :
((referenceableRefNode * string) list * (userTypeRefNode * string) list *
(referenceableNode MapString.t) * (userTypeNode MapString.t)) MapStringOption.t ->
((referenceableRefNode * string) list * (userTypeRefNode * string) list *
(referenceableNode MapString.t) * (userTypeNode MapString.t)) MapStringOption.t =
fun env -> env (* should be List.fold_left (fun env (n : childNode) -> n#collect_environment env) env children *)
(***********************************)
and virtual typedNode (parent : node) =
object (self)
inherit childNode parent
end
and virtual typeBuilderNode (parent : node) =
object(self)
inherit typedNode parent
val mutable _content : typedNode option = None
method set_content : typedNode -> unit = fun content -> _content <- Some content
end
and virtual userTypeNode (parent : node) =
object(self)
inherit typeBuilderNode parent
end
and virtual baseTypeNode (name : string) (parent : node) =
object(self)
inherit typedNode parent
val mutable _name : string = name
end
and userTypeRefNode (name : string) (parent : node) =
object(self)
inherit baseTypeNode name parent
end
and virtual referenceableNode (parent : node) =
object
inherit typedNode parent
end
and virtual referenceableRefNode (parent : node) =
object
inherit typedNode parent
end
class stringTypeNode (base : string) (parent : node) =
object(self)
inherit baseTypeNode base parent
end
class integerTypeNode (base : string) (parent : node) =
object(self)
inherit baseTypeNode base parent
end
class booleanTypeNode (parent : node) =
object(self)
inherit baseTypeNode "boolean" parent
end
(***************************************
method that takes a lot of time to type
after collect_environment add been added into
childNode class
*)
let getTypeForName : node -> string -> typedNode =
fun parent_node type_name ->
match type_name with
"string" as _type -> (new stringTypeNode _type parent_node :> typedNode)
| "foo" as _type ->
failwith ("this type is not available yet: " ^ _type)
(* boolean type *)
| "boolean" -> (new booleanTypeNode parent_node :> typedNode)
(* integer types *)
| "integer" as _type -> (new integerTypeNode _type parent_node :> typedNode)
| ref -> (new userTypeRefNode ref parent_node :> typedNode)
(************** end of the module ******************)
If I compile this module with the method collect_environment, the compilation lasts
70 sec on my computer. If I drop it, it takes only 0.66s
If I change the type of the function and write it:
method collect_environment :
((node * string) list * (node * string) list * (node MapString.t) * (node MapString.t)) MapStringOption.t ->
((node * string) list * (node * string) list * (node MapString.t) * (node MapString.t)) MapStringOption.t =
fun env -> env (* should be List.fold_left (fun env (n : childNode) -> n#collect_environment env) env children *)
end
the compilation of the module lasts 1s.
Do you have any idea on the origin of this problem, and on the way to solve it ?
Thanks.
--
Michaël Marchegay, Stagiaire France Telecom R&D du 11/02/2002 au 26/07/2002
Sous la responsabilité d'Olivier Dubuisson
DTL/TAL - 22307 Lannion Cedex - France