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 mail3-relais-sop.national.inria.fr (mail3-relais-sop.national.inria.fr [192.134.164.104]) by sympa.inria.fr (Postfix) with ESMTPS id DA4F87EE89 for ; Wed, 25 Oct 2017 15:49:58 +0200 (CEST) Authentication-Results: mail3-smtp-sop.national.inria.fr; spf=None smtp.pra=ivg@ieee.org; spf=Pass smtp.mailfrom=ivg@ieee.org; spf=None smtp.helo=postmaster@mail-yw0-f177.google.com Received-SPF: None (mail3-smtp-sop.national.inria.fr: no sender authenticity information available from domain of ivg@ieee.org) identity=pra; client-ip=209.85.161.177; receiver=mail3-smtp-sop.national.inria.fr; envelope-from="ivg@ieee.org"; x-sender="ivg@ieee.org"; x-conformance=sidf_compatible Received-SPF: Pass (mail3-smtp-sop.national.inria.fr: domain of ivg@ieee.org designates 209.85.161.177 as permitted sender) identity=mailfrom; client-ip=209.85.161.177; receiver=mail3-smtp-sop.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 (mail3-smtp-sop.national.inria.fr: no sender authenticity information available from domain of postmaster@mail-yw0-f177.google.com) identity=helo; client-ip=209.85.161.177; receiver=mail3-smtp-sop.national.inria.fr; envelope-from="ivg@ieee.org"; x-sender="postmaster@mail-yw0-f177.google.com"; x-conformance=sidf_compatible IronPort-PHdr: =?us-ascii?q?9a23=3AcdVR0hewmbm3CmBDy+6JjvkolGMj4u6mDksu8pMi?= =?us-ascii?q?zoh2WeGdxc29Zh7h7PlgxGXEQZ/co6odzbGJ4+a9ASQp2tWojjMrSNR0TRgLiM?= =?us-ascii?q?EbzUQLIfWuLgnFFsPsdDEwB89YVVVorDmROElRH9viNRWJ+iXhpRZbIBj0NBJ0?= =?us-ascii?q?K+LpAcaSyp3vj6Hhs6HUNhtBiDu4Sal7IBKooAGXrNRFr5FlL/MQ1BLP6lRPZ+?= =?us-ascii?q?NIzmNpOUnbyxfi6e+x8ZNutSNKtKRypIZ7TazmcvFgHvRjBzM8PjVwvZWzuA?= =?us-ascii?q?=3D=3D?= X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: =?us-ascii?q?A0D6AACWlfBZhrGhVdFcHAEBBAEBCgEBF?= =?us-ascii?q?wEBBAEBCgEBhQYnB4NzgTaXdIF6iEuNf4EiA1wKhTsChGUHQxQBAQEBAQEBAQE?= =?us-ascii?q?BARIBAQEICwsIKC+COAUBHgEFgjsBAQEDASMdAQE3AQQLCQILDSoCAiEBEgEFA?= =?us-ascii?q?RwZiggDCAUIi1CRG0CLIWuCJ4MIAQEFhDANg0QBAQEHAQEBAQEbCBKDHIIHgVC?= =?us-ascii?q?EBoENgl6Bb4NMgmGhPDyPfoR5ghWJfIcVjQ2IYBQFH4EVNoF8gQcISTUGgimCT?= =?us-ascii?q?R+CDyQ2AYpGgVUBAQE?= X-IPAS-Result: =?us-ascii?q?A0D6AACWlfBZhrGhVdFcHAEBBAEBCgEBFwEBBAEBCgEBhQY?= =?us-ascii?q?nB4NzgTaXdIF6iEuNf4EiA1wKhTsChGUHQxQBAQEBAQEBAQEBARIBAQEICwsIK?= =?us-ascii?q?C+COAUBHgEFgjsBAQEDASMdAQE3AQQLCQILDSoCAiEBEgEFARwZiggDCAUIi1C?= =?us-ascii?q?RG0CLIWuCJ4MIAQEFhDANg0QBAQEHAQEBAQEbCBKDHIIHgVCEBoENgl6Bb4NMg?= =?us-ascii?q?mGhPDyPfoR5ghWJfIcVjQ2IYBQFH4EVNoF8gQcISTUGgimCTR+CDyQ2AYpGgVU?= =?us-ascii?q?BAQE?= X-IronPort-AV: E=Sophos;i="5.43,431,1503352800"; d="scan'208,217";a="242337063" Received: from mail-yw0-f177.google.com ([209.85.161.177]) by mail3-smtp-sop.national.inria.fr with ESMTP/TLS/AES128-GCM-SHA256; 25 Oct 2017 15:49:57 +0200 Received: by mail-yw0-f177.google.com with SMTP id l32so13985ywh.13 for ; Wed, 25 Oct 2017 06:49:57 -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=316r+FSrNqo5FpVH9b2/9cFA9RQ8DKmMxbIvBWM5Vds=; b=mmkfLqaEQg6PaG8LooixqBHg45zK+OlN2696EctNPssRHrf/Gry05qL/w+wJpFv86X PrzwRpjqT9Nel4PdEbZrNOCgG0QtZpjfP4n0mVCt15VUzwekmZQjzq2u4VKGJBiYtyHL UrLLv5h5SKPhyAR+TL5yZDG1f4plmNznt7424i5AWdEBpF7Zx/EofWlSd5cF1gDCLx21 Zo1cL34LR+7yAWOyCW1kMxVkEfCb+T7ndT0j3lCsXtP8baR+eBvq2IzZcjiW2C79XUIb OPSWdeepWyIkjIbhbhbH8By6xPpI4xgc49gz8JLlrc8hB5QUlHNCezKcHJCedb027kXL VNKg== 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=316r+FSrNqo5FpVH9b2/9cFA9RQ8DKmMxbIvBWM5Vds=; b=sM/s6NfGzjl0l/Gb6kPaFPDrQd4AWfi9owmEDlyhrTdi0gLtX4bn4jgJOpPzvonki+ XVPz90naF9F4tIg5buqPA9+B5DkNDu29sJql5GuTX/JBZh0Xhyxs6aMhY3Y/AmnSgQT2 ql6wVuuw5awg0ouvTII3xxlSyv7xM5iriWmusiM3sC0PcL8IAfTrJH4xPGsXXu2rPaJC 09JaTSpIazvW3yictsAcs+J95HoIMq0+iFkT378+I8wrlJbj0NJJ0s/In3exfUrv86g+ TjdPwh2rb3KJj44Wf8bEUFLNMy5bClPhJYy3jCAa7shWf4Mt3QwsRoNusgfkoY5QTTTV fl+w== X-Gm-Message-State: AMCzsaWLQkyfXJnO+9jvdaz0eYybSM03HsUJa+hSkJkXfLgX9GROkSLE he5B9Vo6BeRaCjWGlPYo1Le4O/GNKX4UptqYILf0yYNG X-Google-Smtp-Source: ABhQp+T/K3CH1uuASAE1LFpgn9QHz3w+t/HhZkZpj/A0rt+slHZdKeoYN/eEWi32Hrwb9yPN9moOATU0Ppu8JSZ48Lw= X-Received: by 10.37.132.136 with SMTP id v8mr1277652ybk.140.1508939395525; Wed, 25 Oct 2017 06:49:55 -0700 (PDT) MIME-Version: 1.0 Received: by 10.129.174.33 with HTTP; Wed, 25 Oct 2017 06:49:55 -0700 (PDT) In-Reply-To: References: <341271508938027@web34g.yandex.ru> From: Ivan Gotovchits Date: Wed, 25 Oct 2017 09:49:55 -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="089e082bfbc8a8aaf3055c5f542c" Subject: Re: [Caml-list] classes not optimized? --089e082bfbc8a8aaf3055c5f542c Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable a typo: "(i.e., the method can be resolved in runtime)" should be read as "(i.e., the method can be resolved at compile time)" On Wed, Oct 25, 2017 at 9:48 AM, Ivan Gotovchits wrote: > > > 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 gi= ve >> 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 fac= t. > > > > >> >> 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 inli= ned? >> >> 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 >> >> >> > --089e082bfbc8a8aaf3055c5f542c Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
a typo: "(i.e., the method can be resolved in runtime= )" should be read as "(i.e., the method can be resolved at compil= e time)"

On Wed, Oct 25, 2017 at 9:48 AM, Ivan Gotovchits <ivg@ieee.org>= wrote:


On Wed, Oc= t 25, 2017 at 9:27 AM, <vadim@radovel.ru> wrote:
=C2=A0
Excuse me, does this mean that= I should use modules instead of objects if its posible. For example: I hav= e a big list of different modules with the same signature containing some v= alues and functions inside - would it give the best performance in OCaml co= mparing 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 j= ust 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 co= mplex abstractions, but this comes with a price. Given your particular exam= ple, yes, calling a function is faster, than calling a method, as the latte= r introduces an extra layer of indirection via the virtual method table. Mo= reover, 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 me= thod will be called in runtime. Moreover, if it is the case (i.e., the meth= od can be resolved in runtime), then it is a signal that an object should n= ot 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.=C2=A0


=C2=A0
<= blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px= #ccc solid;padding-left:1ex">
=C2=A0
25.10.2017, 12:45, &quo= t;Gabriel Scherer" <gabriel.scherer@gmail.com>:
Object-oriented code tends to generate large i= ntermediate representations, too large to be inlined and too complex to be = partially evaluated at compile-time. I wouldn't expect this sort of opt= imization to work.
=C2=A0
You might have better luck with first-cla= ss 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 se= mantics of methods without the open recursion part?
=C2=A0
We could= add row-typed extensible records to the language. Given how little the obj= ect-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.
=C2=A0
On Wed, Oct 25= , 2017 at 11:31 AM, Christoph H=C3=B6ger <christoph.hoeger@celeraone.com> wrote:
Dear OCam= l users,
=C2=A0
consider the following microbenchmark:
= =C2=A0
<snip>
class s (z : string)=C2=A0 (y : int= )=C2=A0 (x : int) =3D
=C2=A0 object method z =3D z method y =3D y method= x =3D x
end

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

le= t foo_s _ =3D
=C2=A0(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
=C2=A0 let r= ec 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 *)
=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 faclet bench =3D
=C2=A0 let rec bench n a =3D
=C2=A0=C2=A0=C2=A0 if n &= lt;=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<= br>let main _ =3D test
</snip>
=C2=A0
If I r= un it with ocamlopt 4.05.0+flambda and -O3, the version that uses one_s tak= es about 7.5s whereas the one with one_t uses 0.35s. I know that object met= hod lookup is more costly than records, of course. This particular case baf= fles me, though. Why is the class not completely inlined?
=C2=A0
Al= so as a related question, is there a way to have the lookup semantics of me= thods without the open recursion part? That is, can I have a class that con= sists of values, not methods? It would love to have open tuples in some cas= es. For example, I'd like to write a function that takes a tuple of any= length, because it only needs the first element.
=C2=A0
thanks,=C2=A0
Christoph
=C2=A0


--089e082bfbc8a8aaf3055c5f542c--