-
Notifications
You must be signed in to change notification settings - Fork 459
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
To compare string ignoring case, use the option StringComparison.OrdinalIgnoreCase #1321
base: master
Are you sure you want to change the base?
Conversation
…nalIgnoreCase instead of converting the case of the whole string.
@randruc, although you made the code "more correct", there's another issue with The correct equivalent would be Every time any case insensitive comparison is done, the overload with You'll find lots in this code base. |
I indeed found a lot. More generally in the code base, string manipulation is not done the best way. There are lots of potential improvements in changing the way it deals with strings. In particular, concatenations happen everywhere. |
Extracting the strings to a static HashMap(?) then |
I don't see how ToLower() could be faster than ordinal parsing. ToLower() allocates a new string, and iterates over each character. |
I think what @ha-ves is suggesting is having a pre-built dictionary (a frozen dictionary for the supported targets) with a |
I see. Again, in the overall, the mechanics of strings extraction and parsing could indeed be significantly improved. |
value.Equals("rejected", StringComparison.OrdinalIgnoreCase) || | ||
value.Equals("replaced", StringComparison.OrdinalIgnoreCase) || | ||
value.Equals("remote-bye", StringComparison.OrdinalIgnoreCase) || | ||
value.Equals("timeout", StringComparison.OrdinalIgnoreCase); |
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.
Given this is being refactored why not make it even readable:
return value.ToLowerInvariant() is "cancelled"
or "error"
or "local-bye"
or "rejected"
or "replaced"
or "remote-bye"
or "timeout";
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.
That will potentially allocate a string.
The purposed code is a bit more verbose, but potentially more performant.
Unless all input has be previously sanitized and guaranteed to be lower case.
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.
Couldn't agree more.
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'm struggling to see why the emphasis on such fine grained optimisations (in itself an anti-pattern). This part of the code is dealing with the SIP signalling protocol which has far lower traffic volumes than the media & RTP traffic. And even if you're intent on milking performance from the SIP stack you're starting in the wrong place, for example see the extensive use of regex'es in SIPHeader.cs which will far outweigh any string allocations (not that there have been any performance issues reported in that class the last 20 years).
For 90% of the classes in this library the emphasis should be on readability and maintainability ahead of extracting the last 10% of performance. The RTP stack is an exception.
Unlike this lirbary there is a prototype C# video encoding attempt that could benefit a lot from perfomance improvements.
In my use case, I'm trying to run dozens of agents in parallel on a machine with few memory. The performance we are talking about is memory footprint. The very simple use cases with a basic PCM codec is already quite greedy. The part of the library that deals with SIP consumes lots of memory, only for sending signaling messages, as it is full of ToLower(), Trim(), concatenations, and the like, that allocate a new string on each call. |
Fair enough and if performance is a primary requirement there are C/C++ projects (pjsip, kamailio etc) that will always out perform a managed application environment. My point here is that while I, and I'm sure other library users, are grateful for all improvements we're here in c#/dotnet for the ease of use and as above readability & maintainability are signigicant concerns. tldr; PR's that revolve around solving a string allocation here and there at the cost of readability/maintainability are unlikely to be met with much enthusiasm. |
With modern C#/.NET you can get good performance and be on par with C/C++. |
I'm absolutely impressed by what you did with creating this project. I discovered it quite recently, tried it, and the fact is that not only it fits my need, but it worked on the first place! |
I'm working on high performance logging at the moment (it will take a couple of weeks) as a quick win to get out of the way the cost of logging even when not logging. Then I intend to tackle the easy performance issues you mention with strings. Then, eventually, get rid of strings (arrays of 16bit chars) and move to arrays of bytes. That will half the size of most data manipulation. |
We came to the same kind of conclusions regarding strings. |
C# is a programing language for the .NET runtime. They work in tandem. I don't know Go. What does those go slices provide that Span/ReadOnlySpan doesn't? |
Go includes slices in the syntax of the language itself, not as an API like ReadOnlySpan in C#. Slices manipulation is actually the idiomatic way to deal with strings in Go. This is why strings in Go are extremely fast. |
But to answer your question, we should be able to do the equivalent of slices with ReadOnlySpan of course. It's just a bit annoying to write, as it's an API. |
Sure, for some things, for others .NET, or any other memory managed environment, can't compete. There are no general purpose real-time video codecs that can deal with 1080p @ 30fps (or even close) built with C#, Java etc (native library wrappers excluded). |
From my point of view I don't have any BIG plans for the library. I like messing around with SIP & WebRTC and this library, it scratches an itch. I was alwyas thinking Microsoft would eventually add a real-time comms library to .NET but it's never happened. Maybe the AI Realtime API's will finally push them to do it, probably not. It's also not a dictatorship. There have been periods where other maintainers have been more active than me. Maybe someone else will take it in a different direction one day. Again probably not. It's a massive undertaking to get to grips with the underlying standards & concepts for any of SIP, VoiP, RTP or WebRTC let alone all of them together. It's more than a full-time job and it's not a particularly lucrative area (VoIP and WebRTC services are typically free). As far as contributions go they are always welcome (and note that above I said "not much enthusiasm" rather than "not welcome"). The challenge as a maintainer is that people can come often along with big ideas to make wholesale changes. If those changes don't work out, or leave things in a worse state, it's the maintainer(s) that invaribly need to sort it out. What;s appreciated a lot more than applying the latest style fads or optimisations is adding a new capability or enhancement. There's a big list to choose from. Once you get familiar with the library and/or other contributors it's easier to be comfortable accepting changes that have an impact in a broader area. |
I don't know almost nothing about SIP, VoIP, RTP, WebRTC or even networking, but I know my way around C# and .NET. I'm working on a massive PR for High-performance logging, so that logging really becomes pay for play. At the moment, even after #1306, there's a lot of resources being consumed, and that will fix it. Skimming at the code, I noticed a lot of unnecessary string creation (concatenation, upper/lower). Some need to be removed, others need to make more use of But, all this text (as in If it's about And, finally, Pipelines. I'm not a fan of big bang changes. So, iterating over this will be safer to keep everything going. |
This is much better for performance, as it avoids string allocations and conversion of the whole string prior to comparing. It is also idiomatic.