-
Notifications
You must be signed in to change notification settings - Fork 38
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
string constructor performance #1742
Comments
I tried to solidify the further and got some confusing results, so will add more over time. time spicyz -o ex ex-null10000.spicy real 0m27.564s |
My orig discovered issue took place in an "import" - just checked an import version and the effect is the same. (not worse). Just noting to rule that out. |
note I was very loosely saying string above, when really it was bytestrings. As I thought it would be interesting, I morphed it into a string test. On the plus side it wasnt in minutes, but clearly there is some interesing optimization happening: so the one char long case dropped down to almost the null case for bytestrings, but the actual null case plummeted 4x as well, so it was actually 6x longer with one char in strings. These are consistent with 6.2 (same delta). So potential opt point, but not a problem....its something about bytestrings. |
Since this issue is strictly about compilation performance it has not much to do with the performance of an actual constructor (these would be invoked at runtime, not at compile time). Instead it appears that the issue is that for big container literals we generate C++ code which is (very) expensive to compile (this depends on the exact C++ compiler used, but seems consistent). In particular for Spicy code like this global xs = vector(1, 2, 3, 4, 5); we generate C++ roughly equivalent to this std::vector xs{1, 2, 3, 4, 5}; The elements are passed as an I opened #1744 to generate C++ code which seems to be easier to digest for the compiler. For the time being you could unroll the initialization of "huge" containers yourself, e.g., for a global xs: vector<uint8>; # Construct empty `vector`.
# Calling `reserve` for a `vector` before inserting might improve runtime performance.
xs.reserve(5);
# Add elements.
xs.push_back(1);
xs.push_back(2);
xs.push_back(3);
xs.push_back(4);
xs.push_back(5); Moving this to a dedicated function might improve readability and maintenance of your code (but still not allow initializing a |
I'd be surprised if this boils down to large |
I should add: in particular, the original code was like the unrolling you describe, and that took many minutes to compile, whereas using vectors is 100x faster. |
also I think the string result (vs) bytestring argues against it being vector. Had another idea for benchmarking, will try later today. |
I also benchmarked to be sure, so maybe I am not looking at the right thing. I compared code using an initializer list of a non-trival object (in Smoot's case a std::vector<std::string> f() {
auto xs = std::vector<std::string>{
" ", // Repeated `n` times.
// ...
};
return xs;
}
int main() { f(); } and another version using auto xs = std::vector<std::string>();
xs.push_back(" "); // Repeated `n` times.
// ../ I then compiled this with If the All this is roughly equivalent to what is happening for the reproducer; #1744 switches from initializers to insertion and I see an improved performance. |
That's presumably the difference. Your example above used |
I'll attach a sample, but I discovered that loading a pre-computed hash table got really slow on spicy.
After some false trails, I think its actually constructing strings that is the problem. Compare the two attached .spicy files in the zip, in the next comment.
one has 10k empty strings (fast) the other 10k one byte strings (slow) for me
on 7.0.0-dev.254. On 6.0.3 and 6.2.0 however they are both 28s.
The text was updated successfully, but these errors were encountered: