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
Fix overflow when using sf::Clock for long time #1771
Conversation
I am worried about the fact that this PR introduces floating point computation to resolve the overflow problem. This might be creating dangerous side effects, since precision now depends on the order of magnitude of the number and the division will be rounded to nearest even instead of floored. I strongly suggest trying to fix the problem with integer arithmetic only instead. |
@Sakarah This PR does not introduce floating point computation, because there was one to begin with, I only rearranged the order of operations. In return statement there was division, so it is floating point computation and it ended up casting to integer type anyway. Also I didn't see that SFML needed something more precise then microseconds, so any potential precision problems will not affect anything. |
Well, an integer division is clearly not a floating point operation. It is the arithmetically correct division that you can add back with the remainder to perfectly restore the original number. After thinking about it, I guess your fix is OK as it does not loose precision as long as you do not exceed 52 bits in the result. This is I admit very unlikely for a result in microseconds. (2^52 ms is over 100 years) |
The introduction of As for floating point and precision I have to disagree, but let's move on. Do you have some suggestions on how we can avoid those operations? I can't think of one. |
Yes obviously you want to explicit the conversions as you did, the warning says that the operation exist but is not written so the code might be misleading if you don't write these things. Where do you disagree ? I just said that precision is fine until the result time is greater than 52-bits. And this is arguably enough. In case I wasn't clear I changed my mind about the necessity of pure integer arithmetic in this case. I was actually more worried than against. A comment justifying that a 52-bit precision provided by double is enough might be a good idea to convince maintainers if they are as picky as me. Just for information, if you wanted to do this with pure integer arithmetic, you can use a code such as: Int64 full_seconds = time.QuadPart / frequency.QuadPart;
Int64 remainder = time.QuadPart % frequency.QuadPart;
return full_seconds * 1000000 + remainder * 1000000 / frequency.QuadPart; However I benched the performances out of curiosity, and your code is actually faster on x86_64, gcc -O3 than both the current SFML and my solution. Floating point multiplication is incredibly cheap compared to 64 bit integer division. |
@Sakarah Thank you for replies. I hope this PR will be added to SFML as soon as posible, Clock class is very convenient to use. I didn't think of your solution and maybe I think I understand your concern. In my mind every division operation is a floating point operation, because even when two operands are integers, result is a floating point type. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Mozzg Thanks a lot for your PR. Did this code solve the problem you had in #1765?
I'll try to test it myself soon.
In my mind every division operation is a floating point operation, because even when two operands are integers, result is a floating point type.
No, integer division is a different machine instruction than floating-point division, see e.g. DIV and FDIV. The result of integer division is again an integer, not a floating point type.
Also, could you squash your commits into one (git rebase
or the UI of your choice)? For additional changes, you can use git commit --amend
to modify the last commit. Let me know if you need help with that.
If you don't know how to do that, don't worry about it. Since you allowed editing of the branch by the maintainers, I can align the commits the way we usually handle them. But if you want to learn more about git, feel free to do the changes. 🙂 |
@Bromeon @eXpl0it3r I did not used this exact code in my project, rebuilding SFML would be too much work. I just replaced sf::Clock class and time manipulation with this adjusted code. I tested the code by adding a constant, I wrote this test method in my issue #1765. The run/test without using a constant (but only with custom code without Clock class) is going right now and results should be known in 3 days. My code looks like this:
|
57a39cd
to
08a8bcd
Compare
I squashed the commits and rebased onto master. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me 👍🏼
I ran the tennis
example for a few minutes on Windows (with a displayed clock), and seems to work well from what I can tell. I didn't let it run long enough to trigger the overflow, though 😉
Description
This PR is related to the issue #1765
When using sf::Clock class, method restart() may return negative value in continious work because of overflow when calculating current time in microseconds. This pull request is trying to fix that.
Tasks
How to test this PR?
See description in issue #1765