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

Compress GAME_START message #3870

Closed
wants to merge 3 commits into from

Conversation

o01eg
Copy link
Contributor

@o01eg o01eg commented Jun 2, 2022

Alternative approach to #3854

It also breaks some compatibility but enforces only limited messages to be compressed.

@o01eg o01eg added category:feature The Issue/PR describes or implements a new game feature. component:network labels Jun 2, 2022
@o01eg o01eg added this to the v0.5 milestone Jun 2, 2022
@o01eg o01eg requested a review from geoffthemedio June 2, 2022 08:04
@o01eg o01eg self-assigned this Jun 2, 2022
@o01eg o01eg mentioned this pull request Jun 2, 2022
@o01eg o01eg force-pushed the compress-game-start-message branch from 3982e29 to 25d71f4 Compare June 3, 2022 08:00
@@ -920,7 +921,7 @@ void ServerApp::SendNewGameStartMessages() {
m_universe, GetSpeciesManager(),
GetCombatLogManager(), GetSupplyManager(),
player_info_map, m_galaxy_setup_data,
use_binary_serialization));
use_binary_serialization, boost::iostreams::zlib::default_compression));
Copy link
Member

Choose a reason for hiding this comment

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

are there plans to do something other than default_compression ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I suppose it possible to introduce some option.

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm working on porting over the user option and client-server compression usage requests from #3854. Since those work as bool flags, my message creation functions look like:

Message MakeMessage(const std::string& data, bool use_compression) {
    std::ostringstream os;
    {
        boost::iostreams::zlib_params params;
        params.level = boost::iostreams::zlib::no_compression;
        if (use_compression)
            params.level = boost::iostreams::zlib::default_compression;

        boost::iostreams::filtering_ostream zos;
        zos.push(boost::iostreams::zlib_compressor(params));
        zos.push(os);

        freeorion_xml_oarchive oa(zos);
        oa << BOOST_SERIALIZATION_NVP(data);
    }
    return Message{Message::MessageType::SOME_MSG, std::move(os).str()};
}

Would it be preferable for the user option to be the compression level, rather than just a true/false toggle?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hard to say, in most cases big messages are sent from server to client.

@o01eg o01eg marked this pull request as draft June 3, 2022 17:01
mlam19 added a commit to mlam19/freeorion that referenced this pull request Jun 3, 2022
Add compression option to message creation functions. Based on freeorion#3870.
@mlam19
Copy link
Contributor

mlam19 commented Jun 4, 2022

Here's the code for the user options and client-server compression usage requests. I have no idea how to perform Git operations between GitHub forks, so patch files it is.

master...mlam19:msg_data_cpr_v

0001-Stream-based-compression-decompression.patch.txt
0002-Add-compression-usage-option.patch.txt
0003-Add-client-server-compression-usage-requests.patch.txt

@o01eg
Copy link
Contributor Author

o01eg commented Jun 4, 2022

I think we don't need compression for every message because many of them are quite small.

@mlam19
Copy link
Contributor

mlam19 commented Jun 4, 2022

That's fair. I think the messages that tend to get very large are:

  • DISPATCH_COMBAT_LOGS
  • GAME_START
  • TURN_PARTIAL_UPDATE
  • TURN_UPDATE

@o01eg
Copy link
Contributor Author

o01eg commented Jun 4, 2022

CHAT_HISTORY tend to be large too.

@mlam19
Copy link
Contributor

mlam19 commented Jun 6, 2022

0001-Message-compression.patch.txt

  • Compression is limited to only larger message types.
  • Compression is only used for non-localhost clients
  • There's no user selectability
  • The filtering_ostream::reset() were removed; those seem to break things
  • Removed the string comparison for detecting the use of binary serialization; not sure if that would work anymore

EDIT: Updated patch with changes to more message creation calls. filtering_ostream::reset() readded but seems to cause server crash in Message::ChatHistoryMessage().

@o01eg
Copy link
Contributor Author

o01eg commented Jun 7, 2022

The filtering_ostream::reset() were removed; those seem to break things

@mlam19 Did you catch issue with it?

@mlam19
Copy link
Contributor

mlam19 commented Jun 8, 2022

Since the last patch, I've found and set some more use_compression flags in various message creation calls. So now the server crash occurs when filtering_ostream::reset() is used is in Message::ChatHistoryMessage() when a remote client joins a game. I added some debug messages and exception handling.

Message ChatHistoryMessage(const std::vector<std::reference_wrapper<const ChatHistoryEntity>>& chat_history,
                           bool use_compression) {
    std::ostringstream os;
    {
        try {
            boost::iostreams::zlib_params params;
            params.level = boost::iostreams::zlib::no_compression;
            if (use_compression)
                params.level = boost::iostreams::zlib::default_compression;
            boost::iostreams::filtering_ostream zos;
            zos.push(boost::iostreams::zlib_compressor(params));
            zos.push(os);
            freeorion_xml_oarchive oa(zos);
            std::size_t size = chat_history.size();
            oa << BOOST_SERIALIZATION_NVP(size);
            for (const auto &elem : chat_history) {
                oa << boost::serialization::make_nvp(BOOST_PP_STRINGIZE(elem), elem.get());
            }
            if (!zos.strict_sync()) {
                DebugLogger() << "D1";
                zos.reset();
            }
            DebugLogger() << "D2"; // Last debug message displayed
        } catch (const std::exception &err) {
            DebugLogger() << "D3";
            ErrorLogger() << "ChatHistoryMessage:\n" << "Error: " << err.what();
            throw err;
        }
        DebugLogger() << "D4";
    }
    return Message{Message::MessageType::CHAT_HISTORY, std::move(os).str()};
}

The last messages in the server log are the "D1" and "D2" debug messages. Nothing appears in the terminal.

@geoffthemedio
Copy link
Member

the server crash occurs when filtering_ostream::reset() is used
[...]
The last messages in the server log are the "D1" and "D2" debug messages. Nothing appears in the terminal.

By "when" do you mean "if"? Because if the log message for "D2" appears in the log, then the .reset() apparently already ran.

@mlam19
Copy link
Contributor

mlam19 commented Jun 8, 2022

Yes, the "D1" and "D2" indicates that the .reset() has run.

If the .reset() is commented out, then the "D1", "D2" and "D4" messages are logged. After that, the game can be started, but then the remote client cannot progress beyond turn 1 (turn button does nothing.) On the other hand, the server doesn't crash.

@mlam19
Copy link
Contributor

mlam19 commented Jun 12, 2022

Found my problem. xml_oarchive only finishes writing when it is destroyed. In Message::ChatHistoryMessage(), the filtering_ostream was being rendered unusable by reset() before the xml_oarchive was destroyed at the end of the nested block; this caused a segmentation fault during the destruction of the xml_oarchive.

The xml_oarchive is now encapsulated in its own nested block to ensure it is destroyed before the reset().

Here's the updated patch:

0001-Message-compression.patch.txt

mlam19 added a commit to mlam19/freeorion that referenced this pull request Jun 15, 2022
Add compression for large messages. Disable compression for localhost clients. Based on freeorion#3870.
@mlam19 mlam19 mentioned this pull request Jun 15, 2022
@mlam19
Copy link
Contributor

mlam19 commented Jun 15, 2022

I've made a new pull request (#3904) with the patch.

geoffthemedio pushed a commit that referenced this pull request Jul 2, 2022
Add compression for large messages. Disable compression for localhost clients. Based on #3870.
@geoffthemedio geoffthemedio added the status:superseded The PR implementation is insufficient and a follow up implementation PR exists. label Jul 2, 2022
@o01eg o01eg deleted the compress-game-start-message branch July 2, 2022 11:09
@Vezzra Vezzra modified the milestones: v0.5, Gateway to the Void Jul 3, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
category:feature The Issue/PR describes or implements a new game feature. component:network status:superseded The PR implementation is insufficient and a follow up implementation PR exists.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants