• Post Reply Bookmark Topic Watch Topic
  • New Topic

Application Log File - Performance issues

 
Vasco Dion�sio
Greenhorn
Posts: 22
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello guys,
I wonder if you could help me out... I need to write an application log file... I wrote the following method and each time I want to write some String to the file I call it but I'm not sure if the performance is the best I can get. What do you think? Do you know a better way to do it?
private void printLog(String s) {
RandomAccessFile f = null;
try {
f = new RandomAccessFile("mylog.txt","rw");
f.seek(f.length());
f.writeBytes(s+"\n");
} catch(FileNotFoundException e) {
System.out.println("File not found");
} catch(IOException e) {
System.out.println("Couldn't open file");
} finally {
try {
f.close();
} catch (IOException e) {}
}
}

Thank you all in advance
Bye
Vasco
 
jason adam
Chicken Farmer ()
Ranch Hand
Posts: 1932
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Personally, I would use a PrintWriter set to append, and then use it's println() methods to write the data. So, something like
PrintWriter writer = null;
try {
writer = new PrintWriter( new FileOutputStream( "mylog.txt" , true ), true );
writer.println( s );
}
...
Not sure if using the RandomAccessFile is really buying you much other than slightly more complex code.
[ January 26, 2004: Message edited by: jason adam ]
 
Vasco Dion�sio
Greenhorn
Posts: 22
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
First off all thanks for your answer Jason...
Another question...
I am using a "closed" source API by SAP, A.G.
The class where my code runs is a class that extends another class which in turn implements the Runnable interface.
myclass extends ServerClass (closed source by SAP, A.G) --> implements Runnable
Each time I want to append a line to the log file I open the file stream, write the line to be appended and close the file stream. I think that if I would not open and close the file stream each time I wanted to write to file would be more performant. I could open the file output stream in myclass's constructor, write the line each time I want and in the end close the file stream. My problem is "Where can I close the file stream?" because my application is a server which is constantly listening to network calls ---> it "never" ends unless I stop it.
I tried to override the run method of the original ServerClass like this...
public synchronized void run() {
try {
super.run();
}
finally{
System.out.println("I could close the file stream here");
}
}
But I nerver see the message "I could close the file stream here" displayed in my screen. Do you know why this does not work?
Thank you very much for your help...
wich you the best
Vasco
 
Vasco Dion�sio
Greenhorn
Posts: 22
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello Jason,
Could you help me a little bit more, please?
Thank you
Vasco
 
jason adam
Chicken Farmer ()
Ranch Hand
Posts: 1932
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Sorry Vasco, thought I had replied
Honestly, not sure why you aren't getting that message. Opening and closing a stream with each write will impact your performance depending on how often the writing is getting done. Are you doing writes every couple of seconds, or every few minutes? If the latter, you aren't going to see a huge performance increase with not opening and closing a stream each time.
As far as the overriding thing, that's a difficult one to answer. One would think that finally() would be called, but there's a lot of unknowns here. Instead, what about implementing a finalize() method (which all objects inherit from Object), and put it in there? That's probably a better place to stick it anyway.
[ January 27, 2004: Message edited by: jason adam ]
 
Vasco Dion�sio
Greenhorn
Posts: 22
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
That's OK Jason... thanks again for your answer...
I used to think that we have no garantee that the finalize() method is ever called... Isn't it related to cleaning up memory when the garbage collector executes... furthermore, what might happen, what are the implications off not closing the file output stream ever?
Thanks again
Vasco
 
jason adam
Chicken Farmer ()
Ranch Hand
Posts: 1932
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
We're not guaranteed which thread will call finalize(), but it will be called. In fact, the API even gives the example that an object would use finalize to close I/O resources. The finalize method is invoked by the VM when it is determined that there are no longer any references to that object. Perhaps you're thinking of the GC, which we aren't guaranteed that calling the garbage collector will in fact make it do the collecting.
As far as never closing the stream, I think that may be dependent on the underlying system. I think it may be that the resource would be locked, but again I'm not positive on that. Someone else may be able to give a more descriptive answer.
 
Vasco Dion�sio
Greenhorn
Posts: 22
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello Jason,
Now you got me completly confused...
Kathy Sierra writes in her book "Sun Certified Programmer & Developer for Java 2 Study Guide (Exam 310-035 & 310-027)" - pag. 398 - about cleaning up memory before GC and the finalize() method and I quote:
"So, any code that you put into your class�s overridden finalize()method is not guaranteed to run. The finalize() method for any given object might run, but you can�t count on it, so don�t put any essential code into your finalize() method. In fact, we recommend that in general you don�t override finalize() at all."
So... I thougth we couln't rely on the execution of the finalize() method...
that's why I didn't used it at first and replaced the code with the finally block...
Thanks again for your time Jason
Vasco
 
jason adam
Chicken Farmer ()
Ranch Hand
Posts: 1932
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Aaaaah yes, the problem being that Java objects aren't guaranteed to be garbage collected, and therefore this method may not be called. *bonks himself* See what happens when you stop reading? Refreshers are a good thing! If the GC does do it's thing on a method, finalize() will be called I believe, but if the GC never does it's thing on your object, then logically finalize() won't be called. Hence, it's not something to depend on.
So first, how often are you looking at writing? Again, you may be making it more difficult if the optimization just isn't there.
How is this being run? Is it in an app server, a stand alone application?
 
Vasco Dion�sio
Greenhorn
Posts: 22
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
It runs on an application server and it receives several (10) calls per minute... I do one write for each call... so we are talking about 10 writes per minute...
Best regards
Vasco
 
jason adam
Chicken Farmer ()
Ranch Hand
Posts: 1932
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
And you are wanting to make sure that the streams close in case of the server going down, correct?
I wonder if that is really an issue. If the program stops running, then I would think the resources in use by that program would be released, so the streams wouldn't remain opened (since they're objects just like everything else). But since I've steered you wrong once, I'm going to ask a couple of the higher ups their opinion.
 
Vasco Dion�sio
Greenhorn
Posts: 22
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
thanks Jason
 
Stan James
(instanceof Sidekick)
Ranch Hand
Posts: 8791
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
With buffered output I'd be worried that one could crash the VM without flushing the buffer. You'd only lose the last few lines written, but they'd usually be the most interesting. Anybody know any docs about whether that is addressed in the language specs or if we're just guessing? You might have a performance issue on non-buffered IO.
 
Jim Yingst
Wanderer
Sheriff
Posts: 18671
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I see Stan replied while I was still writing, so there's some duplication here, but here you are:
If the program stops running, then I would think the resources in use by that program would be released, so the streams wouldn't remain opened (since they're objects just like everything else).
Generally yes. It's the sort of thing that probably depends on the OS, as well as exactly how was the program stopped. (ctrl-C? kill -9? Turning off the power?) But generally when a process is terminated the OS will manage to clean up well enough that when you start the program again it will be able to open the file and resume writing to it. I think the biggest risk is that you might find some data never got written to the file, maybe because it was still in a buffer somewhere. To help ensure this doesn't happen, you probably want to flush() the file periodically. One way to achieve this is by creating a PrintWriter using new PrintWriter(otherWriter, true), which will automatically flush() the stream whenever you call println(). This can be a little inefficient, but it's easy.
Looking back to earlier posts:
[B]I tried to override the run method of the original ServerClass like this...

But I nerver see the message "I could close the file stream here" displayed in my screen. Do you know why this does not work?[/B]
My guess is that since this is a server of some sort, it's designed to do some sort of infinite loop waiting for new input or new clients. So super.run() never returns at all. If it did, you would see that print statement. Unless output has been redirected somewhere else - but if you're seeing output from other print statements, but not this one, then I'd have to say that super.run() is still running.
I don't know what kind of server you're dealing with here, but it probably has some sort of shutdown method. Find that, and see if you can insert a close() call to the file as part of the shutdown sequence. Alternately if you normally shut down using control-C or something, you can try using a shutdown hook:

This can't always be guaranteed to work, depending on shutdown method (e.g. kill -9 probably won't bother respect the shutdown hook, I'm guessing) but it's as good as you're likely to be able to get on most systems.
Finally, I'd note that there's good logging functionality available already in either java.util.logging or Log4J. The time spent reinventing the wheel here could probably be better spent learning a new API with lots more functionality than what you've got so far.
 
Vasco Dion�sio
Greenhorn
Posts: 22
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello again,
Thank you so much everybody... You have been very helpfull...
The solution using addShutdownHook seems to work fine when I stop the server with CTRL+C or with the kill command... I have to wait now to see how it works when a runtime error occurs...
I hope that one of these days I'm able to help you although it migth take a while since I am only a rookye...
Regards to all,
Vasco

[ January 30, 2004: Message edited by: Vasco Dion�sio ]
[ January 30, 2004: Message edited by: Vasco Dion�sio ]
 
dave sag
Ranch Hand
Posts: 47
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Jim Yingst:
I don't know what kind of server you're dealing with here, but it probably has some sort of shutdown method. Find that, and see if you can insert a close() call to the file as part of the shutdown sequence. Alternately if you normally shut down using control-C or something, you can try using a shutdown hook:

This can't always be guaranteed to work, depending on shutdown method (e.g. kill -9 probably won't bother respect the shutdown hook, I'm guessing) but it's as good as you're likely to be able to get on most systems.


I have found that this works fine for code executed directly but if you try running it using ant's java task then crtl-c never invokes the shutdown hook. I have written a simple test that shows this is true. not sure if this is a bug in the JVM or Ant's Java task.
 
It is sorta covered in the JavaRanch Style Guide.
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!