wanpeebaw
2020-11-9 08:02:44

I have a Brainfuck program translated into Racket program instruction by instruction. Can someone confirm that this is the optimal solution? Or there is still overhead that can be reduced. https://gist.github.com/sleepnova/241c524a3311390ba9e2ff5aed93cbff\|https://gist.github.com/sleepnova/241c524a3311390ba9e2ff5aed93cbff


soegaard2
2020-11-9 08:31:29

@wanpeebaw I observe several inc instructions in a row. You could make a peep-hole optimizer that rewrites to (inc n) . One way to do this, is to expand to (peephole (inc) (inc) (inc) (inc) (inc) (inc) (until (zero? (current-byte)) (dec) (ptr++) ...) and let peephole me a macro that rewrites its input.

Similar optimizations can be done for repeated occurrences of dec, ptr++, ptr-- . Handling mixed sequences of inc and dec would be even better :wink:


hoshom
2020-11-9 08:41:25

@sorawee @343519265 thanks for the workaround.. In my case switching to the base language worked, too, but should I open an issue on GitHub?


soegaard2
2020-11-9 08:42:15

I see several uses if (current-byte) which expands to (bytes-ref arr ptr). If the current byte is read more often than it is written to, you could make a “cache”.

Simply store the current byte in a variable: (define current 0) The price is that set-current-byte! must update the both the variable as well as the array arr.


laurent.orseau
2020-11-9 11:41:15

Is it possible to write a macro (count-me) that • Associates a different counter to each syntactic call site (possibly using syntax-line and syntax-source-path-string) • The counter is in a struct field such as (struct count (n)) • A struct instance is initialized on the first call to the corresponding (count-me) call site • Subsequent calls at the same call site do not use a condition to check if the struct has been initialized, and instead does the minimum possible work such as (set-count-n! the-counter (+ (count-n the-counter)))


laurent.orseau
2020-11-9 11:43:16

My current solution uses a hash-ref at each call, but this is very costly. The ultimate purpose is to count the time and the number of calls at different sites, for debugging/optimization purposes. (raco profile --use-errortrace is pretty good, but sometimes not precise enough)


laurent.orseau
2020-11-9 11:44:54

FYI, incidentally, I also need to gather the struct instances to display the stats when the program exists.


sorawee
2020-11-9 12:12:18

Yes, please do!


mflatt
2020-11-9 13:03:29

Do you need this to work with compilation to “.zo” form? If not, you can use the 3-D macro approach, where the macro expands to a quoted mutable object. As long as the ojbect isn’t something the expander recognizes, like a box or vector, it will be left alone by further expansion and compilation.


greg
2020-11-9 13:51:50

I would not expect most of Racket Mode to work.

Using racket-mode buffers to edit files: yes.

Using racket-xp-mode or racket-repl-mode: no. They need to run a Racket “back end”, which assumes it’s running where your source files are.


samth
2020-11-9 13:58:28

Can you report a bug?


phanthero
2020-11-9 14:15:45

Since I do have racket installed where my source files are (the remote machine), can I force Racket Mode to start up a backend on the remote? i.e. allow Racket Mode to make backends on the remote machine somehow


laurent.orseau
2020-11-9 14:21:18

Interesting. Would you happen to have a pointer that would put me on the right track? (I’m not “seeing it” currently).


mflatt
2020-11-9 14:32:52

laurent.orseau
2020-11-9 14:48:36

Woah, thanks!

The “3d” part is because the compiler is going to keep #,c as a single struct instance rather than generating something like (begin (set-counter-n! '#s((counter #(0 1)) 0 (* x x)) (add1 (counter-n '#s((counter #(0 1)) 0 (* x x))))) (* x x)) which would of course not work?

Also, I’m stumped by these last 3 lines :smile:


mflatt
2020-11-9 14:50:23

Yes. The last three lines are there to report all of the generated counters, transporting them from the compile-time list to a run-time list.


343519265
2020-11-9 14:52:31

It seems @hoshom is going to do this. By looking at the expand observer, this bug results from add-annotations in “class-prims.rkt”, which calls method-procedure? to expand the rhs of definitions before the class environment setup.


laurent.orseau
2020-11-9 14:58:51

I see, thank you, that’s quite instructive


mflatt
2020-11-9 15:01:18

Just to be clear, we normally discourage 3-D macros, because they break the phase separation and tend not to play well with compilation to “.zo” form. This kind of instrumentation task is the one use I know that seems possibly ok.


laurent.orseau
2020-11-9 15:16:59

Makes sense.


laurent.orseau
2020-11-9 15:25:09

There are some strange effects indeed. After turning this into a module, it seems that the counters are not shared by different requires from different modules, correct?


mflatt
2020-11-9 15:30:12

That doesn’t sound right. Are you using something like (define counters (done)) to have the list of counters, and then looking at them after all modules run?


laurent.orseau
2020-11-9 15:39:16

In main.rkt (riskily simplified from real working case): (module+ main (require "a.rkt" "counters.rkt") (count (fun-from-a)) (#%expression (done))) where a.rkt also requires “counters.rkt” and uses count. Then the results shows only the count of “main.rkt”


mflatt
2020-11-9 15:41:38

Oh, I see what you mean. Yes, the counters variable will be specific to a module. You need to use something like (done) in each module to collect the counters for that module.


laurent.orseau
2020-11-9 15:50:11

Ok, that works indeed


mflatt
2020-11-9 21:06:39

@robby (cc: @samth) It turns out that some tests rely on the old keybindings. At least, the frame.rkt test in frameworks/test does around line 184. I guess the tests should just change?


robby
2020-11-9 21:06:55

Yeah, I’ve changed one so far


robby
2020-11-9 21:07:14

I’m happy with just changing the tests but haven’t been proactive about finding them and fixing them


hoshom
2020-11-10 04:48:55

I’ve opened a bug in the typed racket repo