blob: 1bff09ececfa68403385ddc86eed6002d97bb11d [file] [log] [blame]
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/developer/forensics/feedback_data/attachments/inspect_data_budget.h"
#include <lib/syslog/cpp/macros.h>
#include <algorithm>
#include <filesystem>
#include "src/developer/forensics/feedback_data/constants.h"
namespace forensics::feedback_data {
namespace {
// We target a 2MB final ZIP file. We give a budget between 4MB and 20MB for Inspect data, starting
// at 20MB.
const size_t kTargetZipSizeInBytes = 2 * 1024 * 1024;
const size_t kMinInspectDataBudgetInBytes = 4 * 1024 * 1024;
const size_t kMaxInspectDataBudgetInBytes = 20 * 1024 * 1024;
const size_t kStartingInspectDataBudgetInBytes = kMaxInspectDataBudgetInBytes;
} // namespace
InspectDataBudget::InspectDataBudget(const char* limit_data_flag_path) {
limit_data_flag_ = std::filesystem::exists(limit_data_flag_path);
data_budget_ = limit_data_flag_ ? std::make_optional<size_t>(kStartingInspectDataBudgetInBytes)
: std::nullopt;
}
void InspectDataBudget::UpdateBudget(
const std::map<std::string, ArchiveFileStats>& file_size_stats) {
std::string inspect_filename(kAttachmentInspect);
// No-op if data limiting is disabled or the Inspect file doesn't exist in the latest archive.
if (!limit_data_flag_ || file_size_stats.count(inspect_filename) == 0) {
return;
}
size_t previous_zip_size = 0;
for (const auto& [name, size] : file_size_stats) {
previous_zip_size += size.compressed_bytes;
}
// Online algorithm; there is no guarantee the same input will give us the same output. For
// simplicity we use only the last budget and its size output to calculate the new budget.
//
// Note: converges faster when the compressed portion of the inspect file is larger.
// Note: converges when the relationship between budget and snapshot is close to linearity.
const double ratio = (double) kTargetZipSizeInBytes / (double) previous_zip_size;
const size_t new_budget = (size_t) ((double)data_budget_.value() * ratio);
data_budget_ = std::clamp(new_budget, kMinInspectDataBudgetInBytes, kMaxInspectDataBudgetInBytes);
}
} // namespace forensics::feedback_data