-
-
Notifications
You must be signed in to change notification settings - Fork 743
fix Issue 11009 - Regression (2.064 git-head): DMD consumes huge memory ... #1565
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
Conversation
Assigning to @AndrejMitrovic |
Any chance you have a large enum that I could use to test another version of the NoDuplicates template? It would be a bit slower, but should be quite a bit easier on the memory usage, due to the fact only 1 template would be instantiated, rather than 4-5 for every enum member. Also, any suggestion the number of elements at which I should switch between the faster, more memory intensive implementation, and the slower, less memory intensive implementation? |
I'm unsure, you'd have to weight time/memory for both implementations, but it's kind of hard, since we are talking about a compile time function.
You can try this one It has no actual duplicates, but that shouldn't be a problem, since it needs to be processed fast too. |
Well, so far I have it so that, provided there are no duplicate values, you can have as many values as |
It seems like most of those traits that end up using Btw, you've changed the switch into a series of if statements. This now improves memory usage at compile-time, but what happens with performance at runtime? I hope the compiler is smart enough to optimize this and turn it into a switch table in the optimizer. |
I wrote a import std.traits : CommonType;
private CommonType!values[] auto noDuplicates(values...)()
{
auto asArray = [values]; // relies on values having a common type
alias Key = typeof(asArray[0]);
bool[Key] foundSet; // In lieu of a hash set
Key[] result; // foundSet.keys not used because it does not preserve order
foreach(ref value; asArray)
{
if(value !in foundSet)
{
foundSet[value] = true;
result ~= value;
}
}
return result;
}
// TODO: does not account for invalid AA keys. What are the current rules
// on key types?
template NoDuplicates(values...) if(!is(CommonType!values == void))
{
alias NoDuplicates = toTypeTuple!(noDuplicates!values());
} edit: Oh, and I was testing on 2.063 and encountered a "recursive alias" error when edit2: The |
Well, the implementation is now practically copied verbatim from Yes, GenericEraseAll is very memory intensive. That said, I think I can bring the switch back into the equation. Instead of doing an "eager" NoDuplicate, we could just test in each loop. This would be MUCH less compiler intensive, since we don't actually need a Duplicate-less list. We just want to skip the duplicates. EG: switch (value)
foreach (I, member; EnumMembers!S)
{
static if (staticIndexOf!(member, EnumMembers!S[0 .. I] == -1)
{
case member:
... I think In any case, sleep now, tests later. |
|
It can be made O(log(N)) depth (which is mostly what counts in meta programming). |
Yes, that will help memory use, but it still leaves processing time as an O(n^2). That should never be necessary. edit: Remember that the number of iterations here is directly linked to the number of instantiations so it strongly affects memory use as well. |
Well, O(n^2) operations, which may or may not end up being o(n^2) time. We'd have to test, the compiler can surprise us sometimes. Another simple solution is to simply insert a test if the EnumMembers has less than, say, 20 elements, and only do the switch in that case. If not, we just go "toStr" straight away. |
The compiler could even be smart and avoid generating duplicate case errors if the statements for those cases are also equal. But that's pushing it. :) |
…ry when it compiles enum containing many items This is a fixup of pull #1540. Turns out NoDuplicates is scary inefficient for large input. This cleans up and simplifies the pull somewhat.
Alright. I update a new version. Observations:
I think this "fix" is a good compromise, that retains the original intent of the change. @AndrejMitrovic : How do you feel about this version. Should I change anything. If there is anything you don't like, do tell me. Or if you have a better idea, you can submit your own version. I'd review. |
Looks good, although |
fix Issue 11009 - Regression (2.064 git-head): DMD consumes huge memory ...
@monarchdodra: Thanks for these fixups! |
The cost for exactly 50 is +.5 seconds. It seems a little expensive to me. We'd have to bench the run-time to see if there is even any difference anyways... Regardless, the "true" optimization which you initially created is to make it non-allocating, and this is preserved regardless of what we decide the bounds are, so I'm not worrying about it none too much. BTW, whilst we are improving "To", I have two open pulls: |
...when it compiles enum containing many items
http://d.puremagic.com/issues/show_bug.cgi?id=11009
This is a fixup of pull #1540.
Turns out NoDuplicates is scary inefficient for large input.
This cleans up and simplifies the pull somewhat.