From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Original-To: caml-list@sympa.inria.fr Delivered-To: caml-list@sympa.inria.fr Received: from mail2-relais-roc.national.inria.fr (mail2-relais-roc.national.inria.fr [192.134.164.83]) by sympa.inria.fr (Postfix) with ESMTPS id AAECD7EE89 for ; Wed, 25 Oct 2017 15:48:19 +0200 (CEST) Authentication-Results: mail2-smtp-roc.national.inria.fr; spf=None smtp.pra=ivg@ieee.org; spf=Pass smtp.mailfrom=ivg@ieee.org; spf=None smtp.helo=postmaster@mail-yw0-f179.google.com Received-SPF: None (mail2-smtp-roc.national.inria.fr: no sender authenticity information available from domain of ivg@ieee.org) identity=pra; client-ip=209.85.161.179; receiver=mail2-smtp-roc.national.inria.fr; envelope-from="ivg@ieee.org"; x-sender="ivg@ieee.org"; x-conformance=sidf_compatible Received-SPF: Pass (mail2-smtp-roc.national.inria.fr: domain of ivg@ieee.org designates 209.85.161.179 as permitted sender) identity=mailfrom; client-ip=209.85.161.179; receiver=mail2-smtp-roc.national.inria.fr; envelope-from="ivg@ieee.org"; x-sender="ivg@ieee.org"; x-conformance=sidf_compatible; x-record-type="v=spf1" Received-SPF: None (mail2-smtp-roc.national.inria.fr: no sender authenticity information available from domain of postmaster@mail-yw0-f179.google.com) identity=helo; client-ip=209.85.161.179; receiver=mail2-smtp-roc.national.inria.fr; envelope-from="ivg@ieee.org"; x-sender="postmaster@mail-yw0-f179.google.com"; x-conformance=sidf_compatible IronPort-PHdr: =?us-ascii?q?9a23=3AEawOzBRfg4N0ziFAXg+eeciULdpsv+yvbD5Q0YIu?= =?us-ascii?q?jvd0So/mwa67YxaN2/xhgRfzUJnB7Loc0qyN7PCmBDRIyK3CmU5BWaQEbwUCh8?= =?us-ascii?q?QSkl5oK+++Imq/EsTXaTcnFt9JTl5v8iLzG0FUHMHjew+a+SXqvnY6Uy/yPgtt?= =?us-ascii?q?J+nzBpWaz4Huj7jzqNXvZFBWjTa8ZJtoJRmxswjV8NML0qV4LaNk6wXApDNnfP?= =?us-ascii?q?hR22hoJE6I10L9+MiY/ZNu/mJXof13pJ0IarnzY6ltFe8QNz8hKW1goZSz7RQ?= =?us-ascii?q?=3D?= X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: =?us-ascii?q?A0D4AgDnlPBZh7OhVdFcHAEBBAEBCgEBF?= =?us-ascii?q?gEBAQMBAQEJAQEBhQYnB4NzgTaXdIF6iEuNf4EiA1wKhTsChGUHRBMBAQEBAQE?= =?us-ascii?q?BAQEBARIBAQEIDQkIKC+COAUBHgEFgjsBAQEDASMdAQE3AQQLCQILDSoCAiEBE?= =?us-ascii?q?gEFARwZCIoAAwgFCItNkRtAiyFrgieDCAEBBYQwDYNEAQEBAQEFAQEBAQEbCBK?= =?us-ascii?q?DHIIHgVCEBoENgl6Bb4NMgmGhPDyPfoR5kyaNDYhgFAUfgRU3gXuBBwhJNQaCK?= =?us-ascii?q?YJNH4IPJDYBikaBVQEBAQ?= X-IPAS-Result: =?us-ascii?q?A0D4AgDnlPBZh7OhVdFcHAEBBAEBCgEBFgEBAQMBAQEJAQE?= =?us-ascii?q?BhQYnB4NzgTaXdIF6iEuNf4EiA1wKhTsChGUHRBMBAQEBAQEBAQEBARIBAQEID?= =?us-ascii?q?QkIKC+COAUBHgEFgjsBAQEDASMdAQE3AQQLCQILDSoCAiEBEgEFARwZCIoAAwg?= =?us-ascii?q?FCItNkRtAiyFrgieDCAEBBYQwDYNEAQEBAQEFAQEBAQEbCBKDHIIHgVCEBoENg?= =?us-ascii?q?l6Bb4NMgmGhPDyPfoR5kyaNDYhgFAUfgRU3gXuBBwhJNQaCKYJNH4IPJDYBika?= =?us-ascii?q?BVQEBAQ?= X-IronPort-AV: E=Sophos;i="5.43,431,1503352800"; d="scan'208,217";a="297867294" Received: from mail-yw0-f179.google.com ([209.85.161.179]) by mail2-smtp-roc.national.inria.fr with ESMTP/TLS/AES128-GCM-SHA256; 25 Oct 2017 15:48:18 +0200 Received: by mail-yw0-f179.google.com with SMTP id k11so44659ywh.1 for ; Wed, 25 Oct 2017 06:48:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ieee-org.20150623.gappssmtp.com; s=20150623; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc; bh=MdMuadAlZhomRouj+v+lSgen74+EN+RfKdLa2fMhlfM=; b=LhPaNPE7COrlT+7dW2Lla4fR/jeZOvNE5ovydZ2NHB5ctooVvAnY54/xJjkYaZRH9j pH/duWNAvZBUBZo1elEopsZdYvL0r/7PowHMqIJZ7fvR+2TE4UP9MZ+XWmyX7eM/ZjSt xXSlcDBkvJCdkiy5rRP4VS8jPvtqVdSabnjMumVvd00D0vuK5t7pwUtJszn1swWgRWpM rti4HgwQlEQOs5sxxfjXXQChZPWJywSaJpjBR6CATDmITg6szpd/gq5X0xwC+lhHQqDm tdtC+LBOewzlp7SpmzV4SRD3AD9qSnrGVX1UYakrlutuClmRFwctVJaRuBC2dBUTmiI2 MkYg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc; bh=MdMuadAlZhomRouj+v+lSgen74+EN+RfKdLa2fMhlfM=; b=HQGZ3WICM3pg9e6EF7q23XmFrVwQWKCUL20xf5b6fu/Wa1Jsyfel2E0zncWB91ldOO GPg0u0t4nyfc7VS/xP6kMZQEdwJPoQvP/bcz+e4duPpXoovjtQupjUcy+9DP0wS8D1q4 Mq4meuWo50dvARWTo4EuFohnpc2vZPeNSl+jqR8SUGiAaweYahb9nqXjBFWP21vpJk/1 ISZ5fGLXmoiyTGYWAVaJE1/RWjHoQ9ou0b9woysiGpryZ/hH/Beu8/T+vtzVRz+Z6VQU dmqTWMHkJV13UN6FdVAcGpHodtJbd33otgbu+OJVdkEI5nnpLTcjZhMIaaOpbSCwGrpU 86OQ== X-Gm-Message-State: AMCzsaX5OjLMqxfEsAMqmGIMVeHZI6gsucg16ZsZR06cKsGrLaiw8EmV oXOsQ4g+WtpcgSLssavtxqjAIEfPoerM+CIWVjB4gw== X-Google-Smtp-Source: ABhQp+RbaFzgi+Me8BhMIMlmxGRfqY3KWkuG335aiWA4WmwWM3RS9bTwZQ6ZHP1KU+AOjjbtCNKhPH1KrJeGTxcPxo0= X-Received: by 10.37.135.18 with SMTP id a18mr1361379ybl.166.1508939296560; Wed, 25 Oct 2017 06:48:16 -0700 (PDT) MIME-Version: 1.0 Received: by 10.129.174.33 with HTTP; Wed, 25 Oct 2017 06:48:15 -0700 (PDT) In-Reply-To: <341271508938027@web34g.yandex.ru> References: <341271508938027@web34g.yandex.ru> From: Ivan Gotovchits Date: Wed, 25 Oct 2017 09:48:15 -0400 Message-ID: To: vadim@radovel.ru Cc: OCaml Mailing List , Gabriel Scherer , =?UTF-8?Q?Christoph_H=C3=B6ger?= Content-Type: multipart/alternative; boundary="089e08287c08c28433055c5f4e53" Subject: Re: [Caml-list] classes not optimized? --089e08287c08c28433055c5f4e53 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable On Wed, Oct 25, 2017 at 9:27 AM, wrote: > > Excuse me, does this mean that I should use modules instead of objects if > its posible. For example: I have a big list of different modules with the > same signature containing some values and functions inside - would it give > the best performance in OCaml comparing to classes, objects, etc? > If you can solve your problem without relying on objects, then it is better not to use them. There is nothing wrong with them. It just because it is a very powerful mechanism, that sometimes is not easy to control. They give you an extra flexibility so that you can express more complex abstractions, but this comes with a price. Given your particular example, yes, calling a function is faster, than calling a method, as the latter introduces an extra layer of indirection via the virtual method table. Moreover, if a function is know at compile time, it can be inlined, that may provide even further optimization opportunities. It is very hard in general to inline a method, as a compiler needs a proof that this and only this method will be called in runtime. Moreover, if it is the case (i.e., the method can be resolved in runtime), then it is a signal that an object should not be used at all. Basically, objects should be used when you need an open recursion with runtime dispatch. This is a very rare case, in fact. > > 25.10.2017, 12:45, "Gabriel Scherer" : > > Object-oriented code tends to generate large intermediate representations, > too large to be inlined and too complex to be partially evaluated at > compile-time. I wouldn't expect this sort of optimization to work. > > You might have better luck with first-class modules if you want some sort > of tuple subtyping. > (Performance model: with modules, subtyping coercions are compiled as a > field-reordering copy, > so the runtime cost is on the coercion rather than the field access.) > > > Also as a related question, is there a way to have the lookup semantics > of methods without the open recursion part? > > We could add row-typed extensible records to the language. Given how > little the object-oriented layer is used in practice, I am not sure that > this highly work-demanding addition would be a good use of a contributor's > time -- and its utility would have to be weighted against the complexity > cost of adding yet another kind of product structure. > > On Wed, Oct 25, 2017 at 11:31 AM, Christoph H=C3=B6ger < > christoph.hoeger@celeraone.com> wrote: > > Dear OCaml users, > > consider the following microbenchmark: > > > class s (z : string) (y : int) (x : int) =3D > object method z =3D z method y =3D y method x =3D x > end > > type t =3D { x : int; y : int; z : string} > > let foo_s _ =3D > (new s) "Example" 0 1 > > let foo_t _ =3D {x=3D1; y=3D0; z=3D"Example"} > > let one_s _ =3D (foo_s ())#x > > let one_t _ =3D (foo_t ()).x > > let fac =3D > let rec fac n =3D > let f =3D > let rec f n a =3D if n <=3D 1 then a else f (n - (one_s ())) (n * a= ) in > f (* change one_t to one_s or vice-versa *) > in > f n 1 in > fac > let bench =3D > let rec bench n a =3D > if n <=3D 0 > then a > else (let x =3D a && ((fac 20) =3D=3D (20 * (fac 19))) in bench (n -= 1) x) > in > bench > let test =3D bench 10000000 true > let main _ =3D test > > > If I run it with ocamlopt 4.05.0+flambda and -O3, the version that uses > one_s takes about 7.5s whereas the one with one_t uses 0.35s. I know that > object method lookup is more costly than records, of course. This > particular case baffles me, though. Why is the class not completely inlin= ed? > > Also as a related question, is there a way to have the lookup semantics of > methods without the open recursion part? That is, can I have a class that > consists of values, not methods? It would love to have open tuples in some > cases. For example, I'd like to write a function that takes a tuple of any > length, because it only needs the first element. > > thanks, > > Christoph > > > --089e08287c08c28433055c5f4e53 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable


On Wed, Oct 25, 2017 at 9:27 AM, <vadim@radovel.ru> wrot= e:
=C2=A0
Excuse me, does = this mean that I should use modules instead of objects if its posible. For = example: I have a big list of different modules with the same signature con= taining some values and functions inside - would it give the best performan= ce in OCaml comparing to classes, objects, etc?

=

If you can solve your problem without relying on = objects, then it is better not to use them. There is nothing wrong with the= m. It just because it is a very powerful mechanism, that sometimes is not e= asy to control. They give you an extra flexibility so that you can express = more complex abstractions, but this comes with a price. Given your particul= ar example, yes, calling a function is faster, than calling a method, as th= e latter introduces an extra layer of indirection via the virtual method ta= ble. Moreover, if a function is know at compile time, it can be inlined, th= at may provide even further optimization opportunities. It is very hard in = general to inline a method, as a compiler needs a proof that this and only = this method will be called in runtime. Moreover, if it is the case (i.e., t= he method can be resolved in runtime), then it is a signal that an object s= hould not be used at all. Basically, objects should be used when you need a= n open recursion with runtime dispatch. This is a very rare case, in fact.= =C2=A0


=C2=A0
=C2=A0
25.10.2017, 12:45, "Gabriel Scher= er" <gabriel.scherer@gmail.com>:
Object-oriented code tends= to generate large intermediate representations, too large to be inlined an= d too complex to be partially evaluated at compile-time. I wouldn't exp= ect this sort of optimization to work.
=C2=A0
You might have better= luck with first-class modules if you want some sort of tuple subtyping.(Performance model: with modules, subtyping coercions are compiled as a fi= eld-reordering copy,
so the runtime cost is on the coercion rather than = the field access.)

> Also as a related question, is there a way t= o have the lookup semantics of methods without the open recursion part?
= =C2=A0
We could add row-typed extensible records to the language. Give= n how little the object-oriented layer is used in practice, I am not sure t= hat this highly work-demanding addition would be a good use of a contributo= r's time -- and its utility would have to be weighted against the compl= exity cost of adding yet another kind of product structure.
=C2= =A0
On Wed, Oct 25, 2017 at 11:31 AM, Christoph H=C3=B6ger <christoph= .hoeger@celeraone.com> wrote:
Dear OCaml users,
=C2=A0
consider the following microb= enchmark:
=C2=A0
<snip>
class s (z : st= ring)=C2=A0 (y : int)=C2=A0 (x : int) =3D
=C2=A0 object method z =3D z m= ethod y =3D y method x =3D x
end

type t =3D { x : int; y : int; z= : string}

let foo_s _ =3D
=C2=A0(new s) "Example" 0 1<= br>
let foo_t _ =3D {x=3D1; y=3D0; z=3D"Example"}

let o= ne_s _ =3D (foo_s ())#x

let one_t _ =3D (foo_t ()).x

let fac = =3D
=C2=A0 let rec fac n =3D
=C2=A0=C2=A0=C2=A0 let f =3D
=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0 let rec f n a =3D if n <=3D 1 then a else f (n = - (one_s ())) (n * a)=C2=A0 in f (* change one_t to one_s or vice-versa *)<= br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 in
=C2=A0=C2=A0=C2=A0 f n 1=C2= =A0 in
=C2=A0 fac
let bench =3D
=C2=A0 let rec bench n a =3D
= =C2=A0=C2=A0=C2=A0 if n <=3D 0
=C2=A0=C2=A0=C2=A0 then a
=C2=A0=C2= =A0=C2=A0 else (let x =3D a && ((fac 20) =3D=3D (20 * (fac 19)))=C2= =A0 in bench (n - 1) x)=C2=A0 in
=C2=A0 bench
let test =3D bench 10000000 true
let main _ =3D test
</snip>
=
=C2=A0
If I run it with ocamlopt 4.05.0+flambda and -O3, the vers= ion that uses one_s takes about 7.5s whereas the one with one_t uses 0.35s.= I know that object method lookup is more costly than records, of course. T= his particular case baffles me, though. Why is the class not completely inl= ined?
=C2=A0
Also as a related question, is there a way to have the= lookup semantics of methods without the open recursion part? That is, can = I have a class that consists of values, not methods? It would love to have = open tuples in some cases. For example, I'd like to write a function th= at takes a tuple of any length, because it only needs the first element.=C2=A0
thanks,
=C2=A0
Christoph
=C2=A0

--089e08287c08c28433055c5f4e53--