Results 1 to 13 of 13
  1. #1
    cedron is offline Member
    Join Date
    Jun 2011
    Posts
    11
    Rep Power
    0

    Question Problems creating a bit displayer

    I'm trying to create a simple program to view the individual bits any file consists of. I take this file in as an argument. I'm using a JTextArea within a JFrame to display the bits.

    The program works, but is dreadfully slow. Could I get a few pointers as to where the bottleneck(s) is (are)? I'm know the line
    Java Code:
    textArea.append(Integer.toBinaryString(((buffer[i]<<j)&0x80)/128));
    within the two for loops is a huge sinner, but what in particular, and how I could do this differently and more efficient?

    Also I realize that by displaying the bits lazily, i.e. just one "screenfull" at a time, I would get a quicker initial display. How would I go about such a thing, considering scrolling, resizing etc?

    Any pointers are appreciated. Also any other tips related to my coding are also appreciated. Thanks in advance.

    Java Code:
    import java.io.*;
    import java.awt.*;
    import javax.swing.*;
    
    
    public class BitDisplay extends JFrame {
    	
    
    	public BitDisplay(String fileName){
    		setTitle("Text viewer "+fileName);
    		TextLayout textLayout = new TextLayout(fileName,this);
    		getContentPane().add(textLayout);
    
    		addWindowListener(new AppCloser());
    	}
    	
    	public static void main(String[] args) {
    		if(args.length<1){
    			System.out.println("Type the name of the file you want to display");
    			return;
    		}
    		BitDisplay frame = new BitDisplay(args[0]);
    		frame.setLocationRelativeTo(null); 
    		frame.pack();
    		frame.setVisible(true);
    	}
    
    	protected static final class AppCloser extends WindowAdapter {
    		public void windowClosing(WindowEvent e){
    			System.exit(0);
    		}
    	}
    
    	public class TextLayout extends JPanel {	
    		JTextArea textArea;
    		JFrame bitDisplay;
    		JScrollPane scrollPane; 
    		
    		public TextLayout(String fileName, JFrame bitDisplay){	
    			this.bitDisplay = bitDisplay;	
    			
    			textArea = new JTextArea(40,15);
    			textArea.setEditable(false);				
    			textArea.setLineWrap(true);					
    			textArea.setWrapStyleWord(true);
    			textArea.setFont(new Font("Monospaced",Font.BOLD, 14));
    			scrollPane = new JScrollPane(textArea, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED );
    			setLayout(new GridLayout(0,1));	
    			add(scrollPane);
    			
    			byte[] buffer = new byte[8192];
    			BufferedInputStream bufIn;
    			try{		
    				
    				bufIn = new BufferedInputStream(new FileInputStream(fileName));
    				int bytesRead = 0;
    				int i,j,k;
    				k=0;
    				byte[] reverse = new byte[8];
    				while((bytesRead = bufIn.read(buffer)) != -1){	
    					for(i=0;i<bytesRead;i++){
    						for(j=0;j<8;j++){
    							//Most important line. Shifts the byte from 0 to 7 times to the left filling with zero to the right, masks the byte at the most significant bit (0x80=10000000 in radix 2) and divides by 128 to get the correct bit value. 
    							textArea.append(Integer.toBinaryString(((buffer[i]<<j)&0x80)/128));	
    						}					
    						
    					}
    				}
    			}
    			catch(IOException e){
    				e.printStackTrace();
    			}
    		}
    	}
    } //End BitDisplay

  2. #2
    Norm's Avatar
    Norm is offline Moderator
    Join Date
    Jun 2008
    Location
    SW Missouri
    Posts
    17,306
    Rep Power
    25

    Default

    Concatenating Strings over and over and over is slow. append does concatenation.
    Instead of append, try building the String to be displayed in a large StringBuffer then covert it once to String to display.

  3. #3
    cedron is offline Member
    Join Date
    Jun 2011
    Posts
    11
    Rep Power
    0

    Default

    I've tried to make some modification, but I'm still using an append function, although this time with a large pre-allocated StringBuilder (I've read it's preferred to StringBuffer, correct?), like this:

    Java Code:
    StringBuilder sb = new StringBuilder[10485760];
    while((bytesRead = bufIn.read(buffer)) != -1){	
    					for(i=0;i<bytesRead;i++){
    						for(j=0;j<8;j++){
    							//Most important line. Shifts the byte from 0 to 7 times to the left filling with zero to the right, masks the byte at the most significant bit (0x80=10000000 in radix 2) and divides by 128 to get the correct bit value. 
    							sb.append(Integer.toBinaryString(((buffer[i]<<j)&0x80)/128));	
    						}					
    						
    					}
    				}
    textArea.append(sb.toString());
    Still no difference in performance. I'm not to sure about the inner workings of the StringBuilder, but shouldn't this be more effective, or am I basically doing the same as before, only with slightly more code?

  4. #4
    Norm's Avatar
    Norm is offline Moderator
    Join Date
    Jun 2008
    Location
    SW Missouri
    Posts
    17,306
    Rep Power
    25

    Default

    I thought building the String in a StringBuffer before appending it to the textarea would be faster.
    Try profiling the execution to see where the time is spent. One way: I think you use the -Xprof option.

    Add this to your code and see what is output:
    Java Code:
    
    	  long start = System.currentTimeMillis();  // save before start of read of file
                 .....LOOP HERE ....
                // After the loop
                System.out.println("1dur=" + (System.currentTimeMillis() - start));
                String theText = sb.toString();
                System.out.println("2dur=" + (System.currentTimeMillis() - start));
                textArea.append(theText);
                System.out.println("3dur=" + (System.currentTimeMillis() - start));
    Here's what I get using the program source as input:
    1dur=109
    2dur=109
    3dur=1219
    Last edited by Norm; 06-08-2011 at 03:21 PM.

  5. #5
    DarrylBurke's Avatar
    DarrylBurke is offline Member
    Join Date
    Sep 2008
    Location
    Madgaon, Goa, India
    Posts
    11,184
    Rep Power
    19

    Default

    My guess is that the major part of the time is consumed in Integer.toBinaryString.

    Oh, wait... is textArea.append(sb.toString()) inside the loop or after it? Your irregular indents make it difficult to spot, and I'm not about to count braces. If inside the loop, that would be the real bottleneck.

    db

  6. #6
    Norm's Avatar
    Norm is offline Moderator
    Join Date
    Jun 2008
    Location
    SW Missouri
    Posts
    17,306
    Rep Power
    25

    Default

    Look at the timing code I just posted. It says the time is spent in the textarea append()

  7. #7
    JosAH's Avatar
    JosAH is offline Moderator
    Join Date
    Sep 2008
    Location
    Voorschoten, the Netherlands
    Posts
    13,375
    Blog Entries
    7
    Rep Power
    20

    Default

    Why display one bit per iteration? Display the entire byte in binary form, that would speed up the process a bit ...

    kind regards,

    Jos
    cenosillicaphobia: the fear for an empty beer glass

  8. #8
    cedron is offline Member
    Join Date
    Jun 2011
    Posts
    11
    Rep Power
    0

    Default

    I did the profiling you showed and I get the same proportions in my results as you, i.e. the textArea.append is the biggest sinner, while the other operations are quite fast. By using the -Xprof option I found the biggest sinners to be:

    Interpreted + native Method
    2.9% 98 0 javax.swing.text.GapContent.getChars
    0.2% 6 0 javax.swing.text.WrappedPlainView$WrappedLine.brea kLines
    :
    :

    Compile + native Method
    57.5% 1941 0 javax.swing.text.WrappedPlainView.calculateBreakPo sition
    30.2% 0 1017 javax.swing.text.GapContent.getChars

    I suppose this shows that the swing methods being invoked by the JTextArea.append is slowing things down quite a bit.

    How could I go about displaying the bits in a more efficient way? Is there another Swing component or AWT component i should rather use, or should I focus on displaying the bits lazily as I mentioned in my initial post?

  9. #9
    cedron is offline Member
    Join Date
    Jun 2011
    Posts
    11
    Rep Power
    0

    Default

    Quote Originally Posted by JosAH View Post
    Why display one bit per iteration? Display the entire byte in binary form, that would speed up the process a bit ...

    kind regards,

    Jos
    Basically it was a bit of a naive approach, kinda coding straightforward and seeing where the bottlenecks were (if any) afterwards. I'm not too familiar with Swing and how long its methods may take. That also goes for String operations. I did think about this though (displaying each byte instead of each bit), but having another set of operations inside the inner for-loop creating that byte (string) didn't tempt me.

    It all comes down to plain ignorance regarding which operations are fast and which aren't really ;)

  10. #10
    JosAH's Avatar
    JosAH is offline Moderator
    Join Date
    Sep 2008
    Location
    Voorschoten, the Netherlands
    Posts
    13,375
    Blog Entries
    7
    Rep Power
    20

    Default

    Quote Originally Posted by cedron View Post
    Basically it was a bit of a naive approach, kinda coding straightforward and seeing where the bottlenecks were (if any) afterwards. I'm not too familiar with Swing and how long its methods may take. That also goes for String operations. I did think about this though (displaying each byte instead of each bit), but having another set of operations inside the inner for-loop creating that byte (string) didn't tempt me.

    It all comes down to plain ignorance regarding which operations are fast and which aren't really ;)
    Obtaining the binary String representation of an entire byte isn't much code:

    Java Code:
    byte b= // byte to display
    String display= "0000000"+Integer.toBinaryString(b&0xff);
    display= display.substring(display.length()-8);
    At the end of this code snippet the display String contains eight characters for its binary representation. You append it to your JTextArea.

    kind regards,

    Jos
    cenosillicaphobia: the fear for an empty beer glass

  11. #11
    cedron is offline Member
    Join Date
    Jun 2011
    Posts
    11
    Rep Power
    0

    Default

    Quote Originally Posted by JosAH View Post
    Obtaining the binary String representation of an entire byte isn't much code:

    Java Code:
    byte b= // byte to display
    String display= "0000000"+Integer.toBinaryString(b&0xff);
    display= display.substring(display.length()-8);
    At the end of this code snippet the display String contains eight characters for its binary representation. You append it to your JTextArea.

    kind regards,

    Jos
    Thanks for the reply. I guess I thought that the fewer lines within the two for-loops the better, although I understand this is a better approach. Thanks for the code, but just out of curiosity, wouldn't

    Java Code:
    byte b= // byte to display
    String display= Integer.toBinaryString(b&0xff);
    do the same thing? Why would you "prepent" eight zeroes, and then make a substring where you don't include them? (I might be way out on this though...)

    Also, you don't have any good thoughts about how I can display the bits more efficiently than my current implementation with JTextArea.append()?

  12. #12
    JosAH's Avatar
    JosAH is offline Moderator
    Join Date
    Sep 2008
    Location
    Voorschoten, the Netherlands
    Posts
    13,375
    Blog Entries
    7
    Rep Power
    20

    Default

    Quote Originally Posted by cedron View Post
    Thanks for the code, but just out of curiosity, wouldn't

    Java Code:
    byte b= // byte to display
    String display= Integer.toBinaryString(b&0xff);
    do the same thing? Why would you "prepent" eight zeroes, and then make a substring where you don't include them? (I might be way out on this though...)

    Also, you don't have any good thoughts about how I can display the bits more efficiently than my current implementation with JTextArea.append()?
    The toBinaryString( ... ) method doesn't generate leading zeros, i.e. 3 is converted to "11" while you wanted "00000011". If the JTextArea.append( ... ) method is slow converting an entire byte before appending it to the text model takes one append( ... ) call instead of eight (as in your code). You can also try to buffer an entire line before appending ...

    kind regards,

    Jos
    cenosillicaphobia: the fear for an empty beer glass

  13. #13
    cedron is offline Member
    Join Date
    Jun 2011
    Posts
    11
    Rep Power
    0

    Default

    I've googled some and found the main cause of the slow performance. It appears that the JTextField doesn't like being fed strings with no newlines. I assume that's why so much time is being spent in javax.swing.text.WrappedPlainView.calculateBreakPo sition, as I noticed by running the program with the -Xprof option previously.

    If I just add one newline at the end of my stringbuffer before JTtextArea.append(sb), the difference in performance is huge, although still slow for loading or scrolling files longer than 100kB. If I add a newline more often (say every 8192 bytes), it goes much faster for files up to (about) 2 MB, where I run out of heap space. This doesn't actually solve my problem, as I do not want any newlines shown in my bit display, and if I were to use this approach I guess I would have to calculate where the newlines should be every time I resize my window in order to fill the JTextArea completely, which is what I want.

    AWTs TextArea doesn't seem to have this problem, and loads quite quick without any insertion of newlines. It's not very pretty though, but I might stick with it if everything else fails. (I still run out of heap space when I try to load a 2MB file...)

    Turns out this is a bug in JTextArea, as stated in this bugreport: Bug ID: 4202291 long lines in wrapped JTextArea causes severe performance degradation

    A comment at the bottom claims it's fixed in version 6.0, so I'm gonna try to upgrade and see what happens.

    Also got some help from this link: Java in Newer: How to speed up JTextArea? - thatsjava.com

Similar Threads

  1. Title not displayer
    By weezy2894 in forum Java Applets
    Replies: 13
    Last Post: 04-18-2011, 04:12 AM
  2. Creating Snake Game: Few problems.
    By Nickv17 in forum New To Java
    Replies: 2
    Last Post: 01-21-2011, 04:59 AM
  3. InputStream/Jar Problems/File IO Problems
    By rdjava in forum Advanced Java
    Replies: 31
    Last Post: 01-17-2011, 11:12 AM
  4. Creating jar
    By nitinverma in forum AWT / Swing
    Replies: 1
    Last Post: 07-12-2010, 11:07 AM
  5. Creating files stopped creating...
    By Dieter in forum Advanced Java
    Replies: 3
    Last Post: 09-25-2009, 11:45 PM

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •