~aleteoryx/muditaos

cdf5dbf557b29f31c9755feac594d2d2f4013351 — Lefucjusz 1 year, 9 months ago e46cb3e
[BH-1887] Speed up update process

* Added stream buffering for reading data
from tar archive with update.
* Increased size of the buffer used
for unpacking files from tar archive.
* Changed buffers data type from vectors
to raw heap-allocated arrays.
M harmony_changelog.md => harmony_changelog.md +1 -0
@@ 16,6 16,7 @@
### Changed / Improved
* Updated FSL drivers from NXP
* Increased battery charger stack size
* Increased speed of update process

## [2.5.0 2024-02-09]


M module-services/service-desktop/endpoints/update/UpdateHelper.cpp => module-services/service-desktop/endpoints/update/UpdateHelper.cpp +6 -9
@@ 1,4 1,4 @@
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include <service-desktop/Constants.hpp>


@@ 20,11 20,6 @@

namespace sdesktop::endpoints
{
    namespace
    {
        constexpr auto chunkSize = 1024 * 128;
    }

    struct UpdatePackageEntries
    {
        explicit UpdatePackageEntries(const json11::Json &json)


@@ 80,11 75,13 @@ namespace sdesktop::endpoints
            return false;
        }

        constexpr auto chunkSize = 128 * 1024;
        auto rawDataBuffer       = std::make_unique<char[]>(chunkSize);

        MD5 md5;
        std::vector<std::byte> raw_data(chunkSize);
        std::size_t bytesRead;
        while ((bytesRead = std::fread(raw_data.data(), 1, chunkSize, fd)) > 0) {
            md5.add(raw_data.data(), bytesRead);
        while ((bytesRead = std::fread(rawDataBuffer.get(), sizeof(*rawDataBuffer.get()), chunkSize, fd)) > 0) {
            md5.add(rawDataBuffer.get(), bytesRead);
        }

        std::fclose(fd);

M module-utils/tar/include/tar/tar.hpp => module-utils/tar/include/tar/tar.hpp +5 -2
@@ 1,4 1,4 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once


@@ 21,13 21,16 @@ namespace tar
        bool is_file() const;
        bool is_directory() const;

        void read(const std::byte *data, std::size_t size) const;
        void read(std::uint8_t *data, std::size_t size) const;

      private:
        explicit entry(const std::filesystem::path &path);
        friend class iterator;
        mutable mtar_t handle{};
        mtar_header_t tar_header;

        static constexpr auto streamBufferSize = 64 * 1024;
        std::unique_ptr<char[]> streamBuffer;
    };

    class iterator

M module-utils/tar/tar.cpp => module-utils/tar/tar.cpp +22 -19
@@ 1,9 1,8 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "tar/tar.hpp"

#include <fstream>
#include <vector>
#include <iterator>



@@ 14,23 13,25 @@ namespace
        return entry.name() != "." and entry.name() != ".." and entry.name() != "...";
    }

    void write_to_file(const tar::entry &entry, const std::filesystem::path &path)
    void writeToFile(const tar::entry &entry, const std::filesystem::path &path)
    {
        constexpr std::size_t chunk_size = 1024 * 128;
        std::ofstream out_file{path, std::ios::binary};
        if (not out_file.is_open()) {
        auto fd = std::fopen(path.c_str(), "wb");
        if (fd == nullptr) {
            throw std::filesystem::filesystem_error("During opening " + path.string(), std::error_code{});
        }

        std::vector<std::byte> raw_data(chunk_size);
        auto bytes_left = entry.size();
        while (bytes_left > 0) {
            const std::size_t to_read = bytes_left > chunk_size ? chunk_size : bytes_left;
            entry.read(raw_data.data(), to_read);
        constexpr std::size_t chunkSize = 256 * 1024;
        auto rawDataBuffer              = std::make_unique<std::uint8_t[]>(chunkSize);

            out_file.write(reinterpret_cast<const char *>(raw_data.data()), to_read);
            bytes_left -= to_read;
        auto bytesLeft = static_cast<std::size_t>(entry.size());
        while (bytesLeft > 0) {
            const auto bytesToRead = std::min(bytesLeft, chunkSize);
            entry.read(rawDataBuffer.get(), bytesToRead);
            std::fwrite(rawDataBuffer.get(), sizeof(*rawDataBuffer.get()), bytesToRead, fd);
            bytesLeft -= bytesToRead;
        }

        std::fclose(fd);
    }
} // namespace



@@ 41,6 42,9 @@ namespace tar
        if (mtar_open(&handle, path.c_str(), "rb") != MTAR_ESUCCESS) {
            throw std::filesystem::filesystem_error("During opening tar file " + path.string(), std::error_code{});
        }
        streamBuffer = std::make_unique<char[]>(streamBufferSize);
        setvbuf(handle.stream, streamBuffer.get(), _IOFBF, streamBufferSize);

        if (mtar_read_header(&handle, &tar_header) != MTAR_ESUCCESS) {
            throw std::filesystem::filesystem_error("During reading from tar file " + path.string(), std::error_code{});
        }


@@ 65,10 69,10 @@ namespace tar
    {
        return tar_header.name;
    }
    void entry::read(const std::byte *data, const std::size_t size) const
    void entry::read(std::uint8_t *data, const std::size_t size) const
    {
        const std::size_t to_read = size > tar_header.size ? tar_header.size : size;
        if (mtar_read_data(&handle, (void *)(data), to_read) != MTAR_ESUCCESS) {
        const auto bytesToRead = std::min(size, static_cast<std::size_t>(tar_header.size));
        if (mtar_read_data(&handle, reinterpret_cast<void *>(data), bytesToRead) != MTAR_ESUCCESS) {
            throw std::filesystem::filesystem_error("During reading from tar file", std::error_code{});
        }
    }


@@ 89,7 93,6 @@ namespace tar
            mtar_read_header(&entry_->handle, &entry_->tar_header) != MTAR_ESUCCESS) {
            entry_ = {};
        }

        return *this;
    }
    iterator iterator::operator++(int)


@@ 115,8 118,8 @@ namespace tar
                std::filesystem::create_directories(full_path);
            }
            else if (entry.is_file()) {
                write_to_file(entry, full_path);
                writeToFile(entry, full_path);
            }
        }
    }
} // namespace tar
\ No newline at end of file
} // namespace tar

M module-vfs/drivers/src/purefs/fs/filesystem_ext4.cpp => module-vfs/drivers/src/purefs/fs/filesystem_ext4.cpp +2 -2
@@ 1,4 1,4 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include <memory>


@@ 394,7 394,7 @@ namespace purefs::fs::drivers
            mnt,
            [](const char *path) {
                if (ext4_inode_exist(path, EXT4_DE_DIR) == 0) {
                    LOG_WARN("rmdir syscall instead of unlink is recommended for remove directory");
                    LOG_WARN("rmdir syscall instead of unlink is recommended to remove directory");
                    return -ext4_dir_rm(path);
                }
                else {

M pure_changelog.md => pure_changelog.md +1 -0
@@ 12,6 12,7 @@
### Changed / Improved
* Updated share capital in EULA.
* Updated copy on final onboarding screen.
* Increased speed of update process.

## [1.11.0 2023-12-15]