Re: [racket-users] How to improve compile times?

2017-05-03 Thread Daniel Brunner
Am 28.04.2017 um 08:07 schrieb Alex Harsanyi:

> 
> In the end, the start up time does not bother me too much, as it is a GUI 
> application and I spend a lot of time using it after starting it up, so the 7 
> second wait is acceptable. I have other, more interesting, application 
> features to work on anyway :-)
> 

As one of the users of ActivityLog2 I do not mind the startup time either.

Best wishes,
Daniel

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] How to improve compile times?

2017-04-28 Thread Alex Harsanyi
On Friday, April 28, 2017 at 10:04:52 PM UTC+8, Matthew Flatt wrote:
> I notice that your code calls `running-stickman-icon` on startup, which
> takes about 2 seconds on my machine.

Well, this is embarrassing for me.  I remember adding that code in and having 
to decide on whether to wait 2 seconds for the "About" dialog to be ready or to 
compute the value at start up, delaying startup time.  I made a mental note to 
create a PNG image and loading that, but forgot about doing it.   Thanks for 
pointing it out.

Alex.

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] How to improve compile times?

2017-04-28 Thread Matthew Flatt
At Thu, 27 Apr 2017 23:07:01 -0700 (PDT), Alex Harsanyi wrote:
> > * The size of the bytecode does matter (and switching to Chez scheme's 
> run-time could hopefully improve that)
> 
> All the .zo files put together are about 4Mb.  I'm not sure if this is big or 
> not?

4MB is not big. But your program pulls in `framework`, `plot`, and
`math` (which is used by `plot`, anyway), which all have to be loaded
and involve lots of bytecode.

> What I'm wondering is if class definition actually runs some code when a 
> module is required, like the code below:
> 
> (define my-class% 
>(class object% (init) (super-new)
>   (define/public (say-hello) (printf "hello~%"

Yes, constructing the class does take some work, but it's unlikely to
be a noticeable amount of work.

I notice that your code calls `running-stickman-icon` on startup, which
takes about 2 seconds on my machine. Meanwhile, just loading
`plot`+`math`+`framework` takes about 2.5 seconds. Maybe there are some
other slow-to-load libraries, and then maybe improving code-loading
times in Racket will help for your application.

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] How to improve compile times?

2017-04-28 Thread Matthew Flatt
At Thu, 27 Apr 2017 11:47:41 -0700 (PDT), Dupéron Georges wrote:
> If I understand correctly, [...]

Yes, that all looks right.

> It would be nice to find a way to detect what code gets executed when
> a module is required, at the various meta-levels. Maybe running raco
> cover on an empty file containing only (require some-module) could
> help?

Yes, that sounds helpful. The module loader should log events about
module loading an instantiation at various phases, and then a tool
could put that information in a readable format. I'll add that to my
"to do" list for the new expander.

> I'm not sure how submodules fit in this picture (the main concerns being the 
> test submodule, and the doc submodule for literate programs).

Submodules differ from top-level modules only in that compiling a
module from source implies compiling its submodules, even if you do not
run the submodules. In compiled form, however, submodule bytecode is
loaded or not independent of other modules, so the existence of a
`test` or `doc` submodule does not affect the time required to load the
enclosing module by itself.

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] How to improve compile times?

2017-04-28 Thread Dupéron Georges
> > * Alex Harsanyi's start-up time is due to run-time (phase 0) initialisation 
> > code in the required libraries, including things like (define v 
> > costly-expression), which look like they could be saved as constants, but 
> > actually involve running the expression.
> 
> I actively try to avoid this case and I believe the program has little or no 
> such code anymore.  However, even when I removed such cases, it did not seem 
> to make much difference.  Racket code actually runs fast.

Just a quick clarification: I meant that such initialisation code may be 
present in the libraries that you require, not in your own code (and so you do 
not have much control over this, unless you start modifying the libraries).

> > * If Alex Harsanyi's code uses dynamic-require or eval, the phase 1 
> > initialisation code of the required libraries is executed when eval or 
> > dynamic-require are first invoked.
> 
> The code does not use any of those things.  Also, apart from 3 macros dealing 
> with baking in some API KEYS at compile time, there are no uses of 
> `define-syntax` and friends.

Again, there could be some use of eval within library code, or in code 
generated by library macros, even if there is no direct use of eval in your 
code.

Nice application, by the way :)

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] How to improve compile times?

2017-04-28 Thread Alex Harsanyi
On Friday, April 28, 2017 at 2:47:41 AM UTC+8, Dupéron Georges wrote:
> Thank you Matthew for the explanation.
> 
> If I understand correctly,
> 
> * Alex Harsanyi's start-up time is due to run-time (phase 0) initialisation 
> code in the required libraries, including things like (define v 
> costly-expression), which look like they could be saved as constants, but 
> actually involve running the expression.
> 

I actively try to avoid this case and I believe the program has little or no 
such code anymore.  However, even when I removed such cases, it did not seem to 
make much difference.  Racket code actually runs fast.

> * If Alex Harsanyi's code uses dynamic-require or eval, the phase 1 
> initialisation code of the required libraries is executed when eval or 
> dynamic-require are first invoked.

The code does not use any of those things.  Also, apart from 3 macros dealing 
with baking in some API KEYS at compile time, there are no uses of 
`define-syntax` and friends.

> * The size of the bytecode does matter (and switching to Chez scheme's 
> run-time could hopefully improve that)

All the .zo files put together are about 4Mb.  I'm not sure if this is big or 
not?

What I'm wondering is if class definition actually runs some code when a module 
is required, like the code below:

(define my-class% 
   (class object% (init) (super-new)
  (define/public (say-hello) (printf "hello~%"


In the end, the start up time does not bother me too much, as it is a GUI 
application and I spend a lot of time using it after starting it up, so the 7 
second wait is acceptable. I have other, more interesting, application features 
to work on anyway :-)

If anyone wants to look at the startup time, or help out with any other 
development, here is the application:

https://github.com/alex-hhh/ActivityLog2

Best Regards,
Alex.

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] How to improve compile times?

2017-04-27 Thread Dupéron Georges
Thank you Matthew for the explanation.

If I understand correctly,

* Alex Harsanyi's start-up time is due to run-time (phase 0) initialisation 
code in the required libraries, including things like (define v 
costly-expression), which look like they could be saved as constants, but 
actually involve running the expression.

* If Alex Harsanyi's code uses dynamic-require or eval, the phase 1 
initialisation code of the required libraries is executed when eval or 
dynamic-require are first invoked.

* The size of the bytecode does matter (and switching to Chez scheme's run-time 
could hopefully improve that)

Concerning the definition of a macro:

;; a.rkt
#lang racket
(require "b.rkt")
v

;; b.rkt
#lang racket
(require "c.rkt")
(provide v)
(define v (foo))

;; c.rkt
#lang racket
(provide foo)
(require racket/function)
(define-syntax foo (curry (λ (v stx)
(displayln v)
#'1)
  (begin (displayln "XX")
 (string-append "c" "c"

* The "cc" is printed when compiling b.rkt, but not when running a.rkt, nor 
when compiling a.rkt.

* The curry and string-append are executed when compiling c.rkt, when c.rkt is 
instantiated because it is required by b.rkt, and another fresh instantiation 
of c.rkt is done when it is transitively required by a.rkt. This can be seen by 
running raco make c.rkt; raco make b.rkt; raco make a.rkt, and observing that 
XX is printed each time.

* When executing racket a.rkt, no XX is printed unless eval is called at 
run-time at some point.

My conclusions, in terms of performance hints are that:

* It is safe to put code within the body of a transformer function (bound to a 
macro).

* Code outside of transformer functions (to define compile-time constants, or 
the curry in the example above) has a cost when compiling all files which 
transitively require that module. It also has a one-time run-time cost if/when 
eval, dynamic-require or something similar is used.

* The bytecode size has an impact too.

* It is therefore better to avoid requiring too many modules if they are not 
needed.



It would be nice to find a way to detect what code gets executed when a module 
is required, at the various meta-levels. Maybe running raco cover on an empty 
file containing only (require some-module) could help?



I'm not sure how submodules fit in this picture (the main concerns being the 
test submodule, and the doc submodule for literate programs).

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] How to improve compile times?

2017-04-27 Thread Matthew Flatt
At Wed, 26 Apr 2017 15:04:15 -0700 (PDT), Dupéron Georges wrote:
> However, I'm not sure what operations can cause compile-time code to
> be run in this situation. My (possibly incorrect) understanding is
> that macros are executed only once (when expanding the code), but the
> code to the right-hand-side of a (define-syntax foo
> costly-operation), and the code within a (begin-for-syntax …) will
> both be run each time the module is required.

Each time a module is compiled, the compile-time code for any imported
modules is run in fresh compile-time instantiations of those modules.
("Compile" = "expand" in this context.)

So, given "a.rkt" as

 ;; a.rkt
 #lang racket
 (require "b.rkt")

and "b.rkt" as

 ;; b.rkt
 #lang racket
 (begin-for-syntax (displayln "b"))

if you use `racket a.rkt` leaving both modules as source, you'll see
printed "b" twice: once when compiling "b.rkt", and once when compiling
"a.rkt". If you use `raco make a.rkt`, you'll also see "b" printed
twice, but then `racket a.rkt` will not print "b".


If you have run `raco make a.rkt` already, then here's a potentially
confusing result:

 % racket
 Welcome to Racket
 > (require "a.rkt")
 > 1
 b
 1

In this case, no "b" is printed to load and execute the runtime part of
"a.rkt". Still, compile-time module instances have been created to
handle further evaluation in the REPL. So, as soon as `eval` is called
by the REPL for the expression `1`, the compile-time parts of "a.rkt"
and "b.rkt" are run. That's why "b" prints, and why it prints so late.


When you've compiled a program to bytecode and then run it, whether any
compile-time code is run depends on whether you use `eval` or
`dynamic-require` or similar.

Another part of the run time is just reading in bytecode, though. The
bytecode-loading part of Racket seems slower than it should be, and
that was one of the things I had planned to rebuild --- but now I'm
hoping that we'll get better load times by swapping Chez Scheme in
place of the current runtime system.

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[racket-users] How to improve compile times?

2017-04-26 Thread Dupéron Georges
Hi all!

Some of my libraries take a while to load: just adding a (require mylib) to an 
empty #lang racket/base file bumps the compile time from 0.5s to 1.5s, even if 
no bindings from the library are used. After experimenting a bit, it seems that 
the overhead is mainly due to other modules which are transitively required 
(typed/racket, syntax/parse, …).

Assuming that all the files except the main one are already byte-compiled with 
raco make, what are the factors which affect compile times when a library is 
(possibly transitively) required? Note that we're talking about milliseconds 
here, but when a lot of modules are required, these can add up.

1. Number of bindings directly provided?
2. Number of bindings provided by transitively-required modules (including 
those which are not re-provided, and are not in the main file's namespace)
3. Number of files which are transitively required?
4. Size of the fully expanded code (or size of the bytecode)?
5. Compile-time operations, e.g. within a begin-for-syntax in a 
(transitively-)required module?
6. When a module is required at several meta-levels, does it affect the compile 
time significantly, or is it roughly the same cost than requiring it only once?
7. Something else?

Point 5 seems to matter, as compiling a.rkt still prints "Hello" even if b.rkt 
is already compiled:

a.rkt:
#lang racket/base
(require "b.rkt")

b.rkt:
#lang racket/base
(require (for-syntax racket/base))
(begin-for-syntax (displayln "Hello"))

However, I'm not sure what operations can cause compile-time code to be run in 
this situation. My (possibly incorrect) understanding is that macros are 
executed only once (when expanding the code), but the code to the 
right-hand-side of a (define-syntax foo costly-operation), and the code within 
a (begin-for-syntax …) will both be run each time the module is required.

What I would like is to learn a few "good practices" and gotchas concerning 
compile-time performance.

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.