|
I have macros LOG1 to LOG5 for logging that aid debugging in my application. However with increased logging my application is effectively getting slowed down, so much to the extent that that application now takes 100 times longer.
While it is very hard to reduce to the number of log messages, i suspected most of the time is spent on writing the log message to the disk. So I implemented a buffered logger that writes to the disk only if the log buffer crosses 1 Mb. Although this has helped, for some reason I am not able to identify, the app is still slower than i am expecting.
Would it help if I offload the disk writing work to another "process" by sending the log messages to that process through a pipe or socket? I am interested in knowning people's experience, and if this will help I would like to know if it is worth implementing.
thanks!
|
|
|
|
|
Britley wrote: I have macros LOG1 to LOG5 for logging that aid debugging in my application. However with increased logging my application is effectively getting slowed down, so much to the extent that that application now takes 100 times longer.
How many log messages do log per unit of time? LOG1 ... LOG5 mean log levels that you turn on/off? How are the LOG1, ... LOG5 macros implemented? Are arguments always evaluated?
|
|
|
|
|
The arguments are not always evaluated. The LOGX imacro is implemented like this:
<br />
void _log(const char *format_str, ...);<br />
#define LOG1 if (logleve >= 1) _log<br />
#define LOG2 if (logleve >= 2) _log<br />
#define LOG3 if (logleve >= 3) _log<br />
I have not measured the number of log statements per unit of time, I am yet to add timestamps to the log messages. I havent added it just to avoid additional CPU cycles on the timestamp formatting. For the debugging to be fruitful I have to set the log level to 5 which outputs maximum number of log messages. I remember with log4j there was a way to redirect the log messages to another message, that is what makes me curious if that is going to help me here.
thanks!
|
|
|
|
|
Britley wrote: I have not measured the number of log statements per unit of time, I am yet to add timestamps to the log messages. I havent added it just to avoid additional CPU cycles on the timestamp formatting. For the debugging to be fruitful I have to set the log level to 5 which outputs maximum number of log messages. I remember with log4j there was a way to redirect the log messages to another message, that is what makes me curious if that is going to help me here.
It's difficult to decide if you simply write too much or if you have a bottleneck in your logger implementation. In the first case interprocess communication would not help you much because it only moves the problem to another location.
|
|
|
|
|
I get your point. I have been using my logger implementation for the past several months and its been doing well if the number of messages are not that many. I understand that IPC is not going to help if the IPC call takes as much longer as the original log call would take, but in my mind I was planning to implement a slow-reader/fast-writer model for the logger where the logger which is the slow reader will run from a seperate thread and will read the common buffer at a slower pace.
before I go ahead implement this, I also would like to profile my logging system. may be adding timestamps would help. Since the apps can be multithreaded profiling is going to be tricky. Any tips you have is appreciated.
thanks!
|
|
|
|
|
I use the event log manager API e.g. ReportEvent().
I created a new log for my 'company' so as not to poulute the Application, Security, or System logs. So far it has worked well.
...cmk
Save the whales - collect the whole set
|
|
|
|
|
In my experience, the bottleneck very often is the sprintf()-statement, and it's variants, of course.
All variants of sprintf (and CString::Format(v)) is extremely time- and CPU-consuming.
For performance, it's always better to use strcpy, strcat, ltoa, e.t.c.
I once had a loop with bad performance. I could improve that loop with a factor 7 (!) just by replacing sprintf with strcpy, strcat and ltoa.
Kakan
|
|
|
|
|
The app that I am currently writing uses simulated mouse clicks to interact with controls on another program's window using Send/PostMessage() calls. I have successfully dealt with pushbuttons, radio buttons, edit boxes and comboboxes, but have now come up against one that won't cooperate ! It is a SysDateTimePick32 control which is used to input dates and times (surprisingly !!). Normally, one can left-click on one of the 3 fields within the control, that field would highlight, and then you could use keyboard input to change the value. In my app, I have (basically) used the same sequence of ops as I would to interact with an edit control. (Get the hwnd for the control, position the cursor over the target field, WM_LBUTTONDOWN/UP to highlight it, and then WM_SETTEXT to attempt to modify the text). This all works except that the text does NOT change (I have checked the message flow in MS SPY++, and it gets a TRUE response to the WM_SETTEXT. I'm baffled ! Surely, if the user can interact with this control in real life, I SHOULD be able to simulate his actions with messages ?? Anybody has experience of the SysDateTimePick32 control in this respect ? Any suggestions appreciated, as my app is dead unless I can get over this !
Doug
|
|
|
|
|
Since you know that this is a SysDateTimePick32 control, why not use the date/time control messages defined on MSDN[^] to manipulate the control directly?
Software Zen: delete this;
|
|
|
|
|
Since my original posting, I have trapped the operator messages in Spy++, and have now implemented using WM_KEYDOWN, WM_CHAR, WM_KEYUP sequences. This works fine ! Gary (and please bear with me, as I'm new to all this !), I don't understand how to interact with a control in another app's window other than by sending 'system' messages to it. Can you really invoke it's member functions externally ? Can you give me a simple example on how to do this ?
Doug
|
|
|
|
|
There are messages that are specific to the date/time control that you can use to 'drive' it from another application. Take a look at the MSDN article I gave you the link for in my original reply to your post. Using the date/time control-specific messages will be a lot easier than trying to simulate the user's actions.
Software Zen: delete this;
|
|
|
|
|
Hi all!
I want to khow c++ routines to draw tables. like those in Microsoft word. for example to draw a table representing weekly program of my education classes. I want routines be able to merge cells, split cells, change line styles, and etc. refer to Microsoft Word for other features.
please anyone write an article about it.
thanks a lot.
|
|
|
|
|
this is one of hardest c++ job.
you should not try things like this except your a top most programer in the world and have at least 1 year time to go.
I guess programers who can do that will not post any question here.
A nice tool for optimizing your Microsoft html-help contents.
Includeh10
|
|
|
|
|
But I only want to use API capabalities to do this. isn't it easy?
|
|
|
|
|
I read many posts on this forum, I have a simple suggestion to C/C++ beginner: use variable properly.
assume you have a varable, which is called MyUser.
is name of the variable good? my answer is "No".
a variable includes 2 parts: type and meaning.
MyUser only includes second part: meaning, but doesn't show type of the variable.
good idea for defining the variable depends on its type, you should add type as prefix for the variable, E.g.
char*pszMyUser; //prefix psz=a Pointer of Zero based String
char**ppszMyUser; //ppsz=a pointer to a Pointer of Zero based String
int iMyUser; //i=integer, some people use "n" or "u"
SYSTEMTIME tmMyUser; //tm=SYSTEMTIME
there are no rules for defining name of prefix, but please respect public usage, E.g, people always use psz for char*, so we should not use other names.
===================================
there are many advantages if you use variable with prefix,
for example, you can update your code easily when program grows large or after one or more years. your code is also readable for others.
===================================
if you have 2 or more C/C++ samples for study, you have to choose one as start sample. first, test their performance, second, see which samples use prefix properly - the one which doesn't use prefix is not good normally.
===================================
if you have a class defined in this way:
class myfile
{
public:
LPTSTR filename;
BOOL dirty;
int data;
};
I suggest you change it as:
class myfile
{
public:
LPTSTR pszFileName;
BOOL bDirty; //b=boolean
int iData;
};
========================
today is sunday.
believe me or not, it is up to you.
A nice tool for optimizing your Microsoft html-help contents.
Includeh10
|
|
|
|
|
includeh10 wrote: a variable includes 2 parts: type and meaning.
This gets into a long religion war of type-naming, but off-hand I would disagree completely. Although it provides the programmer with instant information, it reduces future use, inheritance, polymorphism, and makes your job harder when you upgrade to future versions forcing full rewrites rather than minor changes to your code.
on the debate of hungarian notation[^]
_________________________
Asu no koto o ieba, tenjo de nezumi ga warau.
Talk about things of tomorrow and the mice in the ceiling laugh. (Japanese Proverb)
|
|
|
|
|
For a slightly different take see this. I agree that hungarian can be bad if used wrongly - But if used as described in the link I gave I think hungarian prefixes are a good thing. For example a "p" to name a pointer is usefull and will not pose any problems in the future. And if you do, say, change the pointer to a reference, you would have to visit every use of it anyway so no problem.
Steve
|
|
|
|
|
Stephen Hewitt wrote: For example a "p" to name a pointer is usefull and will not pose any problems in the future. And if you do, say, change the pointer to a reference, you would have to visit every use of it anyway so no problem.
I agree absolutely on the p designation of pointer and require it in my work (or ptr prefix). But the primary problem with hungarian notation is that it forces you to define two separate rules for naming conventions, one based on C/C++ types and one for your own types.
if I make a variable for x as an integer it is iX, but if I make a vector matrix for multidimensional matrix definitions is it vX? usually no. You then start defining a set of rules exceptions if you will when you will use type designation and when you will not, two separate rules rather than one consistant one. Is mX a map X or a multimap X? is hX a hex string of X or a hash table? Thus you get into enlarging your naming convention to cover all things.
myClass myClassUsageVariable;
myClass *p_myClassUsageVariable;
// or
myClass mcUsageVariable;
myClass *p_mcUsageVariable;
// matches this?
int iIterator;
int *p_iIterator;
// or
int intIterator;
int *p_intIterator;
generally type conventions do not ask hungarian for user classes so then you have:
myClass UsageVariable;
int iIterator;
and start drawing out a long line of rules on what should be combined into hungarian and what should not, two completely different naming conventions. Or worse you decide that everything should be listed in hungarian including class, namespace, orignator of the class, as well as type. Now your variable name is taking the place of documentation. (I have had someone try to request this)
using namespace boost; // 3rd party library from boost
shared_ptr boost_boost_sharedptr_pEarthProjection;
Since boost has shared_ptr and scoped_ptr sp is not enough, so either you start enlarging your type definitions or removing them for all 3rd party and user defined work. Again, making two sets of naming conventions, which I consider worse. It also doesn't provide you with any more information that a proper IDE will. A professional tool will tell you the type, good documentation will tell you the type, auto documentation will tell you the type. But hungarian notation just makes life more difficult.
I did say the subject opens up a religion war of types. I agree with the idea that hungarian notation actually reduces object oriented design and creates redundant overhead and restricts future growth so significantly as to actually damage every product cycle it is used in. You find yourself saying "I don't want to make that change, because it requires me to change all the variable names in 100 source files to upgrade quantity from integer to double" so we will continue selling our software to DVD end-sales and not warehouses so that we do not have to deal with crate SKU quantities (including partials) as well as whole. Now you are redefining your companies goals based on the choice of a variable.
I do not ask everyone to give up hungarian, but I will fight it on my team-projects because the rules are inconsistant, or so redundant as to make it unusable and restrictive.
_________________________
Asu no koto o ieba, tenjo de nezumi ga warau.
Talk about things of tomorrow and the mice in the ceiling laugh. (Japanese Proverb)
|
|
|
|
|
I totally agree that some people go overboard with Hungarian notation, presumably in the belief that it will make their code easier to understand.
Me, I have four rules: a pointer variable always starts with p, and a class member variable always starts with m_ and boolean variables always start with b (unless they are called ok or failed). Finally all (of the very few) global variables start with a g_ to highlight that they are global. (I once came across some code, perhaps 200 lines, where the 'programmer' (or idiot, more likely) had defined a global variable called i presumably to save having to define it in every function!)
The first rule certainly helps save confusion, like, Is what I am passing to this function a pointer or a reference? The second rule's benefit comes largely from the fact that with complicated code it is easy to run out of variable names. By sticking a tag in front of a load of the variables, I create room for more. The g_ and m_ prefixes certainly help me stop worrying how the variable got its value.
As for putting an i in front to show that the value is an integer, this is a waste of time at best. And I don't see the point in adding a prefix to strings to indicate that they are null terminated. How many strings are NOT null terminated? Besides, suppose I decide to define
CString Name;
and later in the interests of speed decide to redefine as
char Name[100];
Should I rename Name as psName to show that it is now a pointer to a string? Or call it sName to show that it is an array which works as a string? No, just call it Name, capitalised here because it is an important variable, as distinct from name which is just some temporary name used very locally, a throw-away version.
A name should describe the purpose or algorithmic behavior, not the implementation. The IDE will tell me about implementation. As a programmer looking at ancient code I wrote last month, I want to get an idea of what the code is meant to be doing, what its purpose is, and I do not want to be distracted by irrelevant low level details.
Shraddhan
If you want my advice, contact my secretary for a quotation first.
|
|
|
|
|
hi all, this is more of a design question than a code question, but:
i have a class in my code which represents a file. often i have a member specifying the current filename, and code within the class which loads a file and saves a file.
i was wondering what the generally accepted technique is (if there is one), to store the filename and file code within the class, to store just the file code in the class and the filename outside, or to store all of those outside.
example pseudo-code:
class myfile {<br />
public:<br />
LPTSTR filename;
BOOL dirty;
int data;<br />
<br />
static myfile *LoadFile(LPTSTR fn);<br />
void SaveFile();<br />
};
thanx in advance
|
|
|
|
|
generally you do not want to store just a pointer to a string, you will want to store a string. Also unless you want to expose all that to the all the programmers, make filename, dirty, data all private. Expose a couple of functions to request a copy of or set the filename. That gets into personal preference.
I will give my reasoning for not storing a pointer only as the filename.
A) it is pointing to data outside the class (where ever the string storage was for the original call). This means you will have bugs when ever that data storage is not persistant, or force you to use global variables. In either case you find the class design controlling behavior outside of itself, which is bad news.
B) local storage just makes easier control. copy, verify, error control, manipulation of the name (filename.backup) when you want to make backup copies or working versions. It actually increases your useability of the class for future design changes/features.
C) it fits with the whole idea of object oriented, keep all your data in respect to the class inside the class, or in a friendly class. Too much interconnection/dependancy increases difficulty in understanding.
_________________________
Asu no koto o ieba, tenjo de nezumi ga warau.
Talk about things of tomorrow and the mice in the ceiling laugh. (Japanese Proverb)
|
|
|
|
|
I've inherited an image processing task which I didn't initially write, but which I need to modify - I need to change an input parameter according to the position within the input image. Naturally, the code works by iterating over the destination image, but now I need to change it to iterate over the source image, so I can work out this parameter as I go. The parameter is called sourceFOVRads ( for reference in the code ). The trouble is, I can't work out how to reverse the code so that it iterates over the source instead of destination image. Of course, I know how to iterate over an image using polar co-ordinates, but I think the transform needs to be completely rewritten, I don't see how to reverse the Atan2 calls to get the input parameters.
for(int j=0;j<output.height;j++)
{
for(int="" i="0;i<output.Width;i++)
" {
="" double="" x="2" *="" (double)output.width="" -="" 1;="" -1="" to="" 1
="" y="2" j="" (double)output.height="" calculate="" phi="" and="" theta=""
="" latitude="y*Math.PI/2;" -pi="" 2="" <="y" pi="" longitude="x*Math.PI;"
="" p="" is="" the="" vector="" from="" camera="" position="" into="" scene="" p.x="Math.Cos(latitude)*" math.sin(longitude);
="" p.y="Math.Cos(latitude)*" math.cos(longitude);
="" p.z="Math.Sin(latitude);
" fisheye="" polar="" coordinates
="" r="pixelRadius*phi" sourcefovrads;
="" determine="" coordinate="" in="" source="" image
="" u="Convert.ToInt32(fishCentre.X" +="" r*math.cos(theta));
="" if(u="" 0="" ||="">=source.Width)
continue;
v=Convert.ToInt32(fishCentre.Y - r*Math.Sin(theta));
if(v < 0 || v>=source.Height)
continue;
pOut[(outputStride*j)+(i*3)]=(Byte)(int)pSrc[(sourceStride*v)+(u*3)];
pOut[(outputStride*j)+(i*3)+ 1]=(Byte)(int)pSrc[(sourceStride*v)+(u*3)+ 1];
pOut[(outputStride*j)+(i*3)+ 2]=(Byte)(int)pSrc[(sourceStride*v)+(u*3)+ 2];
As I said, I can do the basic stuff, like so:
for (double t = 0; t < 2 * Math.PI; t += .01)
{
for (int radius = 0; radius < pixelRadius; ++radius)
{
int xSrc = (int)(radius * Math.Cos(t)) + fishCentre.X;
int x = 2 * (xSrc/source.Width) - 1;
int ySrc = (int)(radius * Math.Sin(t)) + fishCentre.Y;
int y = 2 * (xSrc/source.Height) - 1;
pOut[(int)(x*3 + y * sourceStride)] = pSrc[(int)(x*3 + y * sourceStride)];
pOut[(int)(x*3 + 1 + y * sourceStride)] = pSrc[(int)(x*3 + 1 + y * sourceStride)];
pOut[(int)(x*3 + 2 + y * sourceStride)] = pSrc[(int)(x*3 + 2 + y * sourceStride)];
}
}
This code uses polar co-ordinates to copy just the circle of the image that we're interested in, without any transform. It steps over the theta far too quickly mostly so I can quickly see the results of my code
However, in this block:
theta=Math.Atan2(p.z,p.x);
phi=Math.Atan2(Math.Sqrt(p.x*p.x+p.z*p.z),p.y);
r=pixelRadius*phi / sourceFOVRads;
I don't know where to start. I have the pixel radius and r, and as I have my source radius, I can calculate which sourceFOVRads value to use, so I can work out phi, easily. But, I obviously cannot derive the values for p.x, p.y and p.z from this value, and I'm not sure how else to go about it. Any help on this will be greatly appreciated, because I am really stuck.
BTW, the code is C#, I posted it here for visibility.
Christian Graus - Microsoft MVP - C++
|
|
|
|
|
Christian,
What do r, pixelRadius and sourceFOVRads represent?
-Sean
----
Shag a Lizard
|
|
|
|
|
r is the radius of the current postion in the source image, in polar co-ords. pixelRadius is the radius of the circle we're working with. sourceFOVRads is the parameter I need to change based on radius in the source image. I've done some code to try and do this with the current transform, but it doesn't work 100%.
Christian Graus - Microsoft MVP - C++
|
|
|
|
|
In general there is a good reason why such algoriths iterate over the destination image - It ensures that the destination image is fully covered (no gaps) and that we don't get multiple writes to a single pixel.
Steve
|
|
|
|
|