Add benchmarks, migration tests, and dev guide

Add benchmarks for core operations, migration edge case tests, improved
buffer I/O tests, and developer guide

- Introduced `test_benchmarks.cc` for performance benchmarking of key
  operations in `PieceTable` and `Buffer`, including syntax highlighting
  and iteration patterns.
- Added `test_migration_coverage.cc` to provide comprehensive tests for
  migration of `Buffer::Rows()` to `PieceTable` APIs, with edge cases,
  boundary handling, and consistency checks.
- Enhanced `test_buffer_io.cc` with additional cases for save/load
  workflows, file handling, and better integration with the core API.
- Documented architectural details and core concepts in a new
  `DEVELOPER_GUIDE.md`. Highlighted design principles, code
  organization, and contribution workflows.
This commit is contained in:
2026-02-17 16:08:23 -08:00
parent 337b585ba0
commit 8ec0d6ac41
30 changed files with 1916 additions and 102 deletions

14
Swap.cc
View File

@@ -25,14 +25,14 @@ constexpr std::uint32_t VERSION = 1;
static std::string
snapshot_buffer_bytes(const Buffer &b)
{
const auto &rows = b.Rows();
const std::size_t nrows = b.Nrows();
std::string out;
// Cheap lower bound: sum of row sizes.
std::size_t approx = 0;
for (const auto &r: rows)
approx += r.size();
for (std::size_t i = 0; i < nrows; i++)
approx += b.GetLineView(i).size();
out.reserve(approx);
for (std::size_t i = 0; i < rows.size(); i++) {
for (std::size_t i = 0; i < nrows; i++) {
auto v = b.GetLineView(i);
out.append(v.data(), v.size());
}
@@ -284,8 +284,10 @@ SwapManager::Attach(Buffer *buf)
void
SwapManager::Detach(Buffer *buf, const bool remove_file)
{
if (!buf)
if (!buf) {
return;
}
// Write a best-effort final checkpoint before suspending and closing.
// If the caller requested removal, skip the final checkpoint so the file can be deleted.
if (!remove_file)
@@ -297,6 +299,7 @@ SwapManager::Detach(Buffer *buf, const bool remove_file)
it->second.suspended = true;
}
}
Flush(buf);
std::string path;
{
@@ -309,6 +312,7 @@ SwapManager::Detach(Buffer *buf, const bool remove_file)
}
recorders_.erase(buf);
}
if (remove_file && !path.empty()) {
(void) std::remove(path.c_str());
}