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

Optimize getfilecontents() to reduce chance of race for client_state.xml #1426

Conversation

cyrossignol
Copy link
Member

@cyrossignol cyrossignol commented Apr 4, 2019

The getfilecontents() function loads a file into memory, and the previous implementation read the file line-by-line into a buffer. We use this function to load BOINC's client_state.xml file. A user on Slack reported that the wallet took 7 seconds to read this file, and @jamescowens confirmed that it took 10 seconds with his version.

As also confirmed on Slack, BOINC aborts on Windows when trying to update client_state.xml if the wallet holds the file open during start-up. This change improves the performance of the function to greatly reduce the chance of a race between Gridcoin and BOINC.

Copy link
Member

@jamescowens jamescowens left a comment

Choose a reason for hiding this comment

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

Tested it out. Even more compact than my own solution. Reduced the client_state.xml load time on my windows testnet wallet to < 0.5 seconds from about 10 seconds.

@jamescowens
Copy link
Member

I can do a special build of 4.0.2.0 release with just this change to give to KarVi71 and see if it fixes his problem. If so, we can hold off on doing more substantial plumbing work, such as implementing RPC communication between the BOINC client and the wallet.

@jamescowens jamescowens added this to the Denise milestone Apr 4, 2019
@denravonska denravonska merged commit addb536 into gridcoin-community:development Apr 4, 2019
@tomasbrod
Copy link
Member

Can the file be opened in such way, that does not block boinc from writing to it?

@jamescowens
Copy link
Member

jamescowens commented Apr 4, 2019 via email

@tomasbrod
Copy link
Member

That is unfortunate and breaks the copy-and-replace pattern.

@jamescowens
Copy link
Member

It looks like minimizing the amount of time we have the file open has practically solved the issue, but I agree it is an ugly issue underneath....

@cyrossignol
Copy link
Member Author

cyrossignol commented Apr 5, 2019

Fortunately, BOINC does retry the write/rename operations on client_state.xml, so as long as we read the file quickly, the wallet probably won't ever kill BOINC anymore.

I studied this issue for a bit because I was completely blown away by the evidence which showed that it took such a huge amount of time to read a file that's only a few MB large. I wanted to understand why this was happening so that I won't make the same mistake later. At first, I thought that the way that the function opened and closed the file twice introduced some delay because of something in the OS, but removing that nonsense didn't change the result.

The culprit appears to be in the way that the old function appended each line to the buffer:

while (getline(myfile, line))
{
    //       vvvvvv--- copy
    buffer = buffer + line + "\n";
    //     ^--- swap
}

Namely, the function really didn't append anything to the existing buffer. Instead, it copied the whole buffer and replaced it for every line. For larger client_state.xml files, we were churning through over a GB of data just to read the file.

The issue disappeared when I changed that line of code to:

buffer += line + "\n";

...for which std::string overloads operator+=() to append the input to the internal buffer. If the function was written like this to begin with, we may never have seen the race condition with BOINC.

@jamescowens
Copy link
Member

jamescowens commented Apr 5, 2019 via email

denravonska added a commit that referenced this pull request May 10, 2019
Added:
 - Replace NeuralNetwork with portable C++ scraper #1387 (@jamescowens,
   @tomasbrod, @Cycy, @TheCharlatan, @denravonska).
 - Allow compile flags to be used for depends #1423 (@G-UK).
 - Add stake splitting and side staking info to getmininginfo #1424
   (@jamescowens).
 - Add freedesktop.org desktop file and icon set #1438 (@a123b).

Changed:
 - Disable Qt for windows Travis builds #1276 (@TheCharlatan).
 - Replace use of AppCache PROJECT section with strongly-typed structures #1415
   (@cyrossignol).
 - Change dumpwallet to use appropriate data directory #1416 (@jamescowens).
 - Optimize ExtractXML() calls by avoiding unnecessary string copies #1419
   (@cyrossignol).
 - Change signature of IsLockTimeWithinMinutes #1422 (@jamescowens).
 - Restore old poll output for getmininginfo RPC #1437 (@a123b).
 - Prevent segfault when using rpc savescraperfilemanifest #1439 (@jamescowens).
 - Improve miner status messages for ineligible staking balances #1447
   (@cyrossignol).
 - Enhance scraper log archiving #1449 (@jamescowens).

Fixed:
 - Re-enable full GUI 32-bit Windows builds - part of #1387 (@jamescowens).
 - Re-activate Windows Installer #1409 (@TheCharlatan).
 - Fix Depends and Travis build issues for ARM #1417 (@jamescowens).
 - Fix syncupdate icons #1421 (@jamescowens).
 - Fix potential BOINC crash when reading projects #1426 (@cyrossignol).
 - Fix freeze when unlocking wallet #1428 (@denravonska).
 - Fix RPC after high priority alert #1432 (@denravonska).
 - Fix missing poll in GUI when most recent poll expired #1455 (@cyrossignol).

Removed:
 - Remove old, rudimentary side staking implementation #1381 (@denravonska).
 - Remove auto unlock #1402 (@denravonska).
 - Remove superblock forwarding #1430 (@denravonska).
@cyrossignol cyrossignol deleted the optimize-getfilecontents branch August 11, 2019 08:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants