mirror of
https://github.com/SpartanJ/eepp.git
synced 2026-10-01 18:50:16 +03:00
perf: reduce allocations across UI and editor hot paths
- reuse formatting, document text, property resolution, and layout storage - use inline containers for interpolations, callbacks, wrapping, and matcher state - optimize single-line insertion by mutating document lines without splitting - iterate PATH entries directly in Sys::which and reuse candidate buffers - avoid temporary clocks and string copies in frequent ecode plugin updates - retain documents during autocomplete cache jobs and prevent duplicate scheduling - fix PatternMatcher copy assignment and MSVC move-only container compilation - expand coverage for matching, text insertion, reusable strings, and Sys::which
This commit is contained in:
@@ -566,6 +566,13 @@ class EE_API String {
|
||||
|
||||
template <typename... Args>
|
||||
static std::string format( std::string_view format, Args&&... args ) {
|
||||
std::string result;
|
||||
formatTo( result, format, std::forward<Args>( args )... );
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
static void formatTo( std::string& result, std::string_view format, Args&&... args ) {
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wformat-security"
|
||||
@@ -578,18 +585,22 @@ class EE_API String {
|
||||
std::snprintf( nullptr, 0, format.data(),
|
||||
FormatArg<std::decay_t<Args>>::get( std::forward<Args>( args ) )... );
|
||||
|
||||
if ( reqSize < 0 )
|
||||
return "";
|
||||
if ( reqSize < 0 ) {
|
||||
result.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
std::size_t bufSize = static_cast<std::size_t>( reqSize ) + 1;
|
||||
std::string result( bufSize, '\0' );
|
||||
result.resize( bufSize );
|
||||
|
||||
int writtenChars =
|
||||
std::snprintf( &result[0], bufSize, format.data(),
|
||||
FormatArg<std::decay_t<Args>>::get( std::forward<Args>( args ) )... );
|
||||
|
||||
if ( writtenChars < 0 )
|
||||
return "";
|
||||
if ( writtenChars < 0 ) {
|
||||
result.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
if ( static_cast<std::size_t>( writtenChars ) < bufSize ) {
|
||||
result.resize( static_cast<std::size_t>( writtenChars ) );
|
||||
@@ -602,7 +613,6 @@ class EE_API String {
|
||||
#elif defined( __GNUC__ )
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Format a char buffer */
|
||||
@@ -993,6 +1003,9 @@ class EE_API String {
|
||||
|
||||
String& assign( const char* s );
|
||||
|
||||
/** Assigns UTF-8 text while retaining the current UTF-32 storage capacity. */
|
||||
String& assignUtf8( std::string_view utf8String );
|
||||
|
||||
String& assign( std::size_t n, StringBaseType c );
|
||||
|
||||
template <class InputIterator> String& assign( InputIterator first, InputIterator last ) {
|
||||
|
||||
@@ -111,7 +111,7 @@ class EE_API Interpolation1d {
|
||||
const Time& getDuration() const;
|
||||
|
||||
/** @return the vector of points */
|
||||
const std::vector<Point1d>& getPoints() const;
|
||||
const SmallVector<Point1d, 8>& getPoints() const;
|
||||
|
||||
/** @return the vector of points reversed */
|
||||
std::vector<Point1d> getReversePoints();
|
||||
@@ -163,7 +163,7 @@ class EE_API Interpolation1d {
|
||||
|
||||
Float mSpeed;
|
||||
|
||||
std::vector<Point1d> mPoints;
|
||||
SmallVector<Point1d, 8> mPoints;
|
||||
|
||||
Point1d* mActP;
|
||||
Point1d* mNexP;
|
||||
|
||||
@@ -112,7 +112,7 @@ class EE_API Interpolation2d {
|
||||
const Uint32& getCurrentPositionIndex() const;
|
||||
|
||||
/** @return the vector of waypoints */
|
||||
const std::vector<Point2d>& getPoints() const;
|
||||
const SmallVector<Point2d, 8>& getPoints() const;
|
||||
|
||||
/** @return the vector of waypoints reversed */
|
||||
std::vector<Point2d> getReversePoints();
|
||||
@@ -167,7 +167,7 @@ class EE_API Interpolation2d {
|
||||
Point2d* mActP;
|
||||
Point2d* mNexP;
|
||||
|
||||
std::vector<Point2d> mPoints;
|
||||
SmallVector<Point2d, 8> mPoints;
|
||||
|
||||
OnPathEndCallback mOnPathEndCallback;
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifndef EE_SYSTEM_PATTERNMATCHER_HPP
|
||||
#define EE_SYSTEM_PATTERNMATCHER_HPP
|
||||
|
||||
#include <array>
|
||||
#include <eepp/config.hpp>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
@@ -23,16 +24,19 @@ class EE_API PatternMatcher {
|
||||
class EE_API State {
|
||||
public:
|
||||
State( PatternMatcher* pattern, bool ownPattern );
|
||||
State( const State& other );
|
||||
State& operator=( const State& other );
|
||||
|
||||
~State();
|
||||
|
||||
bool range( int index, int& start, int& end );
|
||||
void swap( State& other ) noexcept;
|
||||
|
||||
bool range( int index, int& start, int& end ) const;
|
||||
|
||||
bool matches( const char* string, size_t length );
|
||||
|
||||
PatternMatcher* mPattern;
|
||||
Range* mRanges;
|
||||
size_t mRefCount;
|
||||
std::array<Range, 10> mRanges;
|
||||
bool mOwnPattern;
|
||||
};
|
||||
|
||||
@@ -87,7 +91,7 @@ class EE_API PatternMatcher {
|
||||
iterator end() { return iterator( nullptr ); }
|
||||
|
||||
protected:
|
||||
PatternMatcher::State* mState{ nullptr };
|
||||
PatternMatcher::State mState;
|
||||
const char* mString{ nullptr };
|
||||
size_t mLength{ 0 };
|
||||
};
|
||||
@@ -107,7 +111,7 @@ class EE_API PatternMatcher {
|
||||
PatternMatcher::Match gmatch( const std::string& string ) &;
|
||||
|
||||
bool range( int indexGet, int& startMatch, int& endMatch,
|
||||
PatternMatcher::Range* returnedMatched ) const;
|
||||
const PatternMatcher::Range* returnedMatched ) const;
|
||||
|
||||
bool find( const std::string& s, int& startMatch, int& endMatch, int offset = 0,
|
||||
int returnedMatchIndex = 0 ) const;
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <condition_variable>
|
||||
#include <deque>
|
||||
#include <eepp/core/noncopyable.hpp>
|
||||
#include <eepp/core/small_function.hpp>
|
||||
#include <eepp/system/lock.hpp>
|
||||
#include <eepp/system/mutex.hpp>
|
||||
#include <eepp/system/thread.hpp>
|
||||
@@ -28,10 +29,9 @@ class EE_API ThreadPool : NonCopyable {
|
||||
|
||||
virtual ~ThreadPool();
|
||||
|
||||
Uint64 run(
|
||||
const std::function<void()>& func,
|
||||
const std::function<void( const Uint64& )>& doneCallback = []( const Uint64& ) {},
|
||||
const Uint64& tag = 0 );
|
||||
Uint64 run( SmallFunction<48> func,
|
||||
const std::function<void( const Uint64& )>& doneCallback = {},
|
||||
const Uint64& tag = 0 );
|
||||
|
||||
Uint32 numThreads() const;
|
||||
|
||||
@@ -50,7 +50,7 @@ class EE_API ThreadPool : NonCopyable {
|
||||
private:
|
||||
struct Work {
|
||||
Uint64 id{ 0 };
|
||||
const std::function<void()> func;
|
||||
const SmallFunction<48> func;
|
||||
const std::function<void( const Uint64& )> callback;
|
||||
Uint64 tag{ 0 };
|
||||
};
|
||||
|
||||
@@ -213,6 +213,8 @@ class EE_API TextDocument {
|
||||
|
||||
String getText( const TextRange& range ) const;
|
||||
|
||||
void getTextToBuffer( const TextRange& range, String& buffer ) const;
|
||||
|
||||
String getText() const;
|
||||
|
||||
String getSelectedText() const;
|
||||
|
||||
@@ -78,6 +78,17 @@ class EE_API TextDocumentLine {
|
||||
}
|
||||
}
|
||||
|
||||
void insert( std::size_t position, const String& text ) {
|
||||
if ( mDocMutex ) {
|
||||
Lock lock( *mDocMutex );
|
||||
mText.insert( position, text );
|
||||
updateState();
|
||||
} else {
|
||||
mText.insert( position, text );
|
||||
updateState();
|
||||
}
|
||||
}
|
||||
|
||||
String substr( std::size_t pos = 0, std::size_t n = String::StringType::npos ) const {
|
||||
if ( mDocMutex ) {
|
||||
Lock lock( *mDocMutex );
|
||||
|
||||
@@ -965,6 +965,7 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client {
|
||||
Mutex mHighlightWordCacheMutex;
|
||||
TextRange mHighlightTextRange;
|
||||
TextRange mPreviewColorRange;
|
||||
String mMouseOverColorBuffer;
|
||||
std::vector<UICodeEditorPlugin*> mPlugins;
|
||||
UILoader* mLoader{ nullptr };
|
||||
Float mGlyphWidth{ 0 };
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifndef EE_UI_UISTACKLAYOUT_HPP
|
||||
#define EE_UI_UISTACKLAYOUT_HPP
|
||||
|
||||
#include <eepp/core/small_vector.hpp>
|
||||
#include <eepp/ui/uilayout.hpp>
|
||||
|
||||
namespace EE { namespace UI {
|
||||
@@ -33,7 +34,14 @@ class EE_API UIStackLayout : public UILayout {
|
||||
void setRowValign( const RowValign& rowValign );
|
||||
|
||||
protected:
|
||||
struct NodeLine {
|
||||
SmallVector<UIWidget*, 2> nodes;
|
||||
Float maxY{ 0 };
|
||||
Float width{ 0 };
|
||||
};
|
||||
|
||||
RowValign mRowValign{ RowValign::Bottom };
|
||||
SmallVector<NodeLine, 4> mLines;
|
||||
Node* mParentRef{ nullptr };
|
||||
Uint32 mParentSizeChangeCb{ 0 };
|
||||
Uint32 mParentCloseCb{ 0 };
|
||||
|
||||
@@ -29,6 +29,11 @@ class EE_API UIStyle : public UIState {
|
||||
public:
|
||||
static UIStyle* New( UIWidget* widget );
|
||||
|
||||
UIStyle( const UIStyle& ) = delete;
|
||||
UIStyle& operator=( const UIStyle& ) = delete;
|
||||
UIStyle( UIStyle&& ) = delete;
|
||||
UIStyle& operator=( UIStyle&& ) = delete;
|
||||
|
||||
virtual ~UIStyle();
|
||||
|
||||
bool stateExists( const Uint32& state ) const;
|
||||
@@ -133,9 +138,10 @@ class EE_API UIStyle : public UIState {
|
||||
Uint32 mPropertyResolutionDepth{ 0 };
|
||||
Uint64 mLoadedVersion{ 0 };
|
||||
const CSS::StyleSheet* mLoadedStyleSheet{ nullptr };
|
||||
/** Lazily allocated for styles that use substitutions. The pointed-to properties remain stable
|
||||
* during nested resolutions and retain their string/vector capacities between state changes. */
|
||||
SmallVector<std::unique_ptr<CSS::StyleSheetProperty>, 1> mPropertyResolutionSlots;
|
||||
/** Lazily allocated for styles that use substitutions. The common, non-reentrant resolution
|
||||
* needs no container allocation; nested slots are retained for later reuse. */
|
||||
std::unique_ptr<CSS::StyleSheetProperty> mPropertyResolutionSlot;
|
||||
std::vector<std::unique_ptr<CSS::StyleSheetProperty>> mNestedPropertyResolutionSlots;
|
||||
bool mChangingState;
|
||||
bool mForceReapplyProperties;
|
||||
bool mDisableAnimations;
|
||||
|
||||
Reference in New Issue
Block a user