From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.1.3 (2006-06-01) on yquem.inria.fr X-Spam-Level: ** X-Spam-Status: No, score=2.2 required=5.0 tests=AWL,DNS_FROM_RFC_POST, HTML_MESSAGE,SPF_NEUTRAL autolearn=disabled version=3.1.3 X-Original-To: caml-list@yquem.inria.fr Delivered-To: caml-list@yquem.inria.fr Received: from mail3-relais-sop.national.inria.fr (mail3-relais-sop.national.inria.fr [192.134.164.104]) by yquem.inria.fr (Postfix) with ESMTP id 5B68FBB84 for ; Tue, 17 Feb 2009 08:40:13 +0100 (CET) X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AnQCAJ74mUnRVdqnlGdsb2JhbACCQy6KHYYUZD8BAQEBCQkKCQ+sFY8JAQMBA4QQBoQ0 X-IronPort-AV: E=Sophos;i="4.38,222,1233529200"; d="ml'?scan'208";a="23063118" Received: from mail-bw0-f167.google.com ([209.85.218.167]) by mail3-smtp-sop.national.inria.fr with ESMTP; 17 Feb 2009 08:40:12 +0100 Received: by bwz11 with SMTP id 11so1731103bwz.3 for ; Mon, 16 Feb 2009 23:40:11 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:mime-version:sender:received:in-reply-to :references:date:x-google-sender-auth:message-id:subject:from:to:cc :content-type; bh=pH1Ygk5+iVfOOzHw+p94wbsZWFWTGVdls7rIiajLUuo=; b=v7m1tdKDhxcMin6ZQrH+FaEPppbDrgK4IJiO86NHfOJaYebxLqm5hVSfdlU7abb66D PYCmvVgL3tuxKKl9Yvd4r94lCYHFe5Qqd/iggpcnsAN2Qwj6TQwlIw+NYLEGvRsjRz9B I04s7IAEuFAeDnj46zDZhIFymXInYTaTLMAE0= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=mime-version:sender:in-reply-to:references:date :x-google-sender-auth:message-id:subject:from:to:cc:content-type; b=g+pqDQKK/hV3jL64sMISswxkuZ6muDXfOkOhORhfssMrBwDTdN8lFKAejdXN5PUOxA o0AaO51swgziWntVjMa99uOlYMdQc08XPvqMw5hcYToaMothb5Vb5I3icPbhNjKKqhaj srP8gn73LJoNd9hnyWUIXY3n3Kcw6iAOU5fEg= MIME-Version: 1.0 Sender: remidewitte@gmail.com Received: by 10.223.116.77 with SMTP id l13mr338258faq.106.1234856411545; Mon, 16 Feb 2009 23:40:11 -0800 (PST) In-Reply-To: <2184b2340902160937i53b8f3fbga01eaf14ed829f8f@mail.gmail.com> References: <2184b2340902160715y1f935b5ehc0e6195b3f75b66b@mail.gmail.com> <891bd3390902160847p25ad3bf1pe59da620dfc667f2@mail.gmail.com> <2184b2340902160937i53b8f3fbga01eaf14ed829f8f@mail.gmail.com> Date: Tue, 17 Feb 2009 08:40:11 +0100 X-Google-Sender-Auth: c61dd906afc677cc Message-ID: <2184b2340902162340s540c5ac7g9f42b59d03f643cb@mail.gmail.com> Subject: Re: [Caml-list] Threads performance issue. From: =?UTF-8?Q?R=C3=A9mi_Dewitte?= To: yminsky@gmail.com Cc: caml-list@yquem.inria.fr Content-Type: multipart/mixed; boundary=001636c5afb6c242850463186928 X-Spam: no; 0.00; ocaml:01 uname:01 cheers:01 yaron:01 printf:01 endline:01 nread:01 nread:01 yaron:01 minsky:01 yminsky:01 pcre:01 ocaml:01 pointers:01 beginner's:01 X-Attachments: cset="UTF-8" cset="UTF-8" type="application/octet-stream" name="transf.ml" name="transf.ml" type="application/octet-stream" name="transi.ml" name="transi.ml" --001636c5afb6c242850463186928 Content-Type: multipart/alternative; boundary=001636c5afb6c2427f0463186926 --001636c5afb6c2427f0463186926 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable I have made some further experiments. I have a functional version of the reading algorithm. I have the original imperative version of the algorithm. Either it is linked to thread (T) or not (X). Either it uses extlib (E) or not (X). Results are. XX TX XE TE Imperative | 3.37 | 7.80 | 3.56 | 8.40 Functional | 4.20 | 8.28 | 4.47 | 9.08 test.csv is a 21mo file with ~13k rows and a thousands of columns on a 15rp= m disk. ocaml version : 3.11.0 uname -a gives Linux localhost 2.6.28.4-server-1mnb #1 SMP Mon Feb 9 09:05:19 EST 2009 i68= 6 Intel(R) Core(TM)2 Duo CPU E8400 @ 3.00GHz GNU/Linux While I think I have to find improvements to the functional version, I struggle finding a rationale behind this high loss of performance while I a= m not even using threads, just linking to... Cheers, R=C3=A9mi On Mon, Feb 16, 2009 at 18:37, R=C3=A9mi Dewitte wrote: > Yaron, > > I use a slightly modified version of the CSV library's load_rows . Here i= s > the main code which is highly imperative style. I might transform it in > purely functional style ? > > The main program is : > > open Printf;; > open Sys;; > let timed_exec start_message f =3D > print_string start_message; > let st1 =3D time () in > let r =3D f () in > print_endline ("done in " ^ (string_of_float ((time ()) -. st1)) ); > r;; > > (* This line enabled makes the program really slow ! *) > let run_threaded f =3D Thread.create (fun () -> f (); Thread.exit ()) () > > let () =3D timed_exec "Reading data " (fun () -> > load_rows (fun _ -> ()) (open_in "file1.csv"); > load_rows (fun _ -> ()) (open_in "file2.csv"); > () > ) > > The load_rows : > let load_rows ?(separator =3D ',') ?(nread =3D -1) f chan =3D > let nr =3D ref 0 in > let row =3D ref [] in (* Current row. *) > let field =3D ref [] in (* Current field. *) > let state =3D ref StartField in (* Current state. *) > let end_of_field () =3D > let field_list =3D List.rev !field in > let field_len =3D List.length field_list in > let field_str =3D String.create field_len in > let rec loop i =3D function > [] -> () > | x :: xs -> > field_str.[i] <- x; > loop (i+1) xs > in > loop 0 field_list; > row :=3D (Some field_str) :: !row; > field :=3D []; > state :=3D StartField > in > let empty_field () =3D > row :=3D None :: !row; > field :=3D []; > state :=3D StartField > in > let end_of_row () =3D > let row_list =3D List.rev !row in > f row_list; > row :=3D []; > state :=3D StartField; > nr :=3D !nr + 1; > in > let rec loop () =3D > let c =3D input_char chan in > if c !=3D '\r' then ( (* Always ignore \r characters. *) > match !state with > StartField -> (* Expecting quote or other char. *) > if c =3D '"' then ( > state :=3D InQuotedField; > field :=3D [] > ) else if c =3D separator then (* Empty field. *) > empty_field () > else if c =3D '\n' then ( (* Empty field, end of row. *) > empty_field (); > end_of_row () > ) else ( > state :=3D InUnquotedField; > field :=3D [c] > ) > | InUnquotedField -> (* Reading chars to end of field. *) > if c =3D separator then (* End of field. *) > end_of_field () > else if c =3D '\n' then ( (* End of field and end of row. *) > end_of_field (); > end_of_row () > ) else > field :=3D c :: !field > | InQuotedField -> (* Reading chars to end of field. *) > if c =3D '"' then > state :=3D InQuotedFieldAfterQuote > else > field :=3D c :: !field > | InQuotedFieldAfterQuote -> > if c =3D '"' then ( (* Doubled quote. *) > field :=3D c :: !field; > state :=3D InQuotedField > ) else if c =3D '0' then ( (* Quote-0 is ASCII NUL. *) > field :=3D '\000' :: !field; > state :=3D InQuotedField > ) else if c =3D separator then (* End of field. *) > end_of_field () > else if c =3D '\n' then ( (* End of field and end of row. *) > end_of_field (); > end_of_row () > ) else ( (* Bad single quote in field. *) > field :=3D c :: '"' :: !field; > state :=3D InQuotedField > ) > ); (* end of match *) > if( nread < 0 or !nr < nread) then loop () else () > in > try > loop () > with > End_of_file -> > (* Any part left to write out? *) > (match !state with > StartField -> > if !row <> [] then > ( empty_field (); end_of_row () ) > | InUnquotedField | InQuotedFieldAfterQuote -> > end_of_field (); end_of_row () > | InQuotedField -> > raise (Bad_CSV_file "Missing end quote after quoted field.") > ) > > > Thanks, > R=C3=A9mi > > > On Mon, Feb 16, 2009 at 17:47, Yaron Minsky wrote: > >> 2009/2/16 R=C3=A9mi Dewitte >> >>> Hello, >>> >>> I would like to read two files in two different threads. >>> >>> I have made a first version reading the first then the second and it >>> takes 2.8s (native). >>> >>> I decided to make a threaded version and before any use of thread I >>> realized that just linking no even using it to the threads library make= s my >>> first version of the program to run in 12s ! >> >> >> Do you have a short benchmark you can post? The idea that the >> thread-overhead would make a difference like that, particularly for IO-b= ound >> code (which I'm guessing this is) is pretty surprising. >> >> y >> >> >>> >>> I use pcre, extlib, csv libraries as well. >>> >>> I guess it might come from GC slowing down thinks here, doesn't it ? >>> Where can it come from otherwise ? Is there a workaround or something I >>> should know ? >>> >>> Can ocaml use multiple cores ? >>> >>> Do you have few pointers on libraries to make parallel I/Os ? >>> >>> Thanks, >>> R=C3=A9mi >>> >>> _______________________________________________ >>> Caml-list mailing list. Subscription management: >>> http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list >>> Archives: http://caml.inria.fr >>> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners >>> Bug reports: http://caml.inria.fr/bin/caml-bugs >>> >>> >> > --001636c5afb6c2427f0463186926 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable I have made some further experiments.
I have a functional version of the= reading algorithm. I have the original imperative version of the algorithm= .
Either it is linked to thread (T) or not (X). Either it uses extlib (E= ) or not (X).

Results are.
         &= nbsp;        XX    &= nbsp; TX     XE     TE
Imperativ= e | 3.37 | 7.80 | 3.56 | 8.40
Functional | 4.20 | 8.28 | 4.47 | 9.08
=
test.csv is a 21mo file with ~13k rows and a thousands of columns on a = 15rpm disk.

ocaml version : 3.11.0

uname -a gives
Linux localhost 2.6.28.= 4-server-1mnb #1 SMP Mon Feb 9 09:05:19 EST 2009 i686 Intel(R) Core(TM)2 Du= o CPU     E8400  @ 3.00GHz GNU/Linux

While = I think I have to find improvements to the functional version, I struggle f= inding a rationale behind this high loss of performance while I am not even= using threads, just linking to...

Cheers,
R=C3=A9mi

On Mon, Feb 16, = 2009 at 18:37, R=C3=A9mi Dewitte <remi@gide.net> wrote:
Yaron,

I use a slightly modified version of the CSV library's lo= ad_rows . Here is the main code which is highly imperative style. I might t= ransform it in purely functional style ?

The main program is :

open Printf;;
open Sys;;
let timed_exec start_message f =3D
&n= bsp; print_string start_message;
  let st1 =3D time () in
 = ; let r =3D f () in
  print_endline ("done in " ^ (string= _of_float ((time ()) -. st1)) );
  r;;

(* This line enabled makes the program really slow ! *)let run_threaded f =3D Thread.create (fun () -> f (); Thread.exit ()) = ()

let () =3D timed_exec "Reading data " (fun () ->   load_rows (fun _ -> ()) (open_in "file1.csv");
  load_rows (fun _ -> ()) (open_in "file2.csv");
 = ; ()
)

The load_rows :
let load_rows ?(separator =3D ',= 9;) ?(nread =3D -1) f chan =3D
  let nr =3D ref 0 in
  let = row =3D ref [] in            (= * Current row. *)
  let field =3D ref [] in         &= nbsp;  (* Current field. *)
  let state =3D ref StartField in&= nbsp;       (* Current state. *)
  let end= _of_field () =3D
    let field_list =3D List.rev !field i= n
    let field_len =3D List.length field_list in
    let field_str =3D String.create field_len in
 &n= bsp;  let rec loop i =3D function
    [] -> ()      | x :: xs ->
     = ; field_str.[i] <- x;
      loop (i+1) xs
&nbs= p;   in
    loop 0 field_list;
  &= nbsp; row :=3D (Some field_str) :: !row;
    field :=3D [];
    state :=3D StartFie= ld
  in
  let empty_field () =3D
    row = :=3D None :: !row;
    field :=3D [];
  &nbs= p; state :=3D StartField
  in
  let end_of_row () =3D
&n= bsp;   let row_list =3D List.rev !row in
    f row_list;
    row :=3D [];
 =    state :=3D StartField;
    nr :=3D !nr + 1;<= br>  in
  let rec loop () =3D
    let c =3D = input_char chan in
    if c !=3D '\r' then ( = ;           (* Always ignore \r cha= racters. *)
      match !state with
    &nbs= p; StartField ->           = (* Expecting quote or other char. *)
      &nb= sp; if c =3D '"' then (
      &nbs= p;   state :=3D InQuotedField;
      =     field :=3D []
        )= else if c =3D separator then (* Empty field. *)
          empty_field ()
 &= nbsp;      else if c =3D '\n' then (  = ;  (* Empty field, end of row. *)
      &n= bsp;   empty_field ();
       &n= bsp;  end_of_row ()
        ) else (<= br>          state :=3D InUnquotedF= ield;
          field :=3D [c]
        )
    | InUnquotedF= ield ->        (* Reading chars to end of = field. *)
        if c =3D separator then&= nbsp;   (* End of field. *)
      &nb= sp;   end_of_field ()
        el= se if c =3D '\n' then (    (* End of field and end o= f row. *)
          end_of_field ();
 = ;         end_of_row ()
  &= nbsp;     ) else
       &nb= sp;  field :=3D c :: !field
    | InQuotedField ->= ;        (* Reading chars to end of field. *)=
        if c =3D '"' then           state :=3D InQuotedFieldA= fterQuote
        else
  &nbs= p;       field :=3D c :: !field
  &nb= sp; | InQuotedFieldAfterQuote ->
       = ; if c =3D '"' then (        (* = Doubled quote. *)
          fiel= d :=3D c :: !field;
          state :=3D InQuotedField<= br>        ) else if c =3D '0' then (=     (* Quote-0 is ASCII NUL. *)
     =      field :=3D '\000' :: !field;
 &nbs= p;        state :=3D InQuotedField
 &= nbsp;      ) else if c =3D separator then (* End of fie= ld. *)
          end_of_field ()
 =        else if c =3D '\n' then ( &nbs= p;  (* End of field and end of row. *)
     &nb= sp;    end_of_field ();
      &n= bsp;   end_of_row ()
        ) e= lse (            (* Bad single= quote in field. *)
          field :=3D c :: '&quo= t;' :: !field;
          sta= te :=3D InQuotedField
        )
 &= nbsp;  ); (* end of match *)
  if( nread < 0 or !nr < nr= ead) then loop () else ()
  in
  try
    = loop ()
  with
      End_of_file ->
 &n= bsp;  (* Any part left to write out? *)
    (match != state with
         StartField -><= br>           if !row <>= [] then
         ( empty_field (); e= nd_of_row () )
       | InUnquotedField | InQuo= tedFieldAfterQuote ->
           end_of_field (); en= d_of_row ()
       | InQuotedField ->
&nb= sp;          raise (Bad_CSV_file &q= uot;Missing end quote after quoted field.")
    )

Thanks,
R=C3=A9mi


On Mon, Feb 16, 2009 at 17:47, Yaron Minsky <yminsky@gmail.com> wrote:
2009/2/16 R=C3=A9mi Dewitte <remi@gide.net>
Hello,

I would like to read two files in two different threads.
<= br>I have made a first version reading the first then the second and it tak= es 2.8s (native).

I decided to make a threaded version and before an= y use of thread I realized that just linking no even using it to the thread= s library makes my first version of the program to run in 12s !

Do you have a short benchmark you can post?  The idea t= hat the thread-overhead would make a difference like that, particularly for= IO-bound code (which I'm guessing this is) is pretty surprising.

y
 
R=C3=A9m= i

_______________________________________________
Caml-list mailing list. Subscription management:
http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list Archives: http://caml.in= ria.fr
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs




--001636c5afb6c2427f0463186926-- --001636c5afb6c242850463186928 Content-Type: application/octet-stream; name="transf.ml" Content-Disposition: attachment; filename="transf.ml" Content-Transfer-Encoding: base64 X-Attachment-Id: f_fra9dgaf0 KCogb3BlbiBFeHRMaWIgKikKCigqKiBTbGl0aGx5IG1vZGlmaWVkIGNvcHkgZnJvbSBtb2R1bGUg Q1NWICopCmV4Y2VwdGlvbiBCYWRfQ1NWX2ZpbGUgb2Ygc3RyaW5nCgp0eXBlIHN0YXRlX3QgPSBT dGFydEZpZWxkCgkgICAgICAgfCBJblVucXVvdGVkRmllbGQKCSAgICAgICB8IEluUXVvdGVkRmll bGQKCSAgICAgICB8IEluUXVvdGVkRmllbGRBZnRlclF1b3RlCgoKbGV0IGxvYWRfcm93cyA/KHNl cGFyYXRvciA9ICcsJykgPyhucmVhZCA9IC0xKSBmIGNoYW4gPQogIGxldCBlbnRyeSA9IChTdGFy dEZpZWxkLFtdLFtdLDApIGluCigqICAgbGV0IHN0ID0gcmVmIGVudHJ5IGluICopCiAgbGV0IHN0 cmluZ19vZl9maWVsZCBmaWVsZCA9CiAgICBsZXQgZmllbGRfbGlzdCA9IExpc3QucmV2IGZpZWxk IGluCiAgICBsZXQgZmllbGRfbGVuID0gTGlzdC5sZW5ndGggZmllbGRfbGlzdCBpbgogICAgbGV0 IGZpZWxkX3N0ciA9IFN0cmluZy5jcmVhdGUgZmllbGRfbGVuIGluCiAgICBsZXQgcmVjIGxvb3Ag aSA9IGZ1bmN0aW9uCglbXSAtPiAoKQogICAgICB8IHggOjogeHMgLT4KCSAgZmllbGRfc3RyLltp XSA8LSB4OwoJICBsb29wIChpKzEpIHhzCiAgICBpbgogICAgbG9vcCAwIGZpZWxkX2xpc3Q7CiAg ICBmaWVsZF9zdHIKICBpbgogIGxldCBlbmRfb2ZfZmllbGQgZmllbGQgcm93IG5yID0KICAgIGxl dCBzZiA9IChzdHJpbmdfb2ZfZmllbGQgZmllbGQpIGluCiAgICAoU3RhcnRGaWVsZCxbXSwoU29t ZSBzZiA6OiByb3cpLG5yKQogIGluCiAgbGV0IGVtcHR5X2ZpZWxkIHJvdyBuciA9CiAgICAoU3Rh cnRGaWVsZCxbXSxOb25lIDo6IHJvdyxucikKICBpbgogIGxldCBlbmRfb2Zfcm93IHJvdyBuciA9 CiAgICBmIChMaXN0LnJldiByb3cpOwogICAgKFN0YXJ0RmllbGQsW10sW10sbnIgKyAxKQogIGlu CiAgbGV0IGVtcHR5X2ZpZWxkX2FuZF9lbmRfcm93IHJvdyBuciA9CiAgICBlbmRfb2Zfcm93IChO b25lIDo6IHJvdykgbnIKICBpbgogIGxldCBlbmRfb2ZfZmllbGRfYW5kX3JvdyBmaWVsZCByb3cg bnIgPQogICAgbGV0IHNmID0gKHN0cmluZ19vZl9maWVsZCBmaWVsZCkgaW4KICAgIGVuZF9vZl9y b3cgKFNvbWUgc2YgOjogcm93KSBucgogIGluCiAgbGV0IHJlYyByZWFkX2NoYXIgY2hhbiA9IHRy eQogICAgIGxldCBjID0gaW5wdXRfY2hhciBjaGFuIGluIChpZiBjICE9ICdccicgdGhlbiBTb21l IGMgZWxzZSByZWFkX2NoYXIgY2hhbikKICAgIHdpdGggRW5kX29mX2ZpbGUgLT4gTm9uZQogIGlu CgogIGxldCByZWMgbG9vcCBzdCA9CiAgIGxldCAoc3RhdGUsZmllbGQscm93LG5yKSA9IHN0IGlu CiAgIGlmKG5yID0gbnJlYWQpIHRoZW4KICAgICAoKQogICBlbHNlICgKICAgbGV0IGNvID0gcmVh ZF9jaGFyIGNoYW4gaW4KICAgbWF0Y2ggY28gd2l0aAogICB8IE5vbmUgLT4KCShtYXRjaCBzdGF0 ZSB3aXRoCgkgICB8IFN0YXJ0RmllbGQgLT4gaWYgKHJvdyA8PiBbXSkgdGhlbiAobGV0IF8gPSBl bXB0eV9maWVsZF9hbmRfZW5kX3JvdyByb3cgbnIgaW4gKCkpIGVsc2UgKCkKCSAgIHwgSW5VbnF1 b3RlZEZpZWxkIHwgSW5RdW90ZWRGaWVsZEFmdGVyUXVvdGUgLT4KCSAgICAgICBsZXQgXyA9IGVt cHR5X2ZpZWxkX2FuZF9lbmRfcm93IHJvdyBuciBpbiAoKQoJICAgfCBJblF1b3RlZEZpZWxkIC0+ CgkgICAgICAgcmFpc2UgKEJhZF9DU1ZfZmlsZSAiTWlzc2luZyBlbmQgcXVvdGUgYWZ0ZXIgcXVv dGVkIGZpZWxkLiIpCgkpCiAgIHwgU29tZSBjIC0+CiAgICAgIChsZXQgc3RuID0gKG1hdGNoIHN0 YXRlIHdpdGgKCSAgU3RhcnRGaWVsZCAtPgkJCSgqIEV4cGVjdGluZyBxdW90ZSBvciBvdGhlciBj aGFyLiAqKQoJICAgIGlmIGMgPSAnIicgdGhlbiAoCgkgICAgICAoSW5RdW90ZWRGaWVsZCxbXSxy b3csbnIpCgkgICAgKSBlbHNlIGlmIGMgPSBzZXBhcmF0b3IgdGhlbiAoKiBFbXB0eSBmaWVsZC4g KikKCSAgICAgIGVtcHR5X2ZpZWxkIHJvdyBucgoJICAgIGVsc2UgaWYgYyA9ICdcbicgdGhlbiAo CSgqIEVtcHR5IGZpZWxkLCBlbmQgb2Ygcm93LiAqKQoJICAgICAgZW1wdHlfZmllbGRfYW5kX2Vu ZF9yb3cgcm93IG5yCgkgICAgKSBlbHNlICgKCSAgICAgIChJblVucXVvdGVkRmllbGQsW2NdLHJv dyxucikKCSAgICApCgl8IEluVW5xdW90ZWRGaWVsZCAtPgkJKCogUmVhZGluZyBjaGFycyB0byBl bmQgb2YgZmllbGQuICopCgkgICAgaWYgYyA9IHNlcGFyYXRvciB0aGVuCSgqIEVuZCBvZiBmaWVs ZC4gKikKCSAgICAgIGVuZF9vZl9maWVsZCBmaWVsZCByb3cgbnIKCSAgICBlbHNlIGlmIGMgPSAn XG4nIHRoZW4gKAkoKiBFbmQgb2YgZmllbGQgYW5kIGVuZCBvZiByb3cuICopCgkgICAgICBlbmRf b2ZfZmllbGRfYW5kX3JvdyBmaWVsZCByb3cgbnIKCSAgICApIGVsc2UKICAgICAgICAgICAgICAo c3RhdGUsYyA6OiBmaWVsZCxyb3csbnIpCgl8IEluUXVvdGVkRmllbGQgLT4JCSgqIFJlYWRpbmcg Y2hhcnMgdG8gZW5kIG9mIGZpZWxkLiAqKQoJICAgIGlmIGMgPSAnIicgdGhlbgoJICAgICAgKElu UXVvdGVkRmllbGRBZnRlclF1b3RlLGZpZWxkLHJvdyxucikKCSAgICBlbHNlCgkgICAgICAoc3Rh dGUsYzo6ZmllbGQscm93LG5yKQoJfCBJblF1b3RlZEZpZWxkQWZ0ZXJRdW90ZSAtPgoJICAgIGlm IGMgPSAnIicgdGhlbiAoCQkoKiBEb3VibGVkIHF1b3RlLiAqKQoJICAgICAgKEluUXVvdGVkRmll bGQsYzo6ZmllbGQscm93LG5yKQoJICAgICkgZWxzZSBpZiBjID0gJzAnIHRoZW4gKAkoKiBRdW90 ZS0wIGlzIEFTQ0lJIE5VTC4gKikKCSAgICAgIChJblF1b3RlZEZpZWxkLCdcMDAwJyA6OiBmaWVs ZCxyb3csbnIpCgkgICAgKSBlbHNlIGlmIGMgPSBzZXBhcmF0b3IgdGhlbiAoKiBFbmQgb2YgZmll bGQuICopCgkgICAgICBlbmRfb2ZfZmllbGQgZmllbGQgcm93IG5yCgkgICAgZWxzZSBpZiBjID0g J1xuJyB0aGVuICgJKCogRW5kIG9mIGZpZWxkIGFuZCBlbmQgb2Ygcm93LiAqKQoJICAgICAgZW5k X29mX2ZpZWxkX2FuZF9yb3cgZmllbGQgcm93IG5yCgkgICAgKSBlbHNlICgJCQkoKiBCYWQgc2lu Z2xlIHF1b3RlIGluIGZpZWxkLiAqKQoJICAgICAgKEluUXVvdGVkRmllbGQsYyA6OiAnIicgOjog ZmllbGQscm93LG5yKQoJICAgICkKICAgICAgICApIGluIGxvb3Agc3RuICkKICAgKQogICBpbgog ICBsb29wIGVudHJ5CgooKiBsZXQgcnVuX3RocmVhZGVkIGYgPSBUaHJlYWQuY3JlYXRlIChmdW4g KCkgLT4gZiAoKTsgVGhyZWFkLmV4aXQgKCkpICgpICopCgpsZXQgKCkgPSBsZXQgaSA9IG9wZW5f aW4gInRlc3QuY3N2IiBpbiBsb2FkX3Jvd3MgKGZ1biBfIC0+ICgpKSBpOyBjbG9zZV9pbiBpCmxl dCAoKSA9IGxldCBpID0gb3Blbl9pbiAidGVzdC5jc3YiIGluIGxvYWRfcm93cyAoZnVuIF8gLT4g KCkpIGk7IGNsb3NlX2luIGkKbGV0ICgpID0gbGV0IGkgPSBvcGVuX2luICJ0ZXN0LmNzdiIgaW4g bG9hZF9yb3dzIChmdW4gXyAtPiAoKSkgaTsgY2xvc2VfaW4gaQ== --001636c5afb6c242850463186928 Content-Type: application/octet-stream; name="transi.ml" Content-Disposition: attachment; filename="transi.ml" Content-Transfer-Encoding: base64 X-Attachment-Id: f_fra9duso1 KCogb3BlbiBFeHRMaWIgKikKCigqKiBTbGl0aGx5IG1vZGlmaWVkIGNvcHkgZnJvbSBtb2R1bGUg Q1NWICopCmV4Y2VwdGlvbiBCYWRfQ1NWX2ZpbGUgb2Ygc3RyaW5nCgp0eXBlIHN0YXRlX3QgPSBT dGFydEZpZWxkCgkgICAgICAgfCBJblVucXVvdGVkRmllbGQKCSAgICAgICB8IEluUXVvdGVkRmll bGQKCSAgICAgICB8IEluUXVvdGVkRmllbGRBZnRlclF1b3RlCgpsZXQgbG9hZF9yb3dzID8oc2Vw YXJhdG9yID0gJywnKSA/KG5yZWFkID0gLTEpIGYgY2hhbiA9CiAgbGV0IG5yID0gcmVmIDAgaW4K ICBsZXQgcm93ID0gcmVmIFtdIGluCQkJKCogQ3VycmVudCByb3cuICopCiAgbGV0IGZpZWxkID0g cmVmIFtdIGluCQkJKCogQ3VycmVudCBmaWVsZC4gKikKICBsZXQgc3RhdGUgPSByZWYgU3RhcnRG aWVsZCBpbgkJKCogQ3VycmVudCBzdGF0ZS4gKikKICBsZXQgZW5kX29mX2ZpZWxkICgpID0KICAg IGxldCBmaWVsZF9saXN0ID0gTGlzdC5yZXYgIWZpZWxkIGluCiAgICBsZXQgZmllbGRfbGVuID0g TGlzdC5sZW5ndGggZmllbGRfbGlzdCBpbgogICAgbGV0IGZpZWxkX3N0ciA9IFN0cmluZy5jcmVh dGUgZmllbGRfbGVuIGluCiAgICBsZXQgcmVjIGxvb3AgaSA9IGZ1bmN0aW9uCglbXSAtPiAoKQog ICAgICB8IHggOjogeHMgLT4KCSAgZmllbGRfc3RyLltpXSA8LSB4OwoJICBsb29wIChpKzEpIHhz CiAgICBpbgogICAgbG9vcCAwIGZpZWxkX2xpc3Q7CiAgICByb3cgOj0gKFNvbWUgZmllbGRfc3Ry KSA6OiAhcm93OwogICAgZmllbGQgOj0gW107CiAgICBzdGF0ZSA6PSBTdGFydEZpZWxkCiAgaW4K ICBsZXQgZW1wdHlfZmllbGQgKCkgPQogICAgcm93IDo9IE5vbmUgOjogIXJvdzsKICAgIGZpZWxk IDo9IFtdOwogICAgc3RhdGUgOj0gU3RhcnRGaWVsZAogIGluCiAgbGV0IGVuZF9vZl9yb3cgKCkg PQogICAgbGV0IHJvd19saXN0ID0gTGlzdC5yZXYgIXJvdyBpbgogICAgZiByb3dfbGlzdDsKICAg IHJvdyA6PSBbXTsKICAgIHN0YXRlIDo9IFN0YXJ0RmllbGQ7CiAgICBuciA6PSAhbnIgKyAxOwog IGluCiAgbGV0IHJlYyBsb29wICgpID0KICAgIGxldCBjID0gaW5wdXRfY2hhciBjaGFuIGluCiAg ICBpZiBjICE9ICdccicgdGhlbiAoCQkJKCogQWx3YXlzIGlnbm9yZSBcciBjaGFyYWN0ZXJzLiAq KQogICAgICBtYXRjaCAhc3RhdGUgd2l0aAoJICBTdGFydEZpZWxkIC0+CQkJKCogRXhwZWN0aW5n IHF1b3RlIG9yIG90aGVyIGNoYXIuICopCgkgICAgaWYgYyA9ICciJyB0aGVuICgKCSAgICAgIHN0 YXRlIDo9IEluUXVvdGVkRmllbGQ7CgkgICAgICBmaWVsZCA6PSBbXQoJICAgICkgZWxzZSBpZiBj ID0gc2VwYXJhdG9yIHRoZW4gKCogRW1wdHkgZmllbGQuICopCgkgICAgICBlbXB0eV9maWVsZCAo KQoJICAgIGVsc2UgaWYgYyA9ICdcbicgdGhlbiAoCSgqIEVtcHR5IGZpZWxkLCBlbmQgb2Ygcm93 LiAqKQoJICAgICAgZW1wdHlfZmllbGQgKCk7CgkgICAgICBlbmRfb2Zfcm93ICgpCgkgICAgKSBl bHNlICgKCSAgICAgIHN0YXRlIDo9IEluVW5xdW90ZWRGaWVsZDsKCSAgICAgIGZpZWxkIDo9IFtj XQoJICAgICkKCXwgSW5VbnF1b3RlZEZpZWxkIC0+CQkoKiBSZWFkaW5nIGNoYXJzIHRvIGVuZCBv ZiBmaWVsZC4gKikKCSAgICBpZiBjID0gc2VwYXJhdG9yIHRoZW4JKCogRW5kIG9mIGZpZWxkLiAq KQoJICAgICAgZW5kX29mX2ZpZWxkICgpCgkgICAgZWxzZSBpZiBjID0gJ1xuJyB0aGVuICgJKCog RW5kIG9mIGZpZWxkIGFuZCBlbmQgb2Ygcm93LiAqKQoJICAgICAgZW5kX29mX2ZpZWxkICgpOwoJ ICAgICAgZW5kX29mX3JvdyAoKQoJICAgICkgZWxzZQoJICAgICAgZmllbGQgOj0gYyA6OiAhZmll bGQKCXwgSW5RdW90ZWRGaWVsZCAtPgkJKCogUmVhZGluZyBjaGFycyB0byBlbmQgb2YgZmllbGQu ICopCgkgICAgaWYgYyA9ICciJyB0aGVuCgkgICAgICBzdGF0ZSA6PSBJblF1b3RlZEZpZWxkQWZ0 ZXJRdW90ZQoJICAgIGVsc2UKCSAgICAgIGZpZWxkIDo9IGMgOjogIWZpZWxkCgl8IEluUXVvdGVk RmllbGRBZnRlclF1b3RlIC0+CgkgICAgaWYgYyA9ICciJyB0aGVuICgJCSgqIERvdWJsZWQgcXVv dGUuICopCgkgICAgICBmaWVsZCA6PSBjIDo6ICFmaWVsZDsKCSAgICAgIHN0YXRlIDo9IEluUXVv dGVkRmllbGQKCSAgICApIGVsc2UgaWYgYyA9ICcwJyB0aGVuICgJKCogUXVvdGUtMCBpcyBBU0NJ SSBOVUwuICopCgkgICAgICBmaWVsZCA6PSAnXDAwMCcgOjogIWZpZWxkOwoJICAgICAgc3RhdGUg Oj0gSW5RdW90ZWRGaWVsZAoJICAgICkgZWxzZSBpZiBjID0gc2VwYXJhdG9yIHRoZW4gKCogRW5k IG9mIGZpZWxkLiAqKQoJICAgICAgZW5kX29mX2ZpZWxkICgpCgkgICAgZWxzZSBpZiBjID0gJ1xu JyB0aGVuICgJKCogRW5kIG9mIGZpZWxkIGFuZCBlbmQgb2Ygcm93LiAqKQoJICAgICAgZW5kX29m X2ZpZWxkICgpOwoJICAgICAgZW5kX29mX3JvdyAoKQoJICAgICkgZWxzZSAoCQkJKCogQmFkIHNp bmdsZSBxdW90ZSBpbiBmaWVsZC4gKikKCSAgICAgIGZpZWxkIDo9IGMgOjogJyInIDo6ICFmaWVs ZDsKCSAgICAgIHN0YXRlIDo9IEluUXVvdGVkRmllbGQKCSAgICApCiAgICApOyAoKiBlbmQgb2Yg bWF0Y2ggKikKICBpZiggbnJlYWQgPCAwIG9yICFuciA8IG5yZWFkKSB0aGVuIGxvb3AgKCkgZWxz ZSAoKQogIGluCiAgdHJ5CiAgICBsb29wICgpCiAgd2l0aAogICAgICBFbmRfb2ZfZmlsZSAtPgoJ KCogQW55IHBhcnQgbGVmdCB0byB3cml0ZSBvdXQ/ICopCgkobWF0Y2ggIXN0YXRlIHdpdGgKCSAg ICAgU3RhcnRGaWVsZCAtPgoJICAgICAgIGlmICFyb3cgPD4gW10gdGhlbgoJCSAoIGVtcHR5X2Zp ZWxkICgpOyBlbmRfb2Zfcm93ICgpICkKCSAgIHwgSW5VbnF1b3RlZEZpZWxkIHwgSW5RdW90ZWRG aWVsZEFmdGVyUXVvdGUgLT4KCSAgICAgICBlbmRfb2ZfZmllbGQgKCk7IGVuZF9vZl9yb3cgKCkK CSAgIHwgSW5RdW90ZWRGaWVsZCAtPgoJICAgICAgIHJhaXNlIChCYWRfQ1NWX2ZpbGUgIk1pc3Np bmcgZW5kIHF1b3RlIGFmdGVyIHF1b3RlZCBmaWVsZC4iKQoJKQoKKCogbGV0IHJ1bl90aHJlYWRl ZCBmID0gVGhyZWFkLmNyZWF0ZSAoZnVuICgpIC0+IGYgKCk7IFRocmVhZC5leGl0ICgpKSAoKSAq KQoKbGV0ICgpID0gbGV0IGkgPSBvcGVuX2luICJ0ZXN0LmNzdiIgaW4gbG9hZF9yb3dzIChmdW4g XyAtPiAoKSkgaTsgY2xvc2VfaW4gaQpsZXQgKCkgPSBsZXQgaSA9IG9wZW5faW4gInRlc3QuY3N2 IiBpbiBsb2FkX3Jvd3MgKGZ1biBfIC0+ICgpKSBpOyBjbG9zZV9pbiBpCmxldCAoKSA9IGxldCBp ID0gb3Blbl9pbiAidGVzdC5jc3YiIGluIGxvYWRfcm93cyAoZnVuIF8gLT4gKCkpIGk7IGNsb3Nl X2luIGk= --001636c5afb6c242850463186928--