Skip to content

Commit 91c3f17

Browse files
committed
refactor memory streams, avoid asset buffer copy
1 parent 5c85d08 commit 91c3f17

12 files changed

Lines changed: 50 additions & 41 deletions

File tree

libsave/include/SatisfactorySave/IO/Archive/OStreamArchive.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,8 @@ namespace SatisfactorySave {
6767

6868
class SATISFACTORYSAVE_API OMemStreamArchive : public OStreamArchive {
6969
public:
70-
explicit OMemStreamArchive(std::unique_ptr<MemOStream> ostream) {
71-
ostream_ = std::move(ostream);
70+
explicit OMemStreamArchive() {
71+
ostream_ = std::make_unique<MemOStream>();
7272
}
7373

7474
[[nodiscard]] const std::vector<char>& data() const {

libsave/include/SatisfactorySave/IO/MemoryStreams.h

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,18 @@
33
#include <istream>
44
#include <memory>
55
#include <ostream>
6+
#include <span>
67
#include <vector>
78

89
#include "satisfactorysave_export.h"
910

1011
namespace SatisfactorySave {
1112

1213
class SATISFACTORYSAVE_API MemIStreambuf : public std::streambuf {
13-
private:
14-
std::unique_ptr<std::vector<char>> buf_;
15-
1614
public:
17-
explicit MemIStreambuf(std::unique_ptr<std::vector<char>> buf) : buf_(std::move(buf)) {
18-
setg(buf_->data(), buf_->data(), buf_->data() + buf_->size());
15+
explicit MemIStreambuf(std::span<const char> buf) {
16+
setg(const_cast<char*>(buf.data()), const_cast<char*>(buf.data()),
17+
const_cast<char*>(buf.data() + buf.size()));
1918
}
2019

2120
protected:
@@ -39,22 +38,35 @@ namespace SatisfactorySave {
3938

4039
class SATISFACTORYSAVE_API MemIStream : public std::istream {
4140
private:
41+
std::unique_ptr<std::vector<char>> data_buf_;
4242
MemIStreambuf memstreambuf_;
4343

4444
public:
45-
explicit MemIStream(std::unique_ptr<std::vector<char>> buf)
45+
explicit MemIStream(std::vector<char>&& buf)
4646
: std::istream(nullptr),
47-
memstreambuf_(std::move(buf)) {
47+
data_buf_(std::make_unique<std::vector<char>>(std::move(buf))),
48+
memstreambuf_(*data_buf_) {
4849
init(&memstreambuf_);
4950
}
51+
52+
explicit MemIStream(std::span<const char> buf) : std::istream(nullptr), memstreambuf_(buf) {
53+
init(&memstreambuf_);
54+
}
55+
56+
~MemIStream() override = default;
57+
MemIStream(const MemIStream&) = delete;
58+
MemIStream& operator=(const MemIStream&) = delete;
59+
MemIStream(MemIStream&&) = delete;
60+
MemIStream& operator=(MemIStream&&) = delete;
5061
};
5162

5263
class SATISFACTORYSAVE_API MemOStreambuf : public std::streambuf {
5364
private:
5465
std::unique_ptr<std::vector<char>> buf_;
5566

5667
public:
57-
explicit MemOStreambuf(std::unique_ptr<std::vector<char>> buf) : buf_(std::move(buf)) {
68+
explicit MemOStreambuf() {
69+
buf_ = std::make_unique<std::vector<char>>();
5870
setp(buf_->data(), buf_->data() + buf_->size());
5971
}
6072

@@ -102,7 +114,7 @@ namespace SatisfactorySave {
102114
MemOStreambuf memstreambuf_;
103115

104116
public:
105-
MemOStream() : std::ostream(nullptr), memstreambuf_(std::make_unique<std::vector<char>>()) {
117+
MemOStream() : std::ostream(nullptr) {
106118
init(&memstreambuf_);
107119
}
108120

libsave/include/SatisfactorySave/Pak/AssetFile.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ namespace SatisfactorySave {
1515

1616
class SATISFACTORYSAVE_API AssetFile : public IStreamArchive {
1717
public:
18-
explicit AssetFile(const std::vector<char>& uassetData, const std::vector<char>& ubulkData = {});
18+
explicit AssetFile(std::vector<char>&& uassetData, std::vector<char>&& ubulkData = {});
1919

2020
inline void seekCookedSerialOffset(uint64_t offset) {
2121
seek(packageHeader_.PackageSummary.HeaderSize + offset);
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
#pragma once
22

3+
#include <span>
34
#include <vector>
45

56
namespace SatisfactorySave {
67
template<typename T>
78
inline std::size_t vector_bin_size(const std::vector<T>& vec) {
89
return vec.size() * sizeof(T);
910
}
11+
12+
template<typename T>
13+
std::span<const char> vector_to_char_span(const std::vector<T>& vec) {
14+
return std::span<const char>(reinterpret_cast<const char*>(vec.data()), vec.size() * sizeof(T));
15+
}
1016
} // namespace SatisfactorySave

libsave/src/GameTypes/Save/Blueprint.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ SatisfactorySave::Blueprint::Blueprint(const std::filesystem::path& filepath) {
1414

1515
auto file_data_blob = decompressChunks(fileAr);
1616

17-
const auto file_data_blob_size = file_data_blob->size();
17+
const auto file_data_blob_size = file_data_blob.size();
1818
IStreamArchive ar(std::make_unique<MemIStream>(std::move(file_data_blob)));
1919

2020
auto save_version_stack_pusher = ar.pushSaveVersion(header.SaveVersion);
@@ -35,7 +35,7 @@ SatisfactorySave::Blueprint::Blueprint(const std::filesystem::path& filepath) {
3535

3636
void SatisfactorySave::Blueprint::save(const std::filesystem::path& filepath) {
3737
// Serialize data to blob
38-
OMemStreamArchive ar(std::make_unique<MemOStream>());
38+
OMemStreamArchive ar;
3939

4040
auto save_version_stack_pusher = ar.pushSaveVersion(header.SaveVersion);
4141

libsave/src/GameTypes/Save/ChunkHelper.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
#include "IO/ZlibUtils.h"
44

5-
std::unique_ptr<std::vector<char>> SatisfactorySave::decompressChunks(IFStreamArchive& fileAr) {
5+
std::vector<char> SatisfactorySave::decompressChunks(IFStreamArchive& fileAr) {
66
std::vector<ChunkInfo> chunk_list;
77
std::size_t total_decompressed_size = 0;
88
while (fileAr.tell() < fileAr.size()) {
@@ -14,15 +14,15 @@ std::unique_ptr<std::vector<char>> SatisfactorySave::decompressChunks(IFStreamAr
1414
}
1515

1616
// Create a buffer with the total decompressed size.
17-
auto file_data_blob = std::make_unique<std::vector<char>>(total_decompressed_size);
17+
std::vector<char> file_data_blob(total_decompressed_size);
1818

1919
// Decompress in parallel.
2020
// OpenMP requires a signed integer type for loop.
2121
const int64_t size = static_cast<int64_t>(chunk_list.size());
2222
#pragma omp parallel for
2323
for (int64_t i = 0; i < size; i++) {
2424
const ChunkInfo& chunk = chunk_list[i];
25-
char* decompressed_buffer_ptr = file_data_blob->data() + chunk.decompressed_offset;
25+
char* decompressed_buffer_ptr = file_data_blob.data() + chunk.decompressed_offset;
2626
zlibUncompress(decompressed_buffer_ptr, chunk.header.uncompressedSize(), chunk.compressed_chunk.data(),
2727
chunk.compressed_chunk.size());
2828
}

libsave/src/GameTypes/Save/ChunkHelper.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,5 @@ namespace SatisfactorySave {
1818
std::size_t decompressed_offset;
1919
};
2020

21-
std::unique_ptr<std::vector<char>> decompressChunks(IFStreamArchive& fileAr);
21+
std::vector<char> decompressChunks(IFStreamArchive& fileAr);
2222
} // namespace SatisfactorySave

libsave/src/GameTypes/Save/SaveGame.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ SatisfactorySave::SaveGame::SaveGame(const std::filesystem::path& filepath) {
4343

4444
// Store size and init memory stream
4545
TIME_MEASURE_START("toStream");
46-
const auto file_data_blob_size = file_data_blob->size();
46+
const auto file_data_blob_size = file_data_blob.size();
4747
IStreamArchive ar(std::make_unique<MemIStream>(std::move(file_data_blob)));
4848

4949
// Store header SaveVersion as first stack entry.
@@ -85,7 +85,7 @@ SatisfactorySave::SaveGame::SaveGame(const std::filesystem::path& filepath) {
8585

8686
void SatisfactorySave::SaveGame::save(const std::filesystem::path& filepath) {
8787
// Serialize data to blob
88-
OMemStreamArchive ar(std::make_unique<MemOStream>());
88+
OMemStreamArchive ar;
8989

9090
auto save_version_stack_pusher = ar.pushSaveVersion(mSaveHeader.SaveVersion);
9191

libsave/src/Pak/AbstractPakFile.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,8 @@ SatisfactorySave::AssetFile SatisfactorySave::AbstractPakFile::readAsset(const s
1111
}
1212
const std::string filenameUbulk = filenameBase + "ubulk";
1313

14-
const auto uassetFile = readAssetFileContent(filename);
15-
const auto ubulkFile =
16-
containsAssetFilename(filenameUbulk) ? readAssetFileContent(filenameUbulk) : std::vector<char>();
14+
auto uassetFile = readAssetFileContent(filename);
15+
auto ubulkFile = containsAssetFilename(filenameUbulk) ? readAssetFileContent(filenameUbulk) : std::vector<char>();
1716

18-
return AssetFile(uassetFile, ubulkFile);
17+
return AssetFile(std::move(uassetFile), std::move(ubulkFile));
1918
}

libsave/src/Pak/AssetFile.cpp

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,10 @@
88
#include "IO/Archive/IStreamArchive.h"
99
#include "IO/MemoryStreams.h"
1010

11-
SatisfactorySave::AssetFile::AssetFile(const std::vector<char>& uassetData, const std::vector<char>& ubulkData) {
12-
// Make continuous buffer, offset values in file assume this format.
13-
std::unique_ptr<std::vector<char>> buf = std::make_unique<std::vector<char>>(uassetData);
14-
istream_ = std::make_unique<MemIStream>(std::move(buf));
11+
SatisfactorySave::AssetFile::AssetFile(std::vector<char>&& uassetData, std::vector<char>&& ubulkData) {
12+
istream_ = std::make_unique<MemIStream>(std::move(uassetData));
1513
if (!ubulkData.empty()) {
16-
std::unique_ptr<std::vector<char>> ubulk_buf = std::make_unique<std::vector<char>>(ubulkData);
17-
ubulk_ar_ = std::make_unique<IStreamArchive>(std::move(std::make_unique<MemIStream>(std::move(ubulk_buf))));
14+
ubulk_ar_ = std::make_unique<IStreamArchive>(std::make_unique<MemIStream>(std::move(ubulkData)));
1815
}
1916

2017
// Check old asset format

0 commit comments

Comments
 (0)