Skip to content

Commit

Permalink
refactor(lsp): prefer Vector over std::vector
Browse files Browse the repository at this point in the history
Reduce our use of std::vector to reduce binary bloat:
#689
  • Loading branch information
strager committed Nov 6, 2023
1 parent 7ee7681 commit 91a5cfe
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 19 deletions.
13 changes: 13 additions & 0 deletions src/quick-lint-js/container/vector-profiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,14 @@ class Instrumented_Vector {
return Span<const value_type>(this->data_);
}

void swap(Instrumented_Vector &other) {
this->data_.swap(other.data_);
std::swap(this->debug_owner_, other.debug_owner_);
// TODO(strager): Add instrumentation specific to swapping.
this->add_instrumentation_entry(Vector_Instrumentation::Event::resize);
other.add_instrumentation_entry(Vector_Instrumentation::Event::resize);
}

private:
QLJS_FORCE_INLINE void add_instrumentation_entry(
Vector_Instrumentation::Event event) {
Expand All @@ -370,6 +378,11 @@ class Instrumented_Vector {
Vector data_;
const char *debug_owner_;
};

template <class V>
void swap(Instrumented_Vector<V> &lhs, Instrumented_Vector<V> &rhs) {
lhs.swap(rhs);
}
#endif
}

Expand Down
25 changes: 25 additions & 0 deletions src/quick-lint-js/container/vector.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,17 @@ class Uninstrumented_Vector : private Vector {
using Vector::release_to_span;
using Vector::release_to_string_view;
using Vector::to_string_view;

void swap(Uninstrumented_Vector &other) {
static_cast<Vector &>(*this).swap(static_cast<Vector &>(other));
}
};

template <class V>
void swap(Uninstrumented_Vector<V> &lhs, Uninstrumented_Vector<V> &rhs) {
lhs.swap(rhs);
}

using Vector_Size = std::ptrdiff_t;

// Like std::pmr::vector. Some differences:
Expand Down Expand Up @@ -344,6 +353,17 @@ class Raw_Vector {

void erase(value_type *item) { erase(item, item + 1); }

// Swap capacity pointers and sizes between *this and other. All items of
// *this and other are untouched.
//
// Precondition: this->get_allocator() == other.get_allocator()
void swap(Raw_Vector &other) {
QLJS_ALWAYS_ASSERT(this->get_allocator() == other.get_allocator());
std::swap(this->data_, other.data_);
std::swap(this->data_end_, other.data_end_);
std::swap(this->capacity_end_, other.capacity_end_);
}

// If new_size > this->size(): default-construct new items at the end.
// If new_size < this->size(): destruct items at the end.
//
Expand Down Expand Up @@ -415,6 +435,11 @@ class Raw_Vector {
Memory_Resource *allocator_;
};

template <class T>
void swap(Raw_Vector<T> &lhs, Raw_Vector<T> &rhs) {
lhs.swap(rhs);
}

#if QLJS_FEATURE_VECTOR_PROFILING
template <class T>
using Vector = Instrumented_Vector<Raw_Vector<T>>;
Expand Down
21 changes: 10 additions & 11 deletions src/quick-lint-js/lsp/lsp-location.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,24 +139,24 @@ void LSP_Locator::replace_text(LSP_Range range, String8_View replacement_text,
narrow_cast<Offset_Type>(replacement_text.size());

QLJS_ASSERT(!this->offset_of_lines_.empty());
std::size_t start_line = narrow_cast<std::size_t>(range.start.line);
std::size_t end_line = std::min(this->offset_of_lines_.size() - 1,
narrow_cast<std::size_t>(range.end.line));
Vector_Size start_line = narrow_cast<Vector_Size>(range.start.line);
Vector_Size end_line = std::min(this->offset_of_lines_.size() - 1,
narrow_cast<Vector_Size>(range.end.line));

this->input_ = new_input;
std::swap(this->old_offset_of_lines_, this->offset_of_lines_);
std::swap(this->old_line_is_ascii_, this->line_is_ascii_);
swap(this->old_offset_of_lines_, this->offset_of_lines_);
swap(this->old_line_is_ascii_, this->line_is_ascii_);
this->offset_of_lines_.reserve(this->old_offset_of_lines_.size());
this->offset_of_lines_.clear();
this->line_is_ascii_.reserve(this->old_line_is_ascii_.size());
this->line_is_ascii_.clear();

// Offsets before replacement: do not adjust.
this->offset_of_lines_.insert(
this->offset_of_lines_.end(), this->old_offset_of_lines_.begin(),
this->offset_of_lines_.append(
this->old_offset_of_lines_.begin(),
this->old_offset_of_lines_.begin() + range.start.line + 1);
this->line_is_ascii_.insert(
this->line_is_ascii_.end(), this->old_line_is_ascii_.begin(),
this->line_is_ascii_.append(
this->old_line_is_ascii_.begin(),
this->old_line_is_ascii_.begin() + range.start.line);

// Offsets within replacement: re-parse newlines.
Expand All @@ -183,8 +183,7 @@ void LSP_Locator::replace_text(LSP_Range range, String8_View replacement_text,
[&](Offset_Type offset) -> Offset_Type {
return offset + net_bytes_added;
});
this->line_is_ascii_.insert(this->line_is_ascii_.end(),
this->old_line_is_ascii_.begin() +
this->line_is_ascii_.append(this->old_line_is_ascii_.begin() +
narrow_cast<std::ptrdiff_t>(end_line) + 1,
this->old_line_is_ascii_.end());

Expand Down
13 changes: 9 additions & 4 deletions src/quick-lint-js/lsp/lsp-location.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <cstddef>
#include <iosfwd>
#include <quick-lint-js/container/padded-string.h>
#include <quick-lint-js/container/vector.h>
#include <quick-lint-js/fe/source-code-span.h>
#include <quick-lint-js/port/char8.h>
#include <vector>
Expand Down Expand Up @@ -58,13 +59,17 @@ class LSP_Locator {
LSP_Position position(int line_number, Offset_Type offset) const;

Padded_String_View input_;
std::vector<Offset_Type> offset_of_lines_;
std::vector<unsigned char> line_is_ascii_;
Vector<Offset_Type> offset_of_lines_{"LSP_Locator::offset_of_lines_",
new_delete_resource()};
Vector<unsigned char> line_is_ascii_{"LSP_Locator::line_is_ascii_",
new_delete_resource()};

// old_offset_of_lines_ and old_line_is_ascii_ are used for double buffering
// of offset_of_lines_ and line_is_ascii_. This reduces allocations.
std::vector<Offset_Type> old_offset_of_lines_;
std::vector<unsigned char> old_line_is_ascii_;
Vector<Offset_Type> old_offset_of_lines_{"LSP_Locator::old_offset_of_lines_",
new_delete_resource()};
Vector<unsigned char> old_line_is_ascii_{"LSP_Locator::old_line_is_ascii_",
new_delete_resource()};
};
}

Expand Down
7 changes: 4 additions & 3 deletions src/quick-lint-js/lsp/lsp-message-parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <cstddef>
#include <optional>
#include <quick-lint-js/container/string-view.h>
#include <quick-lint-js/container/vector.h>
#include <quick-lint-js/port/char8.h>
#include <quick-lint-js/util/cast.h>
#include <quick-lint-js/util/integer.h>
Expand Down Expand Up @@ -37,7 +38,8 @@ class LSP_Message_Parser_Base {
static bool header_is(String8_View header_name,
String8_View expected_header_name);

std::vector<Char8> buffer_;
Vector<Char8> buffer_{"LSP_Message_Parser_Base::buffer_",
new_delete_resource()};

// If !pending_message_content_length_.has_value(), buffer_ contains message
// headers (and possibly message content and other messages afterwards).
Expand All @@ -63,8 +65,7 @@ template <class Derived>
class LSP_Message_Parser : private LSP_Message_Parser_Base {
public:
void append(String8_View data) {
this->buffer_.insert(this->buffer_.end(), data.data(),
data.data() + data.size());
this->buffer_ += data;
this->parse();
}

Expand Down
4 changes: 3 additions & 1 deletion src/quick-lint-js/lsp/outgoing-json-rpc-message-queue.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#else

#include <quick-lint-js/container/byte-buffer.h>
#include <quick-lint-js/container/vector.h>
#include <vector>

namespace quick_lint_js {
Expand All @@ -30,7 +31,8 @@ class Outgoing_JSON_RPC_Message_Queue {
void send(LSP_Endpoint_Remote&);

private:
std::vector<Byte_Buffer> messages_;
Vector<Byte_Buffer> messages_{"Outgoing_JSON_RPC_Message_Queue::messages_",
new_delete_resource()};
};
}

Expand Down

0 comments on commit 91a5cfe

Please sign in to comment.