Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5cb1b029 authored by Kelvin Zhang's avatar Kelvin Zhang
Browse files

Add lz4 support for VABC

Add lz4 support in CowWriter/CowReader. Lz4 should offer faster
read/write performance but slightly larger COW sizes.

Download time: Reduced from 1264s to 825s (~35% faster)
Filesystem verification time: from 69s to 59s (~15% faster)
COW Size: 2.59GB to 3.21GB, (~25% regression)
Merge time: 37046ms to 27690ms (~25% faster)
Boot time: LZ4 is 2.7% faster

Overall, LZ4 offers faster read/write performance at the cost of 25%
space regression.

Test: th
Bug: 228478555
Change-Id: Ie521852fb3c9ff8a12e55b764c1eb1838f7b2181
parent 4a2beb8d
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -190,6 +190,7 @@ cc_binary {
        "libhealthhalutils",
        "libhealthshim",
        "libsnapshot_cow",
        "liblz4",
        "libsnapshot_nobinder",
        "update_metadata-protos",
    ],
@@ -254,6 +255,7 @@ cc_defaults {
        "libsparse",
        "libutils",
        "liblog",
        "liblz4",
        "libz",
        "libdiagnose_usb",
        "libbase",
+26 −16
Original line number Diff line number Diff line
@@ -44,7 +44,6 @@ cc_defaults {
        "libext2_uuid",
        "libext4_utils",
        "libfstab",
        "libsnapshot_cow",
        "libsnapshot_snapuserd",
        "libz",
    ],
@@ -154,13 +153,16 @@ cc_defaults {
        "-Wall",
        "-Werror",
    ],
    export_include_dirs: ["include"],
    srcs: [
        "cow_decompress.cpp",
        "cow_reader.cpp",
        "cow_writer.cpp",
        "cow_format.cpp",
    shared_libs: [
        "libbase",
        "liblog",
    ],
    static_libs: [
        "libbrotli",
        "libz",
        "liblz4",
    ],
    export_include_dirs: ["include"],
}

cc_library_static {
@@ -168,16 +170,14 @@ cc_library_static {
    defaults: [
        "libsnapshot_cow_defaults",
    ],
    srcs: [
        "cow_decompress.cpp",
        "cow_reader.cpp",
        "cow_writer.cpp",
        "cow_format.cpp",
    ],
    host_supported: true,
    recovery_available: true,
    shared_libs: [
        "libbase",
        "liblog",
    ],
    static_libs: [
        "libbrotli",
        "libz",
    ],
    ramdisk_available: true,
    vendor_ramdisk_available: true,
}
@@ -214,7 +214,7 @@ cc_library_static {

cc_defaults {
    name: "libsnapshot_test_defaults",
    defaults: ["libsnapshot_defaults"],
    defaults: ["libsnapshot_defaults", "libsnapshot_cow_defaults"],
    srcs: [
        "partition_cow_creator_test.cpp",
        "snapshot_metadata_updater_test.cpp",
@@ -295,6 +295,7 @@ cc_test {

cc_binary {
    name: "snapshotctl",
    defaults: ["libsnapshot_cow_defaults", "libsnapshot_hal_deps"],
    srcs: [
        "snapshotctl.cpp",
    ],
@@ -343,6 +344,9 @@ cc_test {

cc_defaults {
    name: "libsnapshot_fuzzer_defaults",
    defaults: [
        "libsnapshot_cow_defaults",
    ],
    native_coverage : true,
    srcs: [
        // Compile the protobuf definition again with type full.
@@ -416,6 +420,7 @@ cc_test {
    name: "cow_api_test",
    defaults: [
        "fs_mgr_defaults",
        "libsnapshot_cow_defaults",
    ],
    srcs: [
        "cow_api_test.cpp",
@@ -471,6 +476,7 @@ cc_binary {
        "libsparse",
        "libxz",
        "libz",
        "liblz4",
        "libziparchive",
        "update_metadata-protos",
    ],
@@ -486,6 +492,9 @@ cc_binary {

cc_binary {
    name: "estimate_cow_from_nonab_ota",
    defaults: [
        "libsnapshot_cow_defaults",
    ],
    host_supported: true,
    device_supported: false,
    cflags: [
@@ -519,6 +528,7 @@ cc_binary {
    name: "inspect_cow",
    host_supported: true,
    device_supported: true,
    defaults: ["libsnapshot_cow_defaults"],
    cflags: [
        "-D_FILE_OFFSET_BITS=64",
        "-Wall",
+39 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@

#include <android-base/logging.h>
#include <brotli/decode.h>
#include <lz4.h>
#include <zlib.h>

namespace android {
@@ -260,5 +261,43 @@ std::unique_ptr<IDecompressor> IDecompressor::Brotli() {
    return std::unique_ptr<IDecompressor>(new BrotliDecompressor());
}

class Lz4Decompressor final : public IDecompressor {
  public:
    ~Lz4Decompressor() override = default;

    bool Decompress(const size_t output_size) override {
        size_t actual_buffer_size = 0;
        auto&& output_buffer = sink_->GetBuffer(output_size, &actual_buffer_size);
        if (actual_buffer_size != output_size) {
            LOG(ERROR) << "Failed to allocate buffer of size " << output_size << " only got "
                       << actual_buffer_size << " bytes";
            return false;
        }
        std::string input_buffer;
        input_buffer.resize(stream_->Size());
        size_t bytes_read = 0;
        stream_->Read(input_buffer.data(), input_buffer.size(), &bytes_read);
        if (bytes_read != input_buffer.size()) {
            LOG(ERROR) << "Failed to read all input at once. Expected: " << input_buffer.size()
                       << " actual: " << bytes_read;
            return false;
        }
        const int bytes_decompressed =
                LZ4_decompress_safe(input_buffer.data(), static_cast<char*>(output_buffer),
                                    input_buffer.size(), output_size);
        if (bytes_decompressed != output_size) {
            LOG(ERROR) << "Failed to decompress LZ4 block, expected output size: " << output_size
                       << ", actual: " << bytes_decompressed;
            return false;
        }
        sink_->ReturnData(output_buffer, output_size);
        return true;
    }
};

std::unique_ptr<IDecompressor> IDecompressor::Lz4() {
    return std::make_unique<Lz4Decompressor>();
}

}  // namespace snapshot
}  // namespace android
+1 −0
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ class IDecompressor {
    static std::unique_ptr<IDecompressor> Uncompressed();
    static std::unique_ptr<IDecompressor> Gz();
    static std::unique_ptr<IDecompressor> Brotli();
    static std::unique_ptr<IDecompressor> Lz4();

    // |output_bytes| is the expected total number of bytes to sink.
    virtual bool Decompress(size_t output_bytes) = 0;
+3 −0
Original line number Diff line number Diff line
@@ -775,6 +775,9 @@ bool CowReader::ReadData(const CowOperation& op, IByteSink* sink) {
        case kCowCompressBrotli:
            decompressor = IDecompressor::Brotli();
            break;
        case kCowCompressLz4:
            decompressor = IDecompressor::Lz4();
            break;
        default:
            LOG(ERROR) << "Unknown compression type: " << op.compression;
            return false;
Loading