Official Soldat Forums

Soldat Fans => Developers Corner => Topic started by: jrgp on March 14, 2011, 03:09:04 pm

Title: C++ Lobby Lister Class
Post by: jrgp on March 14, 2011, 03:09:04 pm
On devs wiki: http://devs.soldat.pl/wiki/index.php?title=Client-Lobby_Protocol_Parsers#By_jrgp
My personal server backup: http://jrgp.us/snipplets/lobby_client.cpp.txt

Compiles/runs on Linux, FreeBSD, and others. The exe generated by ming (using the comment at the top of the file) runs on Windows. I have not tried compiling the source directly on Windows but I assume it works since I'm using the winsock stuff.

It's [over] commented so dealing with it should be easy. Certain parts can be minified but I was too lazy. I was also too lazy to implement specific filtering.

Enjoy or use it for whatever.
Title: Re: C++ Lobby Lister Class
Post by: pubby8 on April 01, 2011, 11:13:56 pm
Nitpicks (since it is on wiki):
Put the "using namespace std" inside functions, not in global scope.
Don't use strlen inside for().
Use prefix ++ instead of postfix.
Title: Re: C++ Lobby Lister Class
Post by: FliesLikeABrick on April 02, 2011, 02:18:17 pm
Can you explain why each of those things is the better way to do it?  Otherwise we have no way to know if what you're saying is just preference or factually better for some reason.
Title: Re: C++ Lobby Lister Class
Post by: pubby8 on April 02, 2011, 06:28:58 pm
Quote
Put the "using namespace std" inside functions, not in global scope.
If "using namespace" is in a header file in global scope, then it applies to anything that includes that header. This causes lots of naming problems and is bad practice.

Quote
Don't use strlen inside for().
This technically means you must call strlen every iteration of the loop, when you only need to call it once. Some compilers (GCC) have specific optimizations for strlen inside for loops, but it is still bad practice and you should not rely on compiler to optimize it. Store value in variable and then use variable in loop!

Quote
Use prefix ++ instead of postfix.
This is pretty minor, but prefix doesn't return the value while postfix does. Prefix should always be used in for loops, and it is considered best practice to do it if you don't need to return the value.
Title: Re: C++ Lobby Lister Class
Post by: jrgp on April 02, 2011, 06:31:15 pm
Quote
Don't use strlen inside for().
This technically means you must call strlen every iteration of the loop, when you only need to call it once. Some compilers (GCC) have specific optimizations for strlen inside for loops, but it is still bad practice and you should not rely on compiler to optimize it. Store value in variable and then use variable in loop!

I agree with you, which is why it wasn't called each time. I think you read it wrong.
Code: (cpp) [Select]
for (i = 0, len = strlen(buff); i < len; i++)
Anything called/set before the first semicolon is just ran once.

I agree with the other two points you mentioned.
Title: Re: C++ Lobby Lister Class
Post by: FliesLikeABrick on April 02, 2011, 06:32:52 pm
Yeah the strlen() in a loop was one that I agree is bad.  didn't know/care about the other two because I don't do anything particularly complex with classes/namespaces - and the other one just seemed very minor.


jrgp is right, that strlen() will only get called once
Title: Re: C++ Lobby Lister Class
Post by: DorkeyDear on April 02, 2011, 07:06:25 pm
in regards to i++ and ++i (http://www.parashift.com/c++-faq-lite/operator-overloading.html#faq-13.15);
that's pretty much the most i can contribute here. :P
Title: Re: C++ Lobby Lister Class
Post by: pubby8 on April 02, 2011, 07:14:27 pm
Quote
Don't use strlen inside for().
This technically means you must call strlen every iteration of the loop, when you only need to call it once. Some compilers (GCC) have specific optimizations for strlen inside for loops, but it is still bad practice and you should not rely on compiler to optimize it. Store value in variable and then use variable in loop!

I agree with you, which is why it wasn't called each time. I think you read it wrong.
Code: (cpp) [Select]
for (i = 0, len = strlen(buff); i < len; i++)
Anything called/set before the first semicolon is just ran once.

I agree with the other two points you mentioned.

Oh, hehe. Didn't see the comma!
Title: Re: C++ Lobby Lister Class
Post by: FliesLikeABrick on April 02, 2011, 08:12:16 pm
I'd love it if you could provide me some references on the pre/post increment thing.  Thinking about it from a low-level machine point of view I'm not sure how they'd be implemented differently enough to make a difference at all, even in terms of just a few clock cycles.

http://physical-thought.blogspot.com/2008/11/pre-vs-post-increment-speed-test.html

I was about to do a test like that, but he did basically the same exact thing.

pubby, can you provide some evidence/links on the matter?
Title: Re: C++ Lobby Lister Class
Post by: pubby8 on April 02, 2011, 08:37:21 pm
It is mostly a problem if you overload classes with ++, as postfix may have to copy the value.

For normal types, it doesn't really matter, but I have habit of using prefix.
Title: Re: C++ Lobby Lister Class
Post by: Mr on April 03, 2011, 06:32:11 am
Instead of using an index to loop through a std::vector, use iterators instead, it's faster and results in smaller code:
Code: [Select]
// Show them
for (vector<server_entry>::iterator server = servers.begin(); server != servers.end(); server++) {
// (refer to any of the fields mentioned by struct near beginning of file)
cout << server->name << " " << server->ip << ":" << server->port << endl;
}

Thanks for the class, using it already.

EDIT: The destructor of the class is never called, add a "delete lc;" after receiving the server list.
The result of the following is always the same:
Code: [Select]
// Request
char req[100];
sprintf(req, "e%c0%c0%c0%c0%c0%c0%c0%c0%c0%c0%c0%c-1%c0%c0\n", 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169);
So why not shorten it to:
Code: [Select]
#define LB_SEP "\169"
const char req[] = "e"LB_SEP"0"LB_SEP"0"LB_SEP"0"LB_SEP"0"LB_SEP"0"LB_SEP"0"LB_SEP"0"LB_SEP"0"LB_SEP"0"LB_SEP"0"LB_SEP"0"LB_SEP"-1"LB_SEP"0"LB_SEP"0\n";
Title: Re: C++ Lobby Lister Class
Post by: pubby8 on April 03, 2011, 12:36:39 pm
Iterators aren't faster, they have more overhead.

Also, you should put a reserve before you start using push_back, so you don't end up with lots of reallocs.
Title: Re: C++ Lobby Lister Class
Post by: Clawbug on April 04, 2011, 02:49:14 am
Well, to throw something in from my part, as I suggested to jrgp on IRC, the standard C libraries should be prefixed with c and should not have .h postfix in them, meaning that e.g. stdio.h becomes cstdio etc.
Title: Re: C++ Lobby Lister Class
Post by: FliesLikeABrick on April 05, 2011, 07:36:41 pm
Yeah, for a vector/array/anything else which uses sequential memory - [] should always be faster than an iterator because you're directly addressing the memory offset.
Title: Re: C++ Lobby Lister Class
Post by: ramirez on April 08, 2011, 07:49:16 am
Quote from: pubby8
Iterators aren't faster, they have more overhead.
Quote from: FliesLikeABrick
Yeah, for a vector/array/anything else which uses sequential memory - [] should always be faster than an iterator because you're directly addressing the memory offset.
This is a common misconception, however it is not true. The correct answer is that which is faster is implementation specific and hence depends on the compiler and what settings you use with it. The standard does in no way specify in which way a compiler should implement the iterator for a given container, the implementation details are completely up to the compiler, you can't say "iterators have more overhead", because different compilers can implement iterators differently. The ONLY thing that is defined is that a certain type of an iterator must do certain things, eg. a forward_iterator must be able to be incremented (these are called "iterator concepts" for the record).

Now that we've gotten technicalities out of the way, let's get back to the real world. What most people don't seem to know is that most compilers actually implement vector iterators as pointers. Yes, that's right. Pointers. I've seen as crude implementations as the iterator being defined as a pointer, but most modern compilers like GCC and MSVC do a bit more; they have a wrapper classes around those pointers. Namely in GCC uses __gnu_cxx::__normal_iterator, and MSVC10 uses std::_Vector_iterator. But make no mistake, these classes are nothing more than very simple wrappers around the underlying pointer types, eg. for vector<int>, they simply wrap int*. Now you might think that "since they're classes, there's obviously extra overhead using them." Well not quite true. These classes are very simple classes with all of their functions defined as inline. When you have your compiler optimizations on, your compiler will inline the code in the place of the function call, which essentially results in same as using a pointer directly.

Neither is obviously faster than the other. It depends completely on the compiler's implementation, its optimizer, whether running a debug build without optimizations or release build with optimizations, et cetera. To show you what I mean, I made a simple test case:

Code: [Select]
#include <vector>
#include <boost/progress.hpp>

int main()
{
        const int entries = 100000000;

        std::vector<int> v;
        v.reserve(entries);
        for (int i = 0; i < entries; ++i) {
                v.push_back(i);
        }

        // benchmark counter
        {
                boost::progress_timer timer;
                for (int i = 0; i < entries; ++i) {
                        v[i] += 10; // do something so loop doesn't get optimized away
                }
        }

        // benchmark iterator
        {
                boost::progress_timer timer;
                for (std::vector<int>::iterator i = v.begin(); i != v.end(); ++i) {
                        *i += 10; // do something so loop doesn't get optimized away
                }
        }
}

Here's the results with GCC:
Quote
$ g++ -O3 benchmark.cpp && ./a.out
0.12 s
0.08 s
$ g++ -O0 benchmark.cpp && ./a.out
0.48 s
1.92 s
As you can see, iterators are faster with full optimization (which you would normally use when you deploy your application), but operator[] is faster without optimizing, which is simply explained by the fact that the iterator code isn't even inlined in that case, not to speak of other optimizations the compiler might make. These results will more than likely vary from compiler to compiler, and there's simply no basis to think that either iterators or counter is faster than the other. I also tested on MSVC, and the results are pretty much the same with _SECURE_SCL set to 0. By default MSVC uses a feature called "checked iterators" which adds extra security, if you want to favor speed, you can do so by turning off checked iterators by turning _SECURE_SCL to 0. Basically this is similar to the operator[] vs .at() in std::vector, except it's a global setting.

So the speed should NOT be the thing you base your decision on. I would use iterators instead of counter and operator[] for following reasons:
- Iterators are made for this very purpose, and the compiler manufacturers will try their best to optimize it for this purpose.
- If you want to deal with container's data in a forward-like manner, then iterators are the most self-documenting way to do just that (this is just my opinion of course).
- Assuming that the underlying implementation uses pointer iterators, to access the iterating element only a de-reference of a pointer is required, with array access it requires a pointer addition arithmetic operation before de-referencing.
- With other containers that don't support random access, you'd have to use iterators, and using them in this situation as well makes your code more consistent.
- In certain situations when you use .begin() and .end() it's harder to write code that accesses the container at wrong position.

If the speed is your biggest issue, then the only thing you can really do is benchmark the code on the platforms you target, and make your decision based on that. That being said, 99% of people should not care about the little speed differences there are between these two implementations.
Title: Re: C++ Lobby Lister Class
Post by: FliesLikeABrick on April 08, 2011, 08:46:20 am
Interesting, I thought that since STL vectors are implemented how they are that what I said about operator[] is true (regardless of whether iterators are the same or faster or slower)

My understanding of how STL vectors are implemented is that they use an array internally and when it is outgrown there is a new array that is created which is double the size (roughly speaking, the real implementation is more nuanced). 
Title: Re: C++ Lobby Lister Class
Post by: ramirez on April 08, 2011, 08:56:14 am
Interesting, I thought that since STL vectors are implemented how they are that what I said about operator[] is true (regardless of whether iterators are the same or faster or slower)

My understanding of how STL vectors are implemented is that they use an array internally and when it is outgrown there is a new array that is created which is double the size (roughly speaking, the real implementation is more nuanced). 
Yeah, that is how a vector is usually implemented, but however as usual the standard doesn't force the compiler to do it this exact way. The one thing that the standard specifies is that "vector must be a contiguous area of memory".
Title: Re: C++ Lobby Lister Class
Post by: pubby8 on April 08, 2011, 09:14:22 pm
Hm, very interesting how iterators can produce faster code, however I wanted to point out that the most likely increase in speed you saw in your example was because of cache usage. If you switch the tests around, you will find that iterators are slightly slower if the test code was put before the non-iterator code.

I do agree that vector iterators should be used, but I think most people overuse vectors, and iterators overall.
Title: Re: C++ Lobby Lister Class
Post by: Clawbug on April 09, 2011, 03:10:05 am
Hm, very interesting how iterators can produce faster code, however I wanted to point out that the most likely increase in speed you saw in your example was because of cache usage. If you switch the tests around, you will find that iterators are slightly slower if the test code was put before the non-iterator code.

I do agree that vector iterators should be used, but I think most people overuse vectors, and iterators overall.

How can people overuse vectors or iterators in C++? STL containers are more or less meant to be used instead of old-fashioned plain array data structures, and iterators are meant to be used for iterating through them. It's kind of like std::string vs. C-string thing; in C++ using good ol' C strings is more or less considered bad practice(error prone, not always clear, POINTERS yuck!) because you've got std::string. Of course old C strings are perfectly valid, but I'd guess that it's more because of better backward compatibility with C and it's legacy rather than as an practical language feature.

I myself use STL containers as much as possible, and try to use high level features of C++ whenever possible instead of doing things in the "good old C way", even though I am much bigger fan of C than C++. After all, they're two distinct languages.
Title: Re: C++ Lobby Lister Class
Post by: ramirez on April 09, 2011, 09:31:19 am
Hm, very interesting how iterators can produce faster code, however I wanted to point out that the most likely increase in speed you saw in your example was because of cache usage. If you switch the tests around, you will find that iterators are slightly slower if the test code was put before the non-iterator code.
The results stay the same even after swapping them with GCC 4.45, that is not the reason. As I explained they boil down to simple pointers, THAT is the reason why they're faster.
Title: Re: C++ Lobby Lister Class
Post by: pubby8 on April 09, 2011, 01:36:48 pm
Quote
How can people overuse vectors or iterators in C++? STL containers are more or less meant to be used instead of old-fashioned plain array data structures, and iterators are meant to be used for iterating through them. It's kind of like std::string vs. C-string thing; in C++ using good ol' C strings is more or less considered bad practice(error prone, not always clear, POINTERS yuck!) because you've got std::string. Of course old C strings are perfectly valid, but I'd guess that it's more because of better backward compatibility with C and it's legacy rather than as an practical language feature.

Because people misuse the STL/STD all the time:
not using reserve
using push_back when there is no need to
improper use of temporary objects (c_str is very commonly misused)
iterator problems and quirks
using wrong algorithm/container

C library has just as many problems as C++ does, I just find it silly when people treat C++'s library as a holy scripture, and never write their own containers classes.

Quote
The results stay the same even after swapping them with GCC 4.45, that is not the reason. As I explained they boil down to simple pointers, THAT is the reason why they're faster.
I'm definitely getting a difference on the order, dunno why I am and you are not.

And you can easily change your code to:
Code: [Select]
                for (int* i = va; i < &va[100000000]; ++i) {
                        *i += 10; // do something so loop doesn't get optimized away
                }
I find this more readable than the iterator code.

But it is all personal preference, so don't take what I say as argument, just as discussion   :)

Title: Re: C++ Lobby Lister Class
Post by: ramirez on April 11, 2011, 04:43:24 am
And you can easily change your code to:
Code: [Select]
                for (int* i = va; i < &va[100000000]; ++i) {
                        *i += 10; // do something so loop doesn't get optimized away
                }
I find this more readable than the iterator code.

But it is all personal preference, so don't take what I say as argument, just as discussion   :)
That is just terrible, no offense. No C++ programmer in their right mind would code like that, that looks like something a C programmer that just started C++ would do. And while we're on the subject of aesthetics, in C++0x you can actually do this with iterators, which is much nicer:

Code: [Select]
for (auto i = v.begin(); i < v.end(); i++) { ... }
The auto keyword will deduce the type from the expression, in this case std::vector<int>::iterator; this is already supported in MSVC2010 and latest GCC versions.
Title: Re: C++ Lobby Lister Class
Post by: iDante on April 11, 2011, 05:23:17 am
Will auto acquire some new usefulness in C++0x?

Also jrgp you really don't need that much commenting. I'm normally a proponent of heavy comments but several of these made me cry a little bit.
Code: [Select]
// Result stored here
vector<std::string> result;

// Give
return result;

// Store actual servers here
vector<server_entry> servers;
etc.

Shoutout to ramirez btw, your posts are always really awesome and informative :)
Title: Re: C++ Lobby Lister Class
Post by: ramirez on April 11, 2011, 05:42:08 am
Will auto acquire some new usefulness in C++0x?
Well all it really does is simplify your code quite a bit. You can see the usefulness in using auto instead of say, std::map<std:.string, std::vector<int>>::iterator ;)
Another good example is that if you want to eg. store a lambda function in 0x, it's much easier with the auto keyword, eg:
Code: [Select]
auto func = [](int x, int y) { return x + y; };
Title: Re: C++ Lobby Lister Class
Post by: pubby8 on April 11, 2011, 01:30:20 pm
And you can easily change your code to:
Code: [Select]
                for (int* i = va; i < &va[100000000]; ++i) {
                        *i += 10; // do something so loop doesn't get optimized away
                }
I find this more readable than the iterator code.

But it is all personal preference, so don't take what I say as argument, just as discussion   :)
That is just terrible, no offense. No C++ programmer in their right mind would code like that, that looks like something a C programmer that just started C++ would do. And while we're on the subject of aesthetics, in C++0x you can actually do this with iterators, which is much nicer:

I don't see why that code is so "terrible" - it's very clear and simple.
In my opinion, if you want a language where you avoid pointers, memory, and anything slightly c-like, then go use java.



Title: Re: C++ Lobby Lister Class
Post by: ramirez on April 11, 2011, 04:33:05 pm
For various reasons:

1) It's not consistent with the concept called iterators in C++, it'll not work for other containers that are non-sequential; you should try to keep consistent. This is C++, not C, use the facilities that C++ provide you. That method is pretty much only guaranteed to work with vector (actually it's not even valid for vector, but it could be by changing it a bit, see next reason).

2) That is actually defined as undefined behavior per standard when you run that code; you're accessing the array outside of its boundaries. It most likely works on most compilers, but the fact is that accessing outside the array's boundary. The proper way would be i < &va[0]+100000000 or i <= &va[99999999].

3) You're using a magic number, you probably meant to use va.size() instead of that 100000000.

4) In case you want it, you're not taking advantage of your compiler's some features, for instance MSVC has a feature called checked iterators (http://msdn.microsoft.com/en-us/library/aa985965(v=vs.80).aspx) that add extra security to them. This is arguable though, since checked iterators actually have a bit of an overhead to them, so if you care more about speed than safety, you would turn these off anyways.

So basically, iterators are generally safer and more consistent. If you get used to iterators, like you should, then you don't need to guess "how should I iterate this type of container", since every container would be iterated through similarly. There's no other way to iterate through some container's than the standard library iterators, take for example a list or a set or a map. Get used to the iterators everywhere.

Btw another fun fact about C++0x, it includes a feature called range-based for loop, which is essentially a foreach loop similar from other languages. It allows you to iterate containers (as well as regular arrays) like this:

Code: [Select]
for (int& x: va) {
    x += 10; // we're iterating by reference
}

This is by far the simplest and cleanest way to iterate a container.
Title: Re: C++ Lobby Lister Class
Post by: pubby8 on April 11, 2011, 05:33:55 pm
Oh, I think there is misunderstanding.
That code was being used on a normal array, not on a vector (that is why I renamed it "va" (a for array) and not "v")

Quote
2) That is actually defined as undefined behavior per standard when you run that code; you're accessing the array outside of its boundaries. It most likely works on most compilers, but the fact is that accessing outside the array's boundary. The proper way would be i < &va[0]+100000000 or i <= &va[99999999].
I see what you are saying, but &va[0]+100000000 could also be problematic if it happened to overflow (very  very unlikely)

Quote
3) You're using a magic number, you probably meant to use va.size() instead of that 100000000.
Here is another reason why I dislike vectors - they store additional values such as size and reserved size. 90% of arrays I need are a constant size. If it was actual code, of course there wouldn't be a magic number in there, but it was a test snippet so I hope you understand the purpose of it was not about use of magic numbers.

Quote
4) In case you want it, you're not taking advantage of your compiler's some features, for instance MSVC has a feature called checked iterators that add extra security to them. This is arguable though, since checked iterators actually have a bit of an overhead to them, so if you care more about speed than safety, you would turn these off anyways.
If iterators are so safe and consistent, why are there "checked iterators" then?

Quote
So basically, iterators are generally safer and more consistent. If you get used to iterators, like you should, then you don't need to guess "how should I iterate this type of container", since every container would be iterated through similarly. There's no other way to iterate through some container's than the standard library iterators, take for example a list or a set or a map. Get used to the iterators everywhere.
You should be thinking about "how should I iterate this container," as it can be very critical to your performance. Especially since STL wasn't designed for threading.

I've used the STL a great deal a while ago, but I found it limiting. I rewrote my code that was using it and actually got ~7 times performance improvement. It still remained readable, it was largely OO, and I didn't have to write too much code. You don't need to have some oversimplified helper library to hold your hand to get stuff done in a good way.
/rant

Title: Re: C++ Lobby Lister Class
Post by: ramirez on April 11, 2011, 06:13:35 pm
Oh, I think there is misunderstanding.
That code was being used on a normal array, not on a vector (that is why I renamed it "va" (a for array) and not "v")
Okay, that was indeed confusing, you should have said so, just changing a name of a variable is not enough to jump from one topic to another. Last I checked we were discussing about the C++ standard library iterators here.

Quote
I see what you are saying, but &va[0]+100000000 could also be problematic if it happened to overflow (very  very unlikely)
That obviously depends on the size of the array.. If it has 100000000  elements, then doing &va[0]+100000000 is same as &va[100000000], there's no difference, it is not "very very unlikely" that one would overflow but other would not. I don't understand how this is relevant to the discussion at hand in anyway.

Quote
Here is another reason why I dislike vectors - they store additional values such as size and reserved size. 90% of arrays I need are a constant size. If it was actual code, of course there wouldn't be a magic number in there, but it was a test snippet so I hope you understand the purpose of it was not about use of magic numbers.
Those "additional values" are what makes them possible in the first place. If 90% of your arrays are of static size, you probably code way differently than I do (and I don't disagree btw, if your arrays are static size, there's not much point using vector then). But that is beyond the whole argument here, we were not talking about variable length arrays vs static length arrays, we were discussing the C++ standard library iterators, and how standard containers should be iterated.

In terms of additional overhead things like keeping track of the size; it's not much. What's expensive though is that if the vector goes over its reserved capacity, since it'll need to copy the data to a new location in that case (C++0x has a nifty feature called move semantics, that make copying larger objects that are being destructed after the copy much faster!) Once again a good C++ programmer is aware of this, and knows to reserve space for his vector when necessary.

Quote
If iterators are so safe and consistent, why are there "checked iterators" then?
They're mostly useful for finding bugs in your code. For example normally if you try to use an uninitialized iterator or one that has gone beyond the bounds of the container you'll get undefined behavior; you might spot the error or you might not. It might not happen for you, but it might happen to some of your users. With checked iterators you catch bugs like those much easier in your code, as they're checked and exceptions are thrown (it's mainly useful to keep on in debugging builds, for release builds and maximal speed you usually want to turn it off if you want the extra speed).

Quote
You should be thinking about "how should I iterate this container," as it can be very critical to your performance. Especially since STL wasn't designed for threading.
With most containers there is only one way to iterate the container. Also remember that the point of iterators is to, well, iterate through the container. The compiler manufacturers have taken steps to optimize the iterator code so that it'll be as fast as possible. Don't try to prematurely optimize code like this, I'm sure you've heard the saying that premature optimization is the root of all evil. ;) In matter of fact, by not understanding how iterators really work, you can actually write more inefficient code than just trusting your compiler and its optimizer (as I showed before). I won't even start on talking about threading, as it is way off topic here, and it's actually implementation specific (there are thread safe implementations of the library).

Quote
I've used the STL a great deal a while ago, but I found it limiting. I rewrote my code that was using it and actually got ~7 times performance improvement. It still remained readable, it was largely OO, and I didn't have to write too much code. You don't need to have some oversimplified helper library to hold your hand to get stuff done in a good way.
I don't believe that. I would like to see some benchmarks and code where you custom written containers/code is 7 times faster. What is more likely is that you misused the standard library and used wrong containers for wrong things (it's essential to understand how each container works so you can use it for the purpose it was meant for), or perhaps you did your benchmarks using debug builds instead of release builds (as I demonstrated before, the containers/iterators are quite a bit faster in release builds due to optimizations taking place). Also note that the C++0x has new containers that are better for certain things, such as std::unordered_map (basically a hashmap), before C++0x most people prefer to use boost to get access to these useful containers (why reinvent the wheel right? boost containers follow the format of stdlib containers as in they're iteretable and compatible with the stdlib algorithms, and they are thoroughly tested and optimized). But I'm willing to be proven wrong, but I don't take your word for it. I want to see code and benchmarks, I'm sure you understand my skepticism of you being able to write ~7 times faster code than the people who write these compilers for living and know C++ and inside and out, plus how to optimize their code for their own compiler.

PS. It is confusing to call the standard library STL, and is not quite accurate. You might want to consider calling it C++ standard library, or stdlib, either, see the first answer here to as of why: http://stackoverflow.com/questions/5205491/whats-this-stl-vs-c-standard-library-fight-all-about
Title: Re: C++ Lobby Lister Class
Post by: pubby8 on April 12, 2011, 02:28:10 pm
Quote
That obviously depends on the size of the array.. If it has 100000000  elements, then doing &va[0]+100000000 is same as &va[100000000], there's no difference, it is not "very very unlikely" that one would overflow but other would not. I don't understand how this is relevant to the discussion at hand in anyway.
I was just saying that &va[0]+9999999 seemed better.

Quote
In terms of additional overhead things like keeping track of the size; it's not much. What's expensive though is that if the vector goes over its reserved capacity, since it'll need to copy the data to a new location in that case (C++0x has a nifty feature called move semantics, that make copying larger objects that are being destructed after the copy much faster!) Once again a good C++ programmer is aware of this, and knows to reserve space for his vector when necessary.
That overhead may not seem like much when you are testing 1 vector, but since you will likely have 1000s of vectors in actual code, the overhead will become noticeable. Not a big problem, but it makes a lot of sense to use arrays when you can.

Quote
They're mostly useful for finding bugs in your code. For example normally if you try to use an uninitialized iterator or one that has gone beyond the bounds of the container you'll get undefined behavior; you might spot the error or you might not. It might not happen for you, but it might happen to some of your users. With checked iterators you catch bugs like those much easier in your code, as they're checked and exceptions are thrown (it's mainly useful to keep on in debugging builds, for release builds and maximal speed you usually want to turn it off if you want the extra speed).
Yeah, those features are helpful. They work for normal arrays too though, like valgrind.

Quote
I don't believe that. I would like to see some benchmarks and code where you custom written containers/code is 7 times faster. What is more likely is that you misused the standard library and used wrong containers for wrong things (it's essential to understand how each container works so you can use it for the purpose it was meant for), or perhaps you did your benchmarks using debug builds instead of release builds (as I demonstrated before, the containers/iterators are quite a bit faster in release builds due to optimizations taking place). Also note that the C++0x has new containers that are better for certain things, such as std::unordered_map (basically a hashmap), before C++0x most people prefer to use boost to get access to these useful containers (why reinvent the wheel right? boost containers follow the format of stdlib containers as in they're iteretable and compatible with the stdlib algorithms, and they are thoroughly tested and optimized). But I'm willing to be proven wrong, but I don't take your word for it. I want to see code and benchmarks, I'm sure you understand my skepticism of you being able to write ~7 times faster code than the people who write these compilers for living and know C++ and inside and out, plus how to optimize their code for their own compiler.
While vector obviously isn't 7 times slower, stuff like list and map are not optimal in most cases. One algorithm I got big speed improvements was a LRU caching one - I originally used a list, and also tried a map+list, but by rewriting it using a custom hash table that uses a linked list with 4 pointers per node, and a custom stack-based allocator, I got massive improvements.




Title: Re: C++ Lobby Lister Class
Post by: ramirez on April 12, 2011, 05:49:05 pm
While vector obviously isn't 7 times slower, stuff like list and map are not optimal in most cases. One algorithm I got big speed improvements was a LRU caching one - I originally used a list, and also tried a map+list, but by rewriting it using a custom hash table that uses a linked list with 4 pointers per node, and a custom stack-based allocator, I got massive improvements.
You can't really compare that. You wrote an entirely different kind of container and compared it to another kind of container. All that really shows is that hashmap was a better container than a sorted map for that situation. You should have used std::unordered_list or boost::hash_map in the first place if you needed hash map. But writing your own is understandable if you don't want to depend on boost and you didn't use 0x, or you needed some special features.

Btw std::map insertions are a lot faster if you know where in the container you insert it, and give a hint iterator to the .insert() function, and by a lot I mean it can easily be up to 5-10 times faster, or even more, depending on the size of the map.
Title: Re: C++ Lobby Lister Class
Post by: pubby8 on April 12, 2011, 08:02:35 pm
Quote
You can't really compare that. You wrote an entirely different kind of container and compared it to another kind of container.
I converted a list and an associative array into a list and an associative array. Yes, it did go from a RB-tree to a hash table, but map and list was the correct containers if using strictly standard library.

If you think boost::hash_map could get better performance, would you be willing to test it and write code that performs the same thing that mine does? I can give you the details if you are willing to do so.

Quote
Btw std::map insertions are a lot faster if you know where in the container you insert it, and give a hint iterator to the .insert() function, and by a lot I mean it can easily be up to 5-10 times faster, or even more, depending on the size of the map.
Yes, but there are few cases where you would iterate through a map, and then need to insert while iterating.


Title: Re: C++ Lobby Lister Class
Post by: VirtualTT on April 22, 2011, 09:49:37 am
The first thing is that res variable upon successful call to getaddrinfo() points to the first node of the linked-list of addrinfo structs (you must later call freeaddrinfo() with this first node). So you should loop through this list and try to create socket with each struct and try to connect it while currentaddrinfo->ai_next != NULL instead of trying to connect using only the first node.

Also under windows you should prefer WSAGetLastError() to get error codes.