Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Split std_specs in 32 bits ci #8065

Merged
merged 3 commits into from
Aug 12, 2019
Merged

Conversation

bcardiff
Copy link
Member

@bcardiff bcardiff commented Aug 9, 2019

Only for std_specs run against the compiled compiler which seems to be the one failing

This introduces a way to run a subset of the specs via an env var SPEC_SPLIT. Is not expected to be used as a public API but is a workaround to help a bit the CI.

Let's see how it works...

@bcardiff
Copy link
Member Author

bcardiff commented Aug 9, 2019

Still. failing, but I noticed, the ci uses threads=1 but for the compilers run in the compiler_spec n_threads will still be 8. Could that be something impacting this @asterite?

bin/ci Outdated
with_build_env 'SPEC_SPLIT="1%4" make std_spec threads=1'
with_build_env 'SPEC_SPLIT="2%4" make std_spec threads=1'
with_build_env 'SPEC_SPLIT="3%4" make std_spec threads=1'
with_build_env 'make compiler_spec docs threads=1'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should use SPEC_SPLIT here too. This is where it's failing.

@straight-shoota
Copy link
Member

straight-shoota commented Aug 9, 2019

How's this supposed to work? If I understand the issue correctly, the compiler runs out of memory while compiling the specs. Unless I'm missing some key concept here, changing the logic in Spec.matches? only changes which specs are executed (at runtime). But they're still compiled into the spec binary. In fact, this is now compiling std_spec four times.

We don't need to split spec execution but already spec compilation.

@asterite
Copy link
Member

asterite commented Aug 9, 2019

@straight-shoota As far as I can tell from CI's output, it's failing when running the specs, not when compiling them.

src/spec/dsl.cr Outdated
# :nodoc:
def self.matches?(description, file, line, end_line = line)
spec_pattern = @@pattern
spec_line = @@line
locations = @@locations
split_filter = @@split_filter

if split_filter && line % split_filter[:quotient] != split_filter[:remainder]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The way I thought about SPLIT_SPEC, each time you do it a counter would get incremented, and it's this counter you would check against.

By using just the line number it might happen that more specs are in lines 1 modulo 4, for example.

But if it works then it's a good start :-)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, that's another way to filter them. The distribution of the std_spec at least was good enough.

$ make std_spec
7744 examples, 0 failures, 0 errors, 8 pending

$ SPEC_SPLIT="0%4" make std_spec
1958 examples, 0 failures, 0 errors, 2 pending

$ SPEC_SPLIT="1%4" make std_spec
1856 examples, 0 failures, 0 errors, 2 pending

$ SPEC_SPLIT="2%4" make std_spec
1958 examples, 0 failures, 0 errors, 2 pending

$ SPEC_SPLIT="3%4" make std_spec
1972 examples, 0 failures, 0 errors, 2 pending

@asterite
Copy link
Member

asterite commented Aug 9, 2019

Maybe we can try running all specs (like this, splitted) with -v to see in which one it fails. Maybe there's a bunch of specs that allocate too much memory and they are the only problem... 🤔

@straight-shoota
Copy link
Member

Hm, yeah it seems you're right. Compiling the specs is not the issue. But when it's at runtime, this might actually mean there are some memory leaks. So -v and perhaps a GC status report between examples would help identify the issues.

@bcardiff bcardiff force-pushed the split-specs branch 2 times, most recently from 7435599 to 4a6611e Compare August 9, 2019 17:44
@asterite
Copy link
Member

asterite commented Aug 9, 2019

@straight-shoota Oh, I know for sure there's a memory leak. When we compiler specs without the prelude the malloc that's used when you do SomeClass.new or Pointer.malloc is C malloc, and there's no matching free for that (there's no GC), so all specs that run without a prelude that create classes or allocate memory through Pointer will currently leak that memory. And we have a a lot of those tests.

Unfortunately I can't think of an easy way to fix that.

@straight-shoota
Copy link
Member

@asterite I see. There is the option to disable JIT compilation and run specs without prelude in a separate process as well. So it's a trade-off between speed and memory. I'm not sure how much a difference it makes, is it worth looking into that? But anyway, this is just relevant for specs and not a critical problem. So as long as we get the 32-bit specs to work by splitting them up, I guess this should be fine.

@straight-shoota
Copy link
Member

Another idea, just from the top of the head: Maybe we could somehow rig the malloc calls inside the JIT-executed spec code. So that we can keep track of the memory and free it after the spec has completed. Codegen can probably be changed for that, so it would be a little bit different code from normal execution, but that might be acceptable.

@j8r
Copy link
Contributor

j8r commented Aug 10, 2019

The issue isn't just for 32bits, in general too much memory is used for tests. It would be better to fix the root cause instead. The memory in the CI isn't infinite, and the limit might be eventually reached in the future even for 64bit. It also impacts devs who are using machines with not much RAM.

@asterite
Copy link
Member

j8r PRs and ideas are welcome. This just affects us Crystal developers. I think this fix is fine and it let's us move forward.

Copy link
Contributor

@j8r j8r left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest to have an environment variable to run split specs.
It will be useful for those running specs in ARMhf, like distribution (Alpine) or devs, or just those having not much RAM in their 64bit OS.

@bcardiff
Copy link
Member Author

I'm pushing temporarily @asterite's commit to check if that fix the ci. Other than that the PR is ready for review and squash

@bcardiff bcardiff added this to the 0.30.1 milestone Aug 12, 2019
@bcardiff bcardiff merged commit 80d9252 into crystal-lang:master Aug 12, 2019
bcardiff pushed a commit that referenced this pull request Aug 12, 2019
* Skip some specs for 32 bits
* Restrict threads used in the compiler during the specs
* Split std_specs in 32 bits ci
@bcardiff bcardiff deleted the split-specs branch August 13, 2019 17:27
dnamsons pushed a commit to dnamsons/crystal that referenced this pull request Jan 10, 2020
* Skip some specs for 32 bits
* Restrict threads used in the compiler during the specs
* Split std_specs in 32 bits ci
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants