-
Notifications
You must be signed in to change notification settings - Fork 333
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Performance and safety improvements #429
base: master
Are you sure you want to change the base?
Conversation
ef76547
to
69591ea
Compare
d3a418b
to
b5906e2
Compare
Rebased and tested with GCC/Debian/testing, Windows Visual Studio Community 2022 and AppleClang/MacOS. Potential reservations: changes the API subtly, not sure about consequences for other projects which use this. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice. Removing std::regex is refreshing. :)
}; // class backend_interface | ||
|
||
/// Captures (backend) version information. | ||
struct Version { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs MATPLOT_EXPORTS if it's part of the API.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would also be good to maintain the snake_case convention. version
or maybe gnuplot::version
since there's no other backend.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll make it snake case, sorry.
I could also move Version to gnuplot, I just thought the class is more general than just gnuplot.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. Outside gnuplot
is also OK. I was thinking about the name-grabbing, but that's also OK. We won't need matplot::version
for anything else.
std::string gnuplot::default_terminal_type() { | ||
static std::string terminal_type; | ||
const bool dont_know_term_type = terminal_type.empty(); | ||
if (dont_know_term_type) { | ||
terminal_type = run_and_get_output("gnuplot -e \"show terminal\" 2>&1"); | ||
terminal_type = std::regex_replace(terminal_type, | ||
std::regex("[^]*terminal type is ([^ ]+)[^]*"), "$1"); | ||
terminal_type = word_after(terminal_type, "terminal type is "); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Heh... Great! :)
source/matplot/backend/gnuplot.cpp
Outdated
if (!version) { // unknown version | ||
const auto version_str = run_and_get_output("gnuplot --version 2>&1"); | ||
const auto major = word_after(version_str, "gnuplot"); | ||
const auto minor = word_after(major, "."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This pattern is a little confusing when the function is called repeatedly. Let's say the output is "... gnuplot 5.2 patchlevel 6"
. Wouldn't major
just be "5"
? If so, then there's no word after "."
because major
doesn't include everything after 5
. That is, major is "5"
and not "5.2 patchlevel 6"
. On the other hand, if major
does contain "5.2 patchlevel 6"
, then the function name and return value are a little misleading.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, the name major
is misleading, I have renamed it to major_minor
and added example in comments -- I think it's clearer when an example is upfront.
source/matplot/backend/gnuplot.h
Outdated
@@ -47,7 +47,7 @@ namespace matplot::backend { | |||
/// Identify the default terminal type in the system | |||
static std::string default_terminal_type(); | |||
static bool terminal_is_available(std::string_view); | |||
static std::tuple<int, int, int> gnuplot_version(); | |||
static Version gnuplot_version(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So converting the output to a tuple
wouldn't break the API? A Version
is a better decision than a tuple,
but it's hard to tell how many people are counting on this API.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, I have reverted Version
to std::tuple
as I did not know that one can compare them in such elegant way. I used to kill it if the code is not about generic programming (Scott Meyers book).
I learned something today, thanks!
@@ -426,7 +426,7 @@ namespace matplot { | |||
run_command("set polar"); | |||
} | |||
auto set_or_unset_axis = [this](class axis_type &ax, | |||
std::string axis_name, | |||
const std::string &axis_name, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If that was your concern about breaking the API, both std::string axis_name
and std::string const& axis_name
are OK. In the implementation the std::string axis_name
can be moved and the std::string const& axis_name
can be copied. As far as the user is concerned, that doesn't functionally break the API. Only std::string &axis_name
would be a problem.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No concerns here: that is just a lambda expression - internal stuff.
And yes, it'll bind to the same calls as previously, we just need to make sure that the lambda expression itself does not modify the parameters, but that is checked by the compiler.
} | ||
constexpr bool operator!=(const Version &other) const { return !(*this == other); } | ||
constexpr bool operator<(const Version &other) const { | ||
if (major < other.major) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it the same as std::tie(major, minor, patch) < std::tie(other.major, other.minor, other.patch)
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. Looking at the rest of the code and considering tuple
defines operator<
, I do prefer Version
over tuple
here if we were coming up with the original API now, but I don't think breaking it now brings a lot of value compared to the potential hassle of people opening issues because the API changed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is gone, sorry my bad.
axes_type::fplot(std::vector<function_line::function_type> equations, | ||
std::array<double, 2> x_range, | ||
std::vector<std::string> line_specs) { | ||
axes_type::fplot(const std::vector<function_line::function_type> &equations, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here. All these API changes are OK.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's OK if the thing is recompiled, but I am not sure at ABI level, and I do not know if anyone cares.
I have removed my |
const bool has_wall_option = | ||
std::get<0>(v) > 5 || (std::get<0>(v) == 5 && std::get<1>(v) >= 5); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this was my trigger :-)
std::regex
withstd:string_view
scanning (thousands of times faster)std::tuple
with dedicatedVersion
class with named membersbackend_interface
for safetyconst &
infplot
and moreclang_tidy
suggests making lots ofconst
methods and more...