|
From: Joshua G. <pr...@co...> - 2005-01-31 03:50:44
|
Hi, DISCLAIMER: I'm sorry if this gets a little long winded but theres a lot of detail to describe. For the past few weeks I have been spending some weekends digging intothe slow performance of jEdit's File System Browser over SMB networkshares. I've been using jEdit for 3yrs and have just lived with thisissue, but now that my company is considering standardizing on jEdit asit's code editor, it has become a larger issue because few are willingto accept it due to this issue. For example browsing a network folderwith 1000 files using jEdit takes close to 17seconds over a 802.11bconnection, but using Windows Explorer takes less than a second. Thegood news is that after one to many cups of coffee, I believe I have asolution to the problem. Here's the details of what I found and how I discovered the solution. After checking out the source from CVS I hunted down the FileVFS classand it's inner class LocalDirectoryEntry. As a test, I then hard-coded in values for all but the 'name', 'path' and 'type', thus eliminating the remaining calls on the File object. To my surprise, this dropped the speed from 17 seconds to around 2 seconds. I then restored the calls for each attribute one-by-one and I found that no single attribute was slow, each one contributed 3-4 seconds to the load time. So clearly there seemed to be an issue with the java.io.File object and how it accessed attributes. A little google searching turned up JSR-203 (originally targeted for JDK1.5, now targeted for JDK1.6) that will add support for bulk-retrieval of file attributes. Further review of the java.io.File class indicated that as suspected, it only retrieves one attribute at a time from the underlying file system. So at that point it was clearthat Java was to fault and for a while I was concerned that nothingcould be done. In disbelief that such a flaw existed, I decided to give theJFileChooser demo that comes with the JDK a try and see if it had thesame slowness when using the detail view and accessing the same networkdirectory. Once again I was surprised because it seemed thatJFileChooser listed the detail view of the directory in only 1 second.Further, I tried using the jEdit File Browser from my Linux desktop tobrowse the same network drive and I found that it also only took 1second. So apparently this flaw is only an issue under Windows andapparently the Sun engineers did something to get JFileChooser's accessto attributes under windows running faster then what java.io.File provided. So into the JFileChooser source I went and after many hours of pouringover all the details and running a number of tests, it looks like Sunspecifically addressed this slowness issue in there code by doing thefollowing: 1. JFileChooser gets it's file listing from the the FileSystemView classin the 'javax.swing.filechooser' package, not from java.io.File. Youcall FileSystemView.getFileSystemView() to get an instance of the classand then you call fsv.getFiles() to get your file listing. The'getFiles()' method returns an array of 'File' objects, which in thecase of Windows, are actually instances of the'sun.awt.shell.Win32ShellFolder2' class that subclasses 'java.io.File'.Looking through the source code for 'Win32ShellFolder2' reveals that theclass performs native bulk retrieval of certain attributes and that itoverrides the 'isHidden()' & 'isDirectory()' method of the 'File'class. Oddly though, the class does not override the 'length()','lastModified()', 'canRead()' or 'canWrite()' methods which means thespeed of those methods does not change. Why this is the case isexplained in point 2. 2. JFileChooser only accesses the attributes for the files that arelisted in the visible area of the JTable. Currently jEdit's browser,lists all the files in a directory, creates a DirectoryEntry instancesfor each 'File' and copies each attribute from the File to theDirectoryEntry. In contrast, JFileChooser lists all the files in adirectory but does not access the attributes for a given file until theTableModel.getValueAt() method is called while rendering the visiblearea of the JTable. This allows the FileBrowser to display very fastsince it only access attributes for the 30 or so files visible in thebrowser at any time. However, there are two attributes that JFileChooser mustaccess for each file before displaying any files. The isHidden() andisDirectory() properties are necessary for the model to render anycontent, which is why those attributes are accessed in a native bulk waythrough the 'Win32ShellFolder2' class. So with this gained insight I proceeded to make the necessary changes tothe jEdit 4.3 pre 2 code base that I have checked out.Making the first change to jEdit was straight forward, I modified theFileVFS._listDirectory() method to use FileSystemView.getFiles() insteadof File.listFiles() and the result was the load time dropped from 17seconds to 14 seconds. Implementing the second change was a bit more involved. Since I neededto delay access the to a file's attributes as long as possible, I had tomodify VFS.DirectoryEntry so that it provided access to it's fields(name, path, symlinkPath, deletePath, type, length, hidden, canRead &canWrite) through methods. That way I could lazy load the attributesfrom the File class when a given method was called. This was long andtedious since every reference to a given field had to be changed to theappropriate method call. I then had to modifyVFSDirectoryEntryTable.resizeColumnsAppropriately() so that it did notcalculate the width of the attribute columns based on the width of thevalues. It still calculates the width of the name column since it'sfast to read the file name, but the attribute columns are hard set to aspecific widths based on the maximum likely value of the attribute. Forinstance the last modified column would not have a value larger than"12/12/12 12:12 PM" so I calculate the width based on that staticvalue. This solution may not be perfect since the Browser is also usedfor other types of file views which may have different attributes that arenot as static in their width, but I'm hoping a solution to this issuecan be found. That was pretty much it for the changes and with thesecond change in place the load time dropped from 14 seconds to 1 second. I'm planning on building a special 4.2 final build with these changes inplace since my company needs this fix soon and 4.3 is still in earlydevelopment. Any thoughts? Is there a chance this could be changed for 4.3? Thanks, -Josh Gertzen |
|
From: Patrick W. <jed...@pd...> - 2005-01-31 06:48:00
|
Josh What a cool and excellent analysis! I was wondering how the JDK had been able to improve render times on the FileChooser. This reminds me of a complaint by author/programmer Elliot Rusty Harold, that the File object in Java is basically just a URL, not a handle to the file itself. One question would be, how does JFileChooser itself do over SMB? Might it make more sense to extend that class and use it as an "alternate" FSB so that we can always pick up enhancements to the JDK, rather than maintaining a completely separate piece of code? I'm just a user, so I ask this just out of interest. Regards Patrick Joshua Gertzen wrote: > Hi, > > DISCLAIMER: I'm sorry if this gets a little long winded but theres a lot > of detail to describe. > > For the past few weeks I have been spending some weekends digging > intothe slow performance of jEdit's File System Browser over SMB > networkshares. I've been using jEdit for 3yrs and have just lived with > thisissue, but now that my company is considering standardizing on jEdit > asit's code editor, it has become a larger issue because few are > willingto accept it due to this issue. For example browsing a network > folderwith 1000 files using jEdit takes close to 17seconds over a > 802.11bconnection, but using Windows Explorer takes less than a second. > Thegood news is that after one to many cups of coffee, I believe I have > asolution to the problem. Here's the details of what I found and how I > discovered the solution. > > After checking out the source from CVS I hunted down the FileVFS > classand it's inner class LocalDirectoryEntry. As a test, I then > hard-coded in values for all but the 'name', 'path' and 'type', thus > eliminating the remaining calls on the File object. To my surprise, > this dropped the speed from 17 seconds to around 2 seconds. I then > restored the calls for each attribute one-by-one and I found that no > single attribute was slow, each one contributed 3-4 seconds to the load > time. So clearly there seemed to be an issue with the java.io.File > object and how it accessed attributes. A little google searching turned > up JSR-203 (originally targeted for JDK1.5, now targeted for JDK1.6) > that will add support for bulk-retrieval of file attributes. Further > review of the java.io.File class indicated that as suspected, it only > retrieves one attribute at a time from the underlying file system. So > at that point it was clearthat Java was to fault and for a while I was > concerned that nothingcould be done. > > In disbelief that such a flaw existed, I decided to give theJFileChooser > demo that comes with the JDK a try and see if it had thesame slowness > when using the detail view and accessing the same networkdirectory. Once > again I was surprised because it seemed thatJFileChooser listed the > detail view of the directory in only 1 second.Further, I tried using the > jEdit File Browser from my Linux desktop tobrowse the same network drive > and I found that it also only took 1second. So apparently this flaw is > only an issue under Windows andapparently the Sun engineers did > something to get JFileChooser's accessto attributes under windows > running faster then what java.io.File provided. > > So into the JFileChooser source I went and after many hours of > pouringover all the details and running a number of tests, it looks like > Sunspecifically addressed this slowness issue in there code by doing > thefollowing: > > 1. JFileChooser gets it's file listing from the the FileSystemView > classin the 'javax.swing.filechooser' package, not from java.io.File. > Youcall FileSystemView.getFileSystemView() to get an instance of the > classand then you call fsv.getFiles() to get your file listing. > The'getFiles()' method returns an array of 'File' objects, which in > thecase of Windows, are actually instances of > the'sun.awt.shell.Win32ShellFolder2' class that subclasses > 'java.io.File'.Looking through the source code for 'Win32ShellFolder2' > reveals that theclass performs native bulk retrieval of certain > attributes and that itoverrides the 'isHidden()' & 'isDirectory()' > method of the 'File'class. Oddly though, the class does not override > the 'length()','lastModified()', 'canRead()' or 'canWrite()' methods > which means thespeed of those methods does not change. Why this is the > case isexplained in point 2. > > 2. JFileChooser only accesses the attributes for the files that > arelisted in the visible area of the JTable. Currently jEdit's > browser,lists all the files in a directory, creates a DirectoryEntry > instancesfor each 'File' and copies each attribute from the File to > theDirectoryEntry. In contrast, JFileChooser lists all the files in > adirectory but does not access the attributes for a given file until > theTableModel.getValueAt() method is called while rendering the > visiblearea of the JTable. This allows the FileBrowser to display very > fastsince it only access attributes for the 30 or so files visible in > thebrowser at any time. However, there are two attributes that > JFileChooser mustaccess for each file before displaying any files. The > isHidden() andisDirectory() properties are necessary for the model to > render anycontent, which is why those attributes are accessed in a > native bulk waythrough the 'Win32ShellFolder2' class. > > So with this gained insight I proceeded to make the necessary changes > tothe jEdit 4.3 pre 2 code base that I have checked out.Making the first > change to jEdit was straight forward, I modified > theFileVFS._listDirectory() method to use FileSystemView.getFiles() > insteadof File.listFiles() and the result was the load time dropped from > 17seconds to 14 seconds. > > Implementing the second change was a bit more involved. Since I > neededto delay access the to a file's attributes as long as possible, I > had tomodify VFS.DirectoryEntry so that it provided access to it's > fields(name, path, symlinkPath, deletePath, type, length, hidden, > canRead &canWrite) through methods. That way I could lazy load the > attributesfrom the File class when a given method was called. This was > long andtedious since every reference to a given field had to be changed > to theappropriate method call. I then had to > modifyVFSDirectoryEntryTable.resizeColumnsAppropriately() so that it did > notcalculate the width of the attribute columns based on the width of > thevalues. It still calculates the width of the name column since > it'sfast to read the file name, but the attribute columns are hard set > to aspecific widths based on the maximum likely value of the attribute. > Forinstance the last modified column would not have a value larger > than"12/12/12 12:12 PM" so I calculate the width based on that > staticvalue. This solution may not be perfect since the Browser is also > usedfor other types of file views which may have different attributes > that arenot as static in their width, but I'm hoping a solution to this > issuecan be found. That was pretty much it for the changes and with > thesecond change in place the load time dropped from 14 seconds to 1 > second. > > I'm planning on building a special 4.2 final build with these changes > inplace since my company needs this fix soon and 4.3 is still in > earlydevelopment. > > Any thoughts? Is there a chance this could be changed for 4.3? > > Thanks, > > -Josh Gertzen > > > > > ------------------------------------------------------- > This SF.Net email is sponsored by: IntelliVIEW -- Interactive Reporting > Tool for open source databases. Create drag-&-drop reports. Save time > by over 75%! Publish reports on the web. Export to DOC, XLS, RTF, etc. > Download a FREE copy at http://www.intelliview.com/go/osdn_nl |
|
From: Joshua G. <pr...@co...> - 2005-02-02 02:55:53
|
Patrick Wright wrote: > What a cool and excellent analysis! Thanks, it took a while to put it together. Patrick Wright wrote: > One question would be, how does JFileChooser itself do over SMB? I'm not sure exactly what you mean by this. If your referring to the speed of JFileChooser when browsing the same SMB network share, then the answer is it's very fast. If your wondering how it performs with regard to it's network communication profile, the answer would be not very good due to the inherent issues with java.io.File. Patrick Wright wrote: > Might it make more sense to extend that class and use it as an > "alternate" FSB The architecture of jEdit's FSB abstracts the file system out of the browser, whereas JFileChooser has the file system integrated directly into it. Therefore it might be difficult to accomplish this. Also, based on my analysis it seems that the only thing JFileChooser *really* offers is the javax.swing.filechooser.FileSystemView class which is public and can easily be used by the jEdit FSB. On another note, I have created a special build of "jEdit 4.2 final", which has all the changes that I described in my original post. I have distributed it amongst the rest of the programmers in my group and everyone is much happier with it's performance. If anyone would like a copy of the modified jEdit.jar build to experiment with, just let me know. -Josh Gertzen |
|
From: Joshua G. <pr...@co...> - 2005-02-02 08:03:50
|
For those who are interested, here's a download link for the modified jEdit 4.2 final jar that contains that contains the file system browser changes: jar: http://www.realitypath.com/josh/jedit42-fast-browser.jar (just rename to jedit.jar and replace with existing jedit.jar). src: http://www.realitypath.com/josh/jedit42source-fast-browser.zip -Josh Gertzen |
|
From: Manfred U. <uss...@ic...> - 2005-02-03 07:08:51
|
Hi Josh, Joshua Gertzen wrote: > For those who are interested, here's a download link for the modified > jEdit 4.2 final jar that contains that contains the file system browser > changes: > > jar: http://www.realitypath.com/josh/jedit42-fast-browser.jar (just > rename to jedit.jar and replace with existing jedit.jar). > I regularly have to open files from directories on Netware drives containing several thousand source files, which I always needed a lot of patience for. Now it's really fast. A huge improvement. Thanks a lot! Manfred -- ________________________________________________________________________ Manfred Usselmann uss...@ic... |
|
From: Slava P. <sl...@je...> - 2005-02-02 23:08:45
|
Thank you very much for tracking this down! I will incorporate your suggestions in 4.3pre2. Joshua Gertzen wrote: > Hi, > > DISCLAIMER: I'm sorry if this gets a little long winded but theres a lot > of detail to describe. > > For the past few weeks I have been spending some weekends digging > intothe slow performance of jEdit's File System Browser over SMB > networkshares. I've been using jEdit for 3yrs and have just lived with > thisissue, but now that my company is considering standardizing on jEdit > asit's code editor, it has become a larger issue because few are > willingto accept it due to this issue. For example browsing a network > folderwith 1000 files using jEdit takes close to 17seconds over a > 802.11bconnection, but using Windows Explorer takes less than a second. > Thegood news is that after one to many cups of coffee, I believe I have > asolution to the problem. Here's the details of what I found and how I > discovered the solution. > > After checking out the source from CVS I hunted down the FileVFS > classand it's inner class LocalDirectoryEntry. As a test, I then > hard-coded in values for all but the 'name', 'path' and 'type', thus > eliminating the remaining calls on the File object. To my surprise, > this dropped the speed from 17 seconds to around 2 seconds. I then > restored the calls for each attribute one-by-one and I found that no > single attribute was slow, each one contributed 3-4 seconds to the load > time. So clearly there seemed to be an issue with the java.io.File > object and how it accessed attributes. A little google searching turned > up JSR-203 (originally targeted for JDK1.5, now targeted for JDK1.6) > that will add support for bulk-retrieval of file attributes. Further > review of the java.io.File class indicated that as suspected, it only > retrieves one attribute at a time from the underlying file system. So > at that point it was clearthat Java was to fault and for a while I was > concerned that nothingcould be done. > > In disbelief that such a flaw existed, I decided to give theJFileChooser > demo that comes with the JDK a try and see if it had thesame slowness > when using the detail view and accessing the same networkdirectory. Once > again I was surprised because it seemed thatJFileChooser listed the > detail view of the directory in only 1 second.Further, I tried using the > jEdit File Browser from my Linux desktop tobrowse the same network drive > and I found that it also only took 1second. So apparently this flaw is > only an issue under Windows andapparently the Sun engineers did > something to get JFileChooser's accessto attributes under windows > running faster then what java.io.File provided. > > So into the JFileChooser source I went and after many hours of > pouringover all the details and running a number of tests, it looks like > Sunspecifically addressed this slowness issue in there code by doing > thefollowing: > > 1. JFileChooser gets it's file listing from the the FileSystemView > classin the 'javax.swing.filechooser' package, not from java.io.File. > Youcall FileSystemView.getFileSystemView() to get an instance of the > classand then you call fsv.getFiles() to get your file listing. > The'getFiles()' method returns an array of 'File' objects, which in > thecase of Windows, are actually instances of > the'sun.awt.shell.Win32ShellFolder2' class that subclasses > 'java.io.File'.Looking through the source code for 'Win32ShellFolder2' > reveals that theclass performs native bulk retrieval of certain > attributes and that itoverrides the 'isHidden()' & 'isDirectory()' > method of the 'File'class. Oddly though, the class does not override > the 'length()','lastModified()', 'canRead()' or 'canWrite()' methods > which means thespeed of those methods does not change. Why this is the > case isexplained in point 2. > > 2. JFileChooser only accesses the attributes for the files that > arelisted in the visible area of the JTable. Currently jEdit's > browser,lists all the files in a directory, creates a DirectoryEntry > instancesfor each 'File' and copies each attribute from the File to > theDirectoryEntry. In contrast, JFileChooser lists all the files in > adirectory but does not access the attributes for a given file until > theTableModel.getValueAt() method is called while rendering the > visiblearea of the JTable. This allows the FileBrowser to display very > fastsince it only access attributes for the 30 or so files visible in > thebrowser at any time. However, there are two attributes that > JFileChooser mustaccess for each file before displaying any files. The > isHidden() andisDirectory() properties are necessary for the model to > render anycontent, which is why those attributes are accessed in a > native bulk waythrough the 'Win32ShellFolder2' class. > > So with this gained insight I proceeded to make the necessary changes > tothe jEdit 4.3 pre 2 code base that I have checked out.Making the first > change to jEdit was straight forward, I modified > theFileVFS._listDirectory() method to use FileSystemView.getFiles() > insteadof File.listFiles() and the result was the load time dropped from > 17seconds to 14 seconds. > > Implementing the second change was a bit more involved. Since I > neededto delay access the to a file's attributes as long as possible, I > had tomodify VFS.DirectoryEntry so that it provided access to it's > fields(name, path, symlinkPath, deletePath, type, length, hidden, > canRead &canWrite) through methods. That way I could lazy load the > attributesfrom the File class when a given method was called. This was > long andtedious since every reference to a given field had to be changed > to theappropriate method call. I then had to > modifyVFSDirectoryEntryTable.resizeColumnsAppropriately() so that it did > notcalculate the width of the attribute columns based on the width of > thevalues. It still calculates the width of the name column since > it'sfast to read the file name, but the attribute columns are hard set > to aspecific widths based on the maximum likely value of the attribute. > Forinstance the last modified column would not have a value larger > than"12/12/12 12:12 PM" so I calculate the width based on that > staticvalue. This solution may not be perfect since the Browser is also > usedfor other types of file views which may have different attributes > that arenot as static in their width, but I'm hoping a solution to this > issuecan be found. That was pretty much it for the changes and with > thesecond change in place the load time dropped from 14 seconds to 1 > second. > > I'm planning on building a special 4.2 final build with these changes > inplace since my company needs this fix soon and 4.3 is still in > earlydevelopment. > > Any thoughts? Is there a chance this could be changed for 4.3? > > Thanks, > > -Josh Gertzen > > > > > ------------------------------------------------------- > This SF.Net email is sponsored by: IntelliVIEW -- Interactive Reporting > Tool for open source databases. Create drag-&-drop reports. Save time > by over 75%! Publish reports on the web. Export to DOC, XLS, RTF, etc. > Download a FREE copy at http://www.intelliview.com/go/osdn_nl |
|
From: Joshua G. <pr...@co...> - 2005-02-07 14:50:36
|
Slava Pestov wrote: > Thank you very much for tracking this down! I will incorporate your > suggestions in 4.3pre2. Thanks, I look forward to seeing it in future releases. jEdit is the best code editor that I have ever found and I'm happy that it will no longer be looked down upon due to this issue. The sad part is that Sun will not improve the performance of java.io.File until JDK1.6. Sometimes, I really wonder about them. Manfred Usselmann wrote: > I regularly have to open files from directories on Netware drives > containing several thousand source files, which I always needed a lot > of patience for. > > Now it's really fast. A huge improvement. I'm glad I could help! Yogesh Kanitkar wrote: > Can we use some of the above suggested technique for improving FTP > browsing. If the retrieval of file attributes and names via FTP can be done in an incremental way, then I'm sure the plugin could be adjusted in a similar way. However, I would suspect that this is not the case, and that the FTP plugin simply parses the output of a 'dir' listing, but I'm not an expert on it. Francis Dob wrote: > Jcifs (http://jcifs.samba.org/) which is an smb implementation > also performs faster, than java.io.File. Hmm, that's a cool library, I'll have to keep in mind for future projects. I haven't read the manual on this, but I would suspect that it requires the java application to directly manage the network connection to shares, which would mean that jEdit's browser could not simply use existing mapped drives under Windows. Therefore something like this would work best as a plugin for jEdit that works similar to how the FTP plugin does. For people who need blazing SMB/CIFS speed it might be worth it to maintain the connections within jEdit. -Josh Gertzen |