pw_blob_store: Add size report
Add size reports for both standard buffered blob and deferred writer
blob store
Change-Id: If8688195f8865c5accc1ec86a9ec57c7b1faecbb
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/31840
Reviewed-by: Alexei Frolov <frolv@google.com>
Commit-Queue: David Rogers <davidrogers@google.com>
diff --git a/pw_blob_store/BUILD.gn b/pw_blob_store/BUILD.gn
index e6c9311..236c8d1 100644
--- a/pw_blob_store/BUILD.gn
+++ b/pw_blob_store/BUILD.gn
@@ -14,6 +14,7 @@
import("//build_overrides/pigweed.gni")
+import("$dir_pw_bloat/bloat.gni")
import("$dir_pw_build/target_types.gni")
import("$dir_pw_docgen/docs.gni")
import("$dir_pw_unit_test/test.gni")
@@ -84,4 +85,29 @@
pw_doc_group("docs") {
sources = [ "docs.rst" ]
+ report_deps = [ ":blob_size" ]
+}
+
+pw_size_report("blob_size") {
+ title = "Pigweed BlobStore size report"
+
+ # To see all the symbols, uncomment the following:
+ # Note: The size report RST table won't be generated when full_report = true.
+ # full_report = true
+
+ binaries = [
+ {
+ target = "size_report:basic_blob"
+ base = "size_report:base"
+ label = "BlobStore"
+ },
+ ]
+
+ binaries += [
+ {
+ target = "size_report:deferred_write_blob"
+ base = "size_report:base"
+ label = "BlobStore with deferred write"
+ },
+ ]
}
diff --git a/pw_blob_store/docs.rst b/pw_blob_store/docs.rst
index a84a22e..906d942 100644
--- a/pw_blob_store/docs.rst
+++ b/pw_blob_store/docs.rst
@@ -10,7 +10,7 @@
Write and read are only done using the BlobWriter and BlobReader classes.
-Once a blob write is closed, reopening followed by a Discard(), Write(), or
+Once a blob write is closed, reopening for write followed by a Discard(), Write(), or
Erase() will discard the previous blob.
Write blob:
@@ -26,5 +26,12 @@
BlobReader::GetMemoryMappedBlob().
3) BlobReader::Close().
+Size report
+-----------
+The following size report showcases the memory usage of the blob store.
+
+.. include:: blob_size
+
+
.. note::
The documentation for this module is currently incomplete.
diff --git a/pw_blob_store/size_report/BUILD b/pw_blob_store/size_report/BUILD
new file mode 100644
index 0000000..4811b4f
--- /dev/null
+++ b/pw_blob_store/size_report/BUILD
@@ -0,0 +1,63 @@
+# Copyright 2021 The Pigweed Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may not
+# use this file except in compliance with the License. You may obtain a copy of
+# the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations under
+# the License.
+
+load(
+ "//pw_build:pigweed.bzl",
+ "pw_cc_binary",
+)
+
+package(default_visibility = ["//visibility:public"])
+
+licenses(["notice"]) # Apache License 2.0
+
+pw_cc_binary(
+ name = "base",
+ srcs = ["base.cc"],
+ deps = [
+ "//pw_assert",
+ "//pw_bloat:bloat_this_binary",
+ "//pw_kvs",
+ "//pw_kvs:flash_test_partition",
+ "//pw_kvs:fake_flash_12_byte_partition",
+ "//pw_log",
+ ],
+)
+
+pw_cc_binary(
+ name = "basic_blob",
+ srcs = ["basic_blob.cc"],
+ deps = [
+ "//pw_assert",
+ "//pw_bloat:bloat_this_binary",
+ "//pw_blob_store",
+ "//pw_kvs",
+ "//pw_kvs:flash_test_partition",
+ "//pw_kvs:fake_flash_12_byte_partition",
+ "//pw_log",
+ ],
+)
+
+pw_cc_binary(
+ name = "deferred_write_blob",
+ srcs = ["deferred_write_blob.cc"],
+ deps = [
+ "//pw_assert",
+ "//pw_bloat:bloat_this_binary",
+ "//pw_blob_store",
+ "//pw_kvs",
+ "//pw_kvs:flash_test_partition",
+ "//pw_kvs:fake_flash_12_byte_partition",
+ "//pw_log",
+ ],
+)
diff --git a/pw_blob_store/size_report/BUILD.gn b/pw_blob_store/size_report/BUILD.gn
new file mode 100644
index 0000000..aca6b84
--- /dev/null
+++ b/pw_blob_store/size_report/BUILD.gn
@@ -0,0 +1,41 @@
+# Copyright 2021 The Pigweed Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may not
+# use this file except in compliance with the License. You may obtain a copy of
+# the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations under
+# the License.
+
+import("//build_overrides/pigweed.gni")
+
+import("$dir_pw_build/target_types.gni")
+
+_deps = [
+ "$dir_pw_bloat:bloat_this_binary",
+ "$dir_pw_kvs:fake_flash_12_byte_partition",
+ "$dir_pw_kvs:flash_test_partition",
+ dir_pw_assert,
+ dir_pw_kvs,
+ dir_pw_log,
+]
+
+pw_executable("base") {
+ sources = [ "base.cc" ]
+ deps = _deps
+}
+
+pw_executable("basic_blob") {
+ sources = [ "basic_blob.cc" ]
+ deps = _deps + [ dir_pw_blob_store ]
+}
+
+pw_executable("deferred_write_blob") {
+ sources = [ "deferred_write_blob.cc" ]
+ deps = _deps + [ dir_pw_blob_store ]
+}
diff --git a/pw_blob_store/size_report/base.cc b/pw_blob_store/size_report/base.cc
new file mode 100644
index 0000000..8f0cc65
--- /dev/null
+++ b/pw_blob_store/size_report/base.cc
@@ -0,0 +1,78 @@
+// Copyright 2021 The Pigweed Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+#include <cstring>
+
+#include "pw_assert/assert.h"
+#include "pw_bloat/bloat_this_binary.h"
+#include "pw_kvs/flash_test_partition.h"
+#include "pw_kvs/key_value_store.h"
+#include "pw_log/log.h"
+
+char working_buffer[256];
+volatile bool is_set;
+
+constexpr size_t kMaxSectorCount = 64;
+constexpr size_t kKvsMaxEntries = 32;
+
+// For KVS magic value always use a random 32 bit integer rather than a human
+// readable 4 bytes. See pw_kvs/format.h for more information.
+static constexpr pw::kvs::EntryFormat kvs_format = {.magic = 0x22d3f8a0,
+ .checksum = nullptr};
+
+volatile size_t kvs_entry_count;
+
+pw::kvs::KeyValueStoreBuffer<kKvsMaxEntries, kMaxSectorCount> test_kvs(
+ &pw::kvs::FlashTestPartition(), kvs_format);
+
+int volatile* unoptimizable;
+
+int main() {
+ pw::bloat::BloatThisBinary();
+
+ // Start of base **********************
+ // Ensure we are paying the cost for log and assert.
+ PW_CHECK_INT_GE(*unoptimizable, 0, "Ensure this CHECK logic stays");
+ PW_LOG_INFO("We care about optimizing: %d", *unoptimizable);
+
+ void* result =
+ std::memset((void*)working_buffer, sizeof(working_buffer), 0x55);
+ is_set = (result != nullptr);
+
+ test_kvs.Init();
+
+ unsigned kvs_value = 42;
+ test_kvs.Put("example_key", kvs_value);
+
+ kvs_entry_count = test_kvs.size();
+
+ unsigned read_value = 0;
+ test_kvs.Get("example_key", &read_value);
+ test_kvs.Delete("example_key");
+
+ auto val = pw::kvs::FlashTestPartition().PartitionAddressToMcuAddress(0);
+ PW_LOG_INFO("Use the variable. %u", unsigned(*val));
+
+ std::array<std::byte, 32> blob_source_buffer;
+ pw::ConstByteSpan write_data = std::span(blob_source_buffer);
+ char name[16] = "BLOB";
+ std::array<std::byte, 32> read_buffer;
+ pw::ByteSpan read_span = read_buffer;
+ PW_LOG_INFO("Do something so variables are used. %u, %c, %u",
+ unsigned(write_data.size()),
+ name[0],
+ unsigned(read_span.size()));
+ // End of base **********************
+ return 0;
+}
diff --git a/pw_blob_store/size_report/basic_blob.cc b/pw_blob_store/size_report/basic_blob.cc
new file mode 100644
index 0000000..667bc01
--- /dev/null
+++ b/pw_blob_store/size_report/basic_blob.cc
@@ -0,0 +1,104 @@
+// Copyright 2021 The Pigweed Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+#include <cstring>
+
+#include "pw_assert/assert.h"
+#include "pw_bloat/bloat_this_binary.h"
+#include "pw_blob_store/blob_store.h"
+#include "pw_kvs/flash_test_partition.h"
+#include "pw_kvs/key_value_store.h"
+#include "pw_log/log.h"
+
+char working_buffer[256];
+volatile bool is_set;
+
+constexpr size_t kMaxSectorCount = 64;
+constexpr size_t kKvsMaxEntries = 32;
+
+// For KVS magic value always use a random 32 bit integer rather than a human
+// readable 4 bytes. See pw_kvs/format.h for more information.
+static constexpr pw::kvs::EntryFormat kvs_format = {.magic = 0x22d3f8a0,
+ .checksum = nullptr};
+
+volatile size_t kvs_entry_count;
+
+pw::kvs::KeyValueStoreBuffer<kKvsMaxEntries, kMaxSectorCount> test_kvs(
+ &pw::kvs::FlashTestPartition(), kvs_format);
+
+int volatile* unoptimizable;
+
+int main() {
+ pw::bloat::BloatThisBinary();
+
+ // Start of base **********************
+ // Ensure we are paying the cost for log and assert.
+ PW_CHECK_INT_GE(*unoptimizable, 0, "Ensure this CHECK logic stays");
+ PW_LOG_INFO("We care about optimizing: %d", *unoptimizable);
+
+ void* result =
+ std::memset((void*)working_buffer, sizeof(working_buffer), 0x55);
+ is_set = (result != nullptr);
+
+ test_kvs.Init();
+
+ unsigned kvs_value = 42;
+ test_kvs.Put("example_key", kvs_value);
+
+ kvs_entry_count = test_kvs.size();
+
+ unsigned read_value = 0;
+ test_kvs.Get("example_key", &read_value);
+ test_kvs.Delete("example_key");
+
+ auto val = pw::kvs::FlashTestPartition().PartitionAddressToMcuAddress(0);
+ PW_LOG_INFO("Use the variable. %u", unsigned(*val));
+
+ std::array<std::byte, 32> blob_source_buffer;
+ pw::ConstByteSpan write_data = std::span(blob_source_buffer);
+ char name[16] = "BLOB";
+ std::array<std::byte, 32> read_buffer;
+ pw::ByteSpan read_span = read_buffer;
+ PW_LOG_INFO("Do something so variables are used. %u, %c, %u",
+ unsigned(write_data.size()),
+ name[0],
+ unsigned(read_span.size()));
+ // End of base **********************
+
+ // Start of basic blob **********************
+ constexpr size_t kBufferSize = 1;
+
+ pw::blob_store::BlobStoreBuffer<kBufferSize> blob(
+ name, pw::kvs::FlashTestPartition(), nullptr, test_kvs, kBufferSize);
+ blob.Init();
+
+ // Use writer.
+ pw::blob_store::BlobStore::BlobWriter writer(blob);
+ writer.Open();
+ writer.Write(write_data);
+ writer.Close();
+
+ // Use reader.
+ pw::blob_store::BlobStore::BlobReader reader(blob);
+ reader.Open();
+ pw::Result<pw::ConstByteSpan> get_result = reader.GetMemoryMappedBlob();
+ PW_LOG_INFO("%d", get_result.ok());
+ auto reader_result = reader.Read(read_span);
+ reader.Close();
+ PW_LOG_INFO("%d", reader_result.ok());
+
+ // End of basic blob **********************
+
+ return 0;
+}
diff --git a/pw_blob_store/size_report/deferred_write_blob.cc b/pw_blob_store/size_report/deferred_write_blob.cc
new file mode 100644
index 0000000..db2f18a
--- /dev/null
+++ b/pw_blob_store/size_report/deferred_write_blob.cc
@@ -0,0 +1,105 @@
+// Copyright 2021 The Pigweed Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+#include <cstring>
+
+#include "pw_assert/assert.h"
+#include "pw_bloat/bloat_this_binary.h"
+#include "pw_blob_store/blob_store.h"
+#include "pw_kvs/flash_test_partition.h"
+#include "pw_kvs/key_value_store.h"
+#include "pw_log/log.h"
+
+char working_buffer[256];
+volatile bool is_set;
+
+constexpr size_t kMaxSectorCount = 64;
+constexpr size_t kKvsMaxEntries = 32;
+
+// For KVS magic value always use a random 32 bit integer rather than a human
+// readable 4 bytes. See pw_kvs/format.h for more information.
+static constexpr pw::kvs::EntryFormat kvs_format = {.magic = 0x22d3f8a0,
+ .checksum = nullptr};
+
+volatile size_t kvs_entry_count;
+
+pw::kvs::KeyValueStoreBuffer<kKvsMaxEntries, kMaxSectorCount> test_kvs(
+ &pw::kvs::FlashTestPartition(), kvs_format);
+
+int volatile* unoptimizable;
+
+int main() {
+ pw::bloat::BloatThisBinary();
+
+ // Start of base **********************
+ // Ensure we are paying the cost for log and assert.
+ PW_CHECK_INT_GE(*unoptimizable, 0, "Ensure this CHECK logic stays");
+ PW_LOG_INFO("We care about optimizing: %d", *unoptimizable);
+
+ void* result =
+ std::memset((void*)working_buffer, sizeof(working_buffer), 0x55);
+ is_set = (result != nullptr);
+
+ test_kvs.Init();
+
+ unsigned kvs_value = 42;
+ test_kvs.Put("example_key", kvs_value);
+
+ kvs_entry_count = test_kvs.size();
+
+ unsigned read_value = 0;
+ test_kvs.Get("example_key", &read_value);
+ test_kvs.Delete("example_key");
+
+ auto val = pw::kvs::FlashTestPartition().PartitionAddressToMcuAddress(0);
+ PW_LOG_INFO("Use the variable. %u", unsigned(*val));
+
+ std::array<std::byte, 32> blob_source_buffer;
+ pw::ConstByteSpan write_data = std::span(blob_source_buffer);
+ char name[16] = "BLOB";
+ std::array<std::byte, 32> read_buffer;
+ pw::ByteSpan read_span = read_buffer;
+ PW_LOG_INFO("Do something so variables are used. %u, %c, %u",
+ unsigned(write_data.size()),
+ name[0],
+ unsigned(read_span.size()));
+ // End of base **********************
+
+ // Start of deferred blob **********************
+ constexpr size_t kBufferSize = 1;
+
+ pw::blob_store::BlobStoreBuffer<kBufferSize> blob(
+ name, pw::kvs::FlashTestPartition(), nullptr, test_kvs, kBufferSize);
+ blob.Init();
+
+ // Use writer.
+ pw::blob_store::BlobStore::DeferredWriter writer(blob);
+ writer.Open();
+ writer.Write(write_data);
+ writer.Flush();
+ writer.Close();
+
+ // Use reader.
+ pw::blob_store::BlobStore::BlobReader reader(blob);
+ reader.Open();
+ pw::Result<pw::ConstByteSpan> get_result = reader.GetMemoryMappedBlob();
+ PW_LOG_INFO("%d", get_result.ok());
+ auto reader_result = reader.Read(read_span);
+ reader.Close();
+ PW_LOG_INFO("%d", reader_result.ok());
+
+ // End of deferred blob **********************
+
+ return 0;
+}