|
Hello,
RE: Quote: I would suggest you create a basic Windows application from the Win32 app template that comes with Visual Studio, and then add your socket code to it.
That puzzles me a bit. My end result for this code is a class that can be included in various projects as opposed to a stand alone application. I cannot see very far down this path yet so will this method yield the results I want? Will I be able to just simply instantiate the class in a new project and have all that is needed for a TCP/IP link with another application/computer?
Thanks for your time
If you work with telemetry, please check this bulletin board: http://www.bkelly.ws/irig_106/
|
|
|
|
|
bkelly13 wrote: Will I be able to just simply instantiate the class in a new project and have all that is needed for a TCP/IP link with another application/computer? Quite possibly, but you still need to get it working first. My suggestion was to create a simple application in which to build and test your class. Once you have it all working you can convert your class into a library which can be used by other people.
Veni, vidi, abiit domum
|
|
|
|
|
OK, I am going down that path, but I still see two parallel but close roads to take.
1. Write my TCP/IP class and find the handle to the main application and pass that to the class for the WndProc method.
2. Create any type of app/template in Visual studio, create a TCP/IP class, and use the CreateWindowEx(...) to create a new window. Make that window hidden and use it only to catch the TCP/IP messages.
From my perspective the second makes much more sense. If I create a new window from within the TCP/IP class then it does not need to capture message from the main app, or alternative, the main app does not need to tell the class about the messages received.
Thanks for your time
If you work with telemetry, please check this bulletin board: http://www.bkelly.ws/irig_106/
|
|
|
|
|
I guess you have to try it and see which works best.
Veni, vidi, abiit domum
|
|
|
|
|
Yes. I am working on a tutorial on the basic window and messaging (again) to try to get that right before I try to make it work with a specific class. This will take a bit.
Thanks for taking the time to converse and advise me on this.
Thanks for your time
If you work with telemetry, please check this bulletin board: http://www.bkelly.ws/irig_106/
|
|
|
|
|
You do not need a window, or a message pump, if you use Winsock2 (see Creating a Basic Winsock Application[^] and it's following articles).
Call socket to create a listening socket, bind it to the host address, set it to be non-blocking with ioctlsocket , and set it to listen with listen . Once listening, accept incoming connections and foist the resulting socket off to its own thread where it can receive data using recv . If there's nothing to accept, sleep for a bit and loop around.
Simple.
(I'd post proper code if I had the right to do so. This is reading from an implementation I wrote for $EMPLOYER a couple of years ago. Somewhere at home I have the code I wrote for myself many years ago, and I'll try to dig it out, write it up, and post it one of these days.)
Alternatively, have you had a look at boost::asio[^]?
|
|
|
|
|
Cool. I will be working that concept.
Thank you for taking the time to post.
Thanks for your time
If you work with telemetry, please check this bulletin board: http://www.bkelly.ws/irig_106/
|
|
|
|
|
Hi guys,
I did some performance comparison between MFC and STL containers and I think maybe it could evolve into an article here at Codeproject. Please have a look at my code and suggest some improvements to make comparison more valid. So far I found that STL still sucks big time even after 10 or 15 years of polishing (and neglecting of MFC) in VS2012. Following is complete source code, just drop it into console project with MFC support, compile and run in Release mode.
#include "stdafx.h"
#include "MFCvsSTL.h"
#include <unordered_map>
#include <map>
#include <vector>
#include <list>
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
CWinApp theApp;
using namespace std;
typedef unordered_map<DWORD, void*> stlmap;
int stlMap(int nCount)
{
int nSize = (int)(1.2 * (float)nCount);
stlmap a(nSize);
for( int i = 0; i < nCount; ++i )
{
a[ i ] = (void *) i;
}
stlmap::iterator iter;
for( int j = 0; j < nCount; ++j )
{
iter = a.find( ( abs( rand() * j ) % nCount ) );
}
return 1;
}
int mfcMap(int nCount)
{
int nSize = (int)(1.2 * (float)nCount);
CMap<DWORD, DWORD, void*, void*> a;
a.InitHashTable( nSize );
for( int i = 0; i < nCount; ++i )
{
a[ i ] = (void *) i;
}
void * val;
for( int j = 0; j < nCount; ++j )
{
a.Lookup( ( abs( rand() * j ) % nCount ), val );
}
return 0;
}
int stlArray(int nCount)
{
vector <int> bigarray;
int nMs = bigarray.max_size();
try
{
bigarray.reserve(nCount);
}
catch (...)
{
CString str;
str.Format(_T("Memory allocation error trying to reserve %d elements. vector.max_size=%d\r\n"), nCount, nMs);
_tprintf(str);
return 0;
}
for(int k = 0; k < nCount; ++k)
{
bigarray.push_back(k);
}
int ret = bigarray.size();
return ret;
}
int mfcArray(int nCount)
{
CUIntArray arr;
arr.SetSize(0, nCount);
for(int k = 0; k < nCount; ++k)
{
arr.Add(k);
}
int ret = arr.GetCount();
return ret;
}
int mfcList(int nCount)
{
CList<int, int> a;
for(int k = 0; k < nCount; ++k)
{
a.AddHead(k);
}
for( int j = 0; j < nCount; ++j )
{
int n = abs(rand() * j ) % nCount;
POSITION pos = a.Find(n);
}
return 1;
}
int stlList(int nCount)
{
list<int> mylist;
for(int k = 0; k < nCount; ++k)
{
mylist.push_front (k);
}
for( int j = 0; j < nCount; ++j )
{
int n = abs(rand() * j ) % nCount;
std::list<int>::iterator findIter = std::find(mylist.begin(), mylist.end(), n);
}
return 1;
}
class CTimeHelper2013
{
public:
SYSTEMTIME m_st1;
SYSTEMTIME m_st2;
BOOL m_bStarted;
int Start();
int DiffMS();
CTimeHelper2013();
virtual ~CTimeHelper2013();
};
int timeMFCl(int nCount)
{
CTimeHelper2013 th;
th.Start();
mfcList(nCount);
return th.DiffMS();
}
int timeSTLl(int nCount)
{
CTimeHelper2013 th;
th.Start();
stlList(nCount);
return th.DiffMS();
}
int timeMFCv(int nCount)
{
CTimeHelper2013 th;
th.Start();
mfcArray(nCount);
return th.DiffMS();
}
int timeSTLv(int nCount)
{
CTimeHelper2013 th;
th.Start();
stlArray(nCount);
return th.DiffMS();
}
int timeMFCh(int nCount)
{
CTimeHelper2013 th;
th.Start();
mfcMap(nCount);
return th.DiffMS();
}
int timeSTLh(int nCount)
{
CTimeHelper2013 th;
th.Start();
stlMap(nCount);
return th.DiffMS();
}
int testHash(int nCount)
{
int d2 = timeSTLh(nCount);
int d1 = timeMFCh(nCount);
CString str;
str.Format(_T("CMap vs unordered_map. Fill & find %d elements. MFC (%d)ms STL (%d)ms\r\n"), nCount, d1, d2);
_tprintf(str);
return 1;
}
int testArray(int nCount)
{
int d2 = timeSTLv(nCount);
int d1 = timeMFCv(nCount);
CString str;
str.Format(_T("CArray vs vector. Fill %d elements. MFC (%d)ms STL (%d)ms\r\n"), nCount, d1, d2);
_tprintf(str);
return 1;
}
int testList(int nCount)
{
int d2 = timeSTLl(nCount);
int d1 = timeMFCl(nCount);
CString str;
str.Format(_T("CList vs list. Fill & find %d elements. MFC (%d)ms STL (%d)ms\r\n"), nCount, d1, d2);
_tprintf(str);
return 1;
}
void perf_startup()
{
SetThreadAffinityMask(GetCurrentThread(), 1);
SetThreadIdealProcessor(GetCurrentThread(), 0);
Sleep(1);
}
CTimeHelper2013::CTimeHelper2013()
{
m_bStarted = 0;
}
CTimeHelper2013::~CTimeHelper2013()
{
}
int CTimeHelper2013::Start()
{
GetLocalTime(&m_st1);
m_bStarted = 1;
return 1;
}
int CTimeHelper2013::DiffMS()
{
GetLocalTime(&m_st2);
m_bStarted = 0;
int nRet1 = m_st2.wMilliseconds - m_st1.wMilliseconds;
int nRet2 = m_st2.wSecond - m_st1.wSecond;
int nRet3 = m_st2.wMinute - m_st1.wMinute;
int nRet4 = m_st2.wHour - m_st1.wHour;
int nRet5 = m_st2.wDay - m_st1.wDay;
int nRet6 = m_st2.wMonth - m_st1.wMonth;
int nRet7 = m_st2.wYear - m_st1.wYear;
int nRet = 0;
nRet += nRet1;
nRet += nRet2 * 1000;
nRet += nRet3 * 1000 * 60;
nRet += nRet4 * 1000 * 60 * 60;
nRet += nRet5 * 1000 * 60 * 60 * 24;
nRet += nRet6 * 1000 * 60 * 60 * 24 * 30;
nRet += nRet7 * 1000 * 60 * 60 * 24 * 365;
return nRet;
}
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
HMODULE hModule = ::GetModuleHandle(NULL);
if (NULL == hModule != NULL)
{
_tprintf(_T("Fatal Error: GetModuleHandle failed\n"));
return 1;
}
if (!AfxWinInit(hModule, NULL, ::GetCommandLine(), 0))
{
_tprintf(_T("Fatal Error: MFC initialization failed\n"));
return 2;
}
_tprintf(_T("MFC vs STL performance test\n"));
perf_startup();
testList(1000 * 10);
testList(1000 * 100);
testList(1000 * 200);
testArray(1000 * 100);
testArray(1000 * 1000);
testArray(1000 * 1000 * 200);
testHash(1000 * 100);
testHash(1000 * 1000);
testHash(1000 * 1000 * 20);
return nRetCode;
}
|
|
|
|
|
|
Exactly why? I can't believe I am violating something.
|
|
|
|
|
To me this simply doesn't seem to be a question and posting code bloat is not really valid on CP I think.
MFC containers: Read this: http://stackoverflow.com/questions/1348078/why-stl-containers-are-preferred-over-mfc-containers[^]
MFC containers vs stl containers: stl is highly portable. The MFC/ATL CString is often better. And we could list pros and contras but I would suggest using stl because it is portable across platforms/compilers...
None of these containers are perfect. They are still OK for 99% of average user applications because performance really doesn't matter in most applications. The threads of an average program spend most of their time sleeping and waiting for IO so the heavy weightlifting is done by the OS and not by the containers compiled into a program.
In far less then 1% of the cases when performance or memory usage matters often none of the above solutions are OK and in that case you have to write your own container specialized for an edge case. For example what do you do if you want a vector that doesn't allocate capacity for 16 items by default even if its empty? Or if you want a vector that takes only the space of a null pointer when empty (because you want to have a lot of vectors and most of them will be empty)?
I wouldn't waste my time comparing the efficiency of two general-purpose container libraries for the reasons mentioned above, especially because you use general-purpose containers usually when performance/memory usage isn't a terrible issue. If you have issues then you circumvent them either by changing your algorithm/memory access to help the general-purpose container library to perform better or by providing custom allocators or as a last resort by writing your own.
|
|
|
|
|
What I asked is to verify if my code is correct and maybe suggest how to make it more valid.
I still remember claims how "highly portable", "highly standard" and "very fast" STL was back in 1999, this is really not what I was asking.
|
|
|
|
|
I never liked this kind of comparison of containers, it is not very useful partly because of the reasons I mentioned in my previous post. Different real-world scenarios can put stress on a container in a thousand different ways.
|
|
|
|
|
Alexander Fedorov wrote: What I asked is to verify if my code is correct and maybe suggest how to make it more valid. I think you will find that CodeProject members do not offer this service.
Veni, vidi, abiit domum
|
|
|
|
|
I can't comment on map/list but if the MFC array type is performing faster than an STL vector or a built in array I'd be very suspicious of what I'd written. In your vector code the push_back and exception handling (which you haven't got for the MFC case) would be my first targets for a good hard look.
|
|
|
|
|
Good point. Exception handling actually does not add anithing to the timing, because its just 1 large function that wrapped in it. I just was wondering why I cannot allocate 500M array while vectors.max_siz says it can do over 1G so basically its a leftover from some debugging. MFC CArray is actually only container that I found is 4-5 times slower than STL vector with or without try-catch block. Maybe if I add array random access to the test MFC will be winning?
|
|
|
|
|
I'm now surprised that the MFC array is so slow - I'd have thought built in, vector and CArray would all be about the same speed. I doubt adding random access will change much, provided you don't change the size a std::vector should be as fast as a built in array for random access.
|
|
|
|
|
Its only noticeably slower on really large arrays, like hundred millions of elements, probably because CArray doing unnecessary stuff like zeroing memory before using it.
|
|
|
|
|
I tried using std::map in an application that handles telemetry data. When it was not working I tried stepping into a simple call to fetch data from the map. After 100+ calls without the data I concluded the problem had been found. When the map was replaced with a simple array, the application ran with a very low CPU load.
The std::map is easy to use and a great way to get the program fundamentals right while trying to ignore the data storage problem. If speed is needed, a general and generic problem that can handle any type of data will be inherently much slower.
My conclusion: the template libraries are really cool and easy to use, but very inefficient.
Thanks for your time
If you work with telemetry, please check this bulletin board: http://www.bkelly.ws/irig_106/
|
|
|
|
|
bkelly13 wrote: My conclusion: the template libraries are really cool and easy to use, but very inefficient.
Well this is not really an accurate statement, because it depends on the template library that you're using and it's implementation and whether your use fits in with the standard use that it was designed for. std::map containers are never going to be fast, so in your case, just about any other container would have been faster. All in all, you can likely make something that is just as fast or faster than any container because you can make it application specific (you know how much data you need and how it will be accessed), but that doesn't discount the use of template libraries.
|
|
|
|
|
When you're choosing a container choose a vector. They're (except for one case) as fast as an equivalent automatic array. Then if you find the interface or performance characteristics of something else works better you can change it later.
|
|
|
|
|
Well... although a dynamically growing vector will still be slower than a pre-allocated array. Although you can presize a vector as well but that would require you to know about the speed cost of dynamic allocation and how vectors allocate arrays internally. Guess what I'm getting at is... you have to know at least a little about your containers and how you're using them.
In summary, no free ride. 
|
|
|
|
|
Could anyone please help me to find why call to sort() is crashing at run-time in following code block:
string s = "Annnitttesrrh.";
vector<char> vecChar(s.begin(), s.end());
sort(vecChar.begin(), vecChar.end(), greater_equal<char>());
Am i missing something very basic ?
|
|
|
|
|
|
I think that equality don't work in sort. Why swap elements if they are equal?
|
|
|
|