C++ Middleware Writer

W

woodbrian77

Perhaps you will say what you find clear or confusing about
the site. Someone mentioned this page

http://webEbenezer.net/build_integration.html

was like a "foreign language." Maybe if you feel the same
you could make a suggestion. There's also a lot of open-
source code available on that page and from the on line
code generator. Any of that could be discussed.

In the Name of the G-d of Abraham, Isaac, and Israel,
thank you for your help.
 
V

Victor Bazarov

This file,
http://webEbenezer.net/misc/cmwAmbassador.cc

has 338 lines and 11 functions at the moment.
Most of the functions are less than 20 lines
long, but the constructor is 104 lines long.
The ctor has the event loop. Is it too long?

The ctor is difficult to read. A bunch of local variables. A bunch of
weird macros (FD_ZERO, FD_SET - can't you do initialization of your
variables without those?). And above all - the infinite loop that after
a minute of looking at it was *unclear how or where it terminates*.

Perhaps I'm going to sound strange, but it always seemed to me that
c-tors should be short and sweet, and all other processing ought to be
given to other functions, split into logical areas (you have three 'try'
blocks in that loop, each could probably be in its own function), and
called from the 'init' kind of function... <shrug> But that's a style
topic, of course, just like the size of a function...

V
 
W

woodbrian77

The ctor is difficult to read. A bunch of local variables. A bunch of

weird macros (FD_ZERO, FD_SET - can't you do initialization of your

variables without those?). And above all - the infinite loop that after

a minute of looking at it was *unclear how or where it terminates*.

That's the event loop of a server. It doesn't terminate
unless there's an exception at a high level.
 
W

woodbrian77

FD* macros are part of the defined API for the select system call.



that said, the op should probably use poll(2) instead of select(2).

It has been several years since I considered using poll
and I don't remember why I didn't use it. It may have
been it wasn't as portable as select.
 
W

woodbrian77

On Friday, August 17, 2012 1:03:27 PM UTC-5, Scott Lurndal wrote:
FD* macros are part of the defined API for the select system call. that said, the op should probably use poll(2) instead of select(2).

I switched to using poll now. Doing so shaved 15 lines
from the program and about 500 bytes off the size of the
executable on Linux. It would have been 16 lines but I
needed this
#define poll WSAPoll
on Windows.

It looked like I would also need
#define pollfd WSAPOLLFD
but at least here on Windows 7 that isn't needed.

I haven't checked any run time performance results, but
it is working on Linux and Windows. The constructor is
now 96 lines.
 
Ö

Öö Tiib

Shalom



Can you give me some suggestions to improve the

C++ Middleware Writer? http://webEbenezer.net

Looking at your site it seems that your software generates serialization code automatically ... but what code? IOW i miss some easy explanation what serialization problems exactly that generated stuff addresses and how and inwhat "tier" of yours. Also ... what problems it ignores or fails to address and leaves up to users? Our FAQ is good source of inspiration how to discuss it in depth (http://www.parashift.com/c++-faq-lite/serialization.html).If boost::serialization is 1.5 times slower or quicker does not really matter much, since i don't use that either.

For me the key problem of serialization (that is often unsolved) is that software evolves. At least successful software. With it evolves the data thatit has to say (or serialize).

On the other hand the users of software do not usually evolve as quick as the software. Some tend to keep old version for decades. More so when the data is serialized into some file to be archived by user for a case. Rather old version gems may turn out of user's archives and become suddenly actual such way. Software developers who might make software that exchanges data (serializes/deserializes) with your software are no different from other users. Here will always be someone posting that he uses past millennium compiler Visual C 6.0 and has some trouble.

Therefore there is huge desire to keep newer versions compatible with olderversions (and third party auxiliaries). That is quite complex problem. Forexample XML-based serialization may solve it partially so that older software just ignores unknown tags and attributes that it does not know of and newer version assumes some defaults if the tags and attributes are missing.
 
W

woodbrian77

Looking at your site it seems that your software generates serialization code automatically ... but what code? IOW i miss some easy explanation whatserialization problems exactly that generated stuff addresses and how and in what "tier" of yours. Also ... what problems it ignores or fails to address and leaves up to users? Our FAQ is good source of inspiration how to discuss it in depth (http://www.parashift.com/c++-faq-lite/serialization.html). If boost::serialization is 1.5 times slower or quicker does not really matter much, since i don't use that either.

The documentation needs work.

The generated code is based on user input. This input:

http://webEbenezer.net/misc/cmw.req
http://webEbenezer.net/misc/remote.mdl

results in this output:

http://webEbenezer.net/misc/remote_messages_middle.cg.hh
http://webEbenezer.net/misc/remote_messages_middle.cg.cc


I've discussed support for multiple versions here and
in other forums and agree that it's a difficult problem.


To the best of my knowledge the C++ Middleware Writer
was the first on line code generator. For years there's
also been an on line PHP code generator. Lately I
noticed an on line Java code generator --
http://www.springfuse.com
 
W

Werner

The ctor has the event loop. Is it too long?

Personally, I don't think it's intuitive (and its
contra-convention) to put the event loop in the
constructor. I would rather perform all
initialization in the constructor, and have the
user call a member function to commence the service.

try
{
CmwAmbassador cmwAmbassador;
cmwAmbassador.run();
}
catch( std::exception const &ex )
{
//...
}
 
8

88888 Dihedral

It has been several years since I considered using poll

and I don't remember why I didn't use it. It may have

been it wasn't as portable as select.

Polling is used for those low cost processors in low cost systems
which do not have a complete set of bios services to support fast
interrupt handlings.
 
W

woodbrian77

On Tuesday, August 21, 2012 2:49:35 AM UTC-5, 88888 Dihedral wrote:
Polling is used for those low cost processors in low cost systems which do not have a complete set of bios services to support fast interrupt handlings.

I've read that poll is slower than some of the
atlernatives. It may be fast enough though and
I'd rather minimize the dependencies. Currently
everything needed is in the archive. This server
(the middle tier) is expected to run on a lan.
A large company might have to maintain several
instances of it. The back tier uses epoll, but
portability isn't as important for that tier.

If the middle tier isn't fast enough, the next
step I'd probably take would be to make it
multithreaded. I've thought about how to do that
and don't think it would be difficult.
 
W

woodbrian77

Personally, I don't think it's intuitive (and its

contra-convention) to put the event loop in the

constructor. I would rather perform all

initialization in the constructor, and have the

user call a member function to commence the service.



try

{

CmwAmbassador cmwAmbassador;

cmwAmbassador.run();

}

catch( std::exception const &ex )

{

//...

}

Thanks. I'll think about that. I've gotten the
ctor down to 91 lines now with some refactoring.

5 of those lines are:
#ifdef CMW_ENDIAN_BIG
, byteOrder(most_significant_first)
#else
, byteOrder(least_significant_first)
#endif

There's an ifdef in the .hh file also on CMW_ENDIAN_BIG.
If Microsoft were to support initializing non static
data members in the class declaration, I could merge
those two ifdefs and get rid of 5 more lines from the ctor.

I'm still wondering if I should drop Windows support
for the middle tier. There's no encryption between
the middle and back tiers yet and in part that's because
of the effort to maintain portability. The front tier
would still be available on Windows. I don't want to
burden small companies/individuals though. Not sure how
many developers only use Windows and would not use the
software if they had to use Linux also.

Dropping Windows support would allow me to clean up
the ctor as mentioned and make it easier to add
encryption between the middle and back tiers.
 
W

woodbrian77

If you are talking about poll(2) (the system call) vs. select(2) (the system call), they

are roughly equivalent in that they perform the same operations in the kernel. poll(2) may

copyin() more bytes because the pollfd array may be larger (for some value of nfd) than the

bitmasks copied in by the select(2) system call, but once in the kernel they're roughly

the same. epoll(2) on linux has additional capabilities that can be useful, but it is non-portable.

Yes, I was talking about poll(2). I use UDP between the
front and middle tier and TCP between the middle and back
tier. There's only one TCP connection so the poll call is:

int prc = poll(fds, 2, configData.keepalive_interval);


I figured Dihedral was suggesting using an event library
rather than poll. I'm not keen on that though.
 
W

Werner

Dropping Windows support would allow me to clean up

the ctor as mentioned and make it easier to add

encryption between the middle and back tiers.

How about a drastic change (when you have time):

CW_Ambassador
- Implemented in terms of CW_AmbassadorImpl...

CW_AmbassadorImpl
- Is abstract.
- Is created by AbstractPlatformFactory as CW_Ambassador(OS)_Impl.
- Where OS can be any of the OS's in question.
- (Bridge Pattern).
- CW_Ambassador has function run, implemented in terms of CW_AmbassadorImpl.
- Run dictates (via template method pattern) everything required in terms of
virtual functions, implemented by CW_AmbassadorImpl derivative.

The user always instantiates CW_Ambassador, and is oblivious of
the factory in the back instantiating a different instance...

I've implemented sockets using IOCP (for windows) and select (VxWorks
and Linux) using this pattern. The indirection does not matter much,
because most of the functions in question are called rarely.

Also, isolate responsibilies in the long function. Give them names,
make them (virtual functions), implemented in terms of an abstract
Impl, who's true implementation is provided by the opaque factory...

Kind regards,

Werner

Kind regards,

Werner
 
W

woodbrian77

Check it out --
http://webEbenezer.net/about.html

The C++ Middleware Writer has been on line now for
ten years.

Originally the front end was a web interface --
http://webEbenezer.net/cgi-bin/samb.cgi .

That interface is no longer supported. Close to
five years ago we replaced the web interface with
a command line interface which is easy to use from
a build environment --
http://webEbenezer.net/build_integration.html .

We've received a lot of help from people here and on
some other forums including the Boost lists. Iirc,
someone on a Boost list first suggested using a
command line interface. I also had the opportunity
to meet Bjarne Stroustrup at Texas A&M and give him
a demo of the software.

It's been fun working on the software and there's still
a lot to do. One thing I raised earlier in this thread
has to do with encryption. I've not decided yet on an
encryption library. It's been a few years since I
researched C, C++ encryption libraries. Have any of
the competitors either fallen behind or improved a lot
over the past few years? A year or so ago a company
told me they use different encryption libraries on
different platforms because they couldn't find one
library that met their needs. As I mentioned earlier
I'm thinking about dropping support for Windows in the
middle tier. The front tier would still work on Windows.
Rackspace (iirc) charges about 4 times more to buy time
on a Windows server than on a Linux server. I don't want
to buy trouble and that's kind of how it seems at the
moment with servers on Windows.

If you have a comment on a matter touched on earlier
in the thread, please chime in.

The first decade has been good, and I expect the future
will be even better!


Sincerely yours,
Brian
Ebenezer Enterprises -- making programming fun again.
http://webEbenezer.net

O n e
B i g -
A s s
M i s t a k e ,
A m e r i c a
 
W

woodbrian77

I made a change to a file and am uncertain why the change
leads to a 492 byte increase in an executable.

The previous version of the file --
http://webEbenezer.net/misc/oldFormatting.hh

and the new version --
http://webEbenezer.net/misc/Formatting.hh
..

I think the only difference is the old version had
prototypes for the functions. I decided to try
removing those prototypes and giving the function
definitions within the class declaration. This is
with g++ 4.7.

I'm surprised by this result. I thought this change
wouldn't have an affect on the size of executables.
What do you recommend?

More feedback on older parts of this thread is
encouraged.


Brian
Ebenezer Enterprises -- Making programming fun again.


http://www.twincities.com/business/ci_21843208/imation-3q-revenue-off-20-percent-layoffs-coming
 
W

woodbrian77

Apparently this enabled the compiler to inline some functions which it did

not do previously. This ought to enhance performance, at some expense of

memory usage (and 492 bytes rounds to zero nowadays, to be honest). If you

are indeed wanting to optimize for size, there are other compiler options

for that (at expence of speed, of course).

I tried a test comparing O3 and Os in the executable in
question. The version built with O3 took 64 seconds and the
Os version took 63 seconds. The O3 version is 72,472 bytes
and the Os version is 44,836 bytes. Also the variation in
executable size that I mentioned above didn't show up when
using Os. I'm going to start using Os and see how that goes.

I recall someone advising me to optimize for size years ago,
but I needed more proof.
 
I

Ian Collins

I tried a test comparing O3 and Os in the executable in
question. The version built with O3 took 64 seconds and the
Os version took 63 seconds. The O3 version is 72,472 bytes
and the Os version is 44,836 bytes. Also the variation in
executable size that I mentioned above didn't show up when
using Os. I'm going to start using Os and see how that goes.

Well what else did you expect? You told the compiler to back off on
inlining and it did.
I recall someone advising me to optimize for size years ago,
but I needed more proof.

Any blanket advice like that should be taken with a grain of salt.
Every application+target environment combination is unique, so to get
the best results, test and measure. Then use profile feedback if your
tools support it to squeeze out the last few percent.
 
W

woodbrian77

That's cool, but I'm curious why are you wanting to go smaller? We have

DLL-s of size around 200 MB and nobody is complaining.

No big reason, but the compile time also improved by about
20%. If simpler optimization produces equal run-time and
better build results, I'm inclined to use it.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,734
Messages
2,569,441
Members
44,832
Latest member
GlennSmall

Latest Threads

Top