
@mflatt Good morning, Matt. Your fix has resolved the student’s problem! Loading/saving .rkt
files now works as expected on her machine. I’ve reached out to her to learn if she sees other diagnostic messages now (in her excitement she forgot to report that :wink:), but the fix definitely is a significant step forward.

Many thanks again, I highly appreciate the instant attention to the matter. Remarkable.

(She used the BC variant, by the way.)

@dianatrai7 has joined the channel

Great!
I am surprised, but being surprised helps me look at the problem a different way. I’m finally able to replicate the original error by mangling my Racket preferences file, changing one of the paths in the recorded “recently opened files” list to have a bad byte.
If the student is willing to help test this theory: Under the “File” menu’s “Open Recent” submenu, are there weird entries, probably with with question marks? A copy of the student’s racket-prefs.rktd
would also be helpful. Unfortunately, that file is not so easy to locate, but it might be something like Application Data/Roaming/Racket/racket-prefs.rktd
in the student’s home directory.
If this theory about a mangled preferences file is right, then I guess the bug really is fixed. It leave the question of how the preferences file was corrupted, but DrRacket shouldn’t fail due to a broken preferences file.

The student has supplied the requested pieces:


There are indeed the weird Unicode symbols you were expecting, Matt.

The student also explicitly said that she wants to sincerely thank the Racket devs. Hereby communicated, I hope. ;-)

If you need anything else, she’ll be happy to provide it.

Thanks, this is very helpful! It’s concerning that several people have apparently experienced similar corruption of the preferences file, but now we at least know that much.

> What is going on with https://download.racket-lang.org/releases/7.9/catalog/ ? > I cannot install packages via raco. Fixed. Package manager > Settings > add > https://pkgs.racket-lang.org/ The catalog: https://download.racket-lang.org/releases/7.9/catalog/ > remove Now I can migrate packages from 7.8 to 7.9 :slightly_smiling_face:

Hm, interesting. Why CS is so heavy? 199mb (when the regular is 80mb).

Mostly because it has compiled machine code, whereas BC has bytecode, which is more compact

In the following code
(struct v (x y))
(match (v 1 2)
[(v _ 2) 1])
the _
ends up expanding into an application of unsafe-struct-ref
. Would it be possible to optimize racket/match
to not do that when fields are being matched after the last _
? Or is there some reason it has to do that that I’m missing? I’m working on an interpreter of sorts and adding a location field as the first field of every instruction struct in my interpreter then updating the match clauses to ignore that field increased the execution time of some programs by 40%.


I see now that there’s a compile-time error when the wrong number of fields is provided in a clause so it seems like all refs due to _
could be eliminated.

It looks like it may be worse if you have a contracted struct.
https://gist.github.com/samdphillips/7e9e285349ef6427f25b7fc9374ba269

That makes sense when a struct is contracted, though the fact that it’s that much slower is surprising.

This change to racket/match
seems to resolve the original issue, though I’m still not sure if it’s a good idea or if my approach makes sense:
https://github.com/racket/racket/compare/master...Bogdanp:optimize-struct-match

Also I’m wondering if I should extend it so that it eliminates unused variable bindings as well.

I still don’t totally understand the problem

is the problem that there’s a useless let
binding?

Yep and that binding does an unsafe-struct-ref
, which ends up being costly over many iterations.

I think the optimizer ought to just drop those bindings

It doesn’t seem to on Racket CS HEAD

Also, the overhead is even worse for things like:
(time
(for ([x 10000000])
(match b
[(st a) 'ok])))
The above takes 700ms on my machine, vs 70 for the wildcard version.

weird, that should behave the same as the wild-card version but with one extra binding

Yeah, that’s what it expands to:
(let ((b8 b))
(let ((fail9
(λ ()
(match:error b8 (syntax-srclocs (quote-syntax srcloc)) 'match))))
(cond
((st? b8)
(let ((temp11 ((λ (x) (unsafe-struct-ref x 0)) b8)))
(syntax-parameterize
((fail (make-rename-transformer (quote-syntax fail9))))
(let ((a temp11)) (let () 'ok)))))
(else (fail9)))))

Racket BC seems to optimize away the binding and the unsafe-struct-ref

Shall I open a bug report for CS?

yeah although doing better in match is reasonable too

maybe chez doesn’t know if unsafe-struct-ref has a side effect?

certainly CP0 doesn’t know that, especially since it’s a regular Scheme function

maybe needs to be fixed at the schemify layer

In (time
(for ([x 10000000])
(let ([b1 (st-x b)])
(let ([b2 b1])
'ok))))
b2 gets optimized away, but not b1

Er, wait, b
is the contracted instance of the struct. The bindings do get optimized away in
(time
(for ([x 100000000])
(let ([b1 (st-x a)])
(let ([b2 b1])
(let ()
'ok)))))
and even in
(time
(for ([x 100000000])
(let ([b1 (unsafe-struct-ref a 0)])
(let ([b2 b1])
(let ()
'ok)))))

Does the binding get optimized out in (match v [(vector a _ b) 'ok])
?

Doesn’t look like it