Discussion:
[ jEdit-devel ] Solution to Slow File System Browser under Windows
Joshua Gertzen
2005-01-31 01:53:49 UTC
Permalink
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
Patrick Wright
2005-01-31 04:52:00 UTC
Permalink
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
Post by Joshua Gertzen
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
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
Joshua Gertzen
2005-02-02 00:58:20 UTC
Permalink
Post by Patrick Wright
What a cool and excellent analysis!
Thanks, it took a while to put it together.
Post by Patrick Wright
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.
Post by Patrick Wright
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
Joshua Gertzen
2005-02-02 06:06:16 UTC
Permalink
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
Manfred Usselmann
2005-02-03 05:10:56 UTC
Permalink
Hi Josh,
Post by Joshua Gertzen
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
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 ***@icg-online.de
Slava Pestov
2005-02-02 21:10:57 UTC
Permalink
Thank you very much for tracking this down! I will incorporate your
suggestions in 4.3pre2.
Post by Joshua Gertzen
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
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
Joshua Gertzen
2005-02-07 12:52:33 UTC
Permalink
Post by Slava Pestov
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.
Post by Slava Pestov
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!
Post by Slava Pestov
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.
Post by Slava Pestov
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

Francis Dobi
2005-02-03 15:44:05 UTC
Permalink
Just a comment on this.
Jcifs (http://jcifs.samba.org/) which is an smb implementation also performs faster,
than java.io.File.
I think it retrieves all file attributes in a bunch.

Francis

__________________________________________________
Do You Yahoo!?
Tired of spam? Yahoo! Mail has the best spam protection around
http://mail.yahoo.com
Yogesh Kanitkar
2005-02-03 19:12:03 UTC
Permalink
Thanks,
for the detailed explanation & solution to an age old problem.

Can we use some of the above suggested technique for improving FTP
browsing. If some one could port the changes to FTP plugin it will be
wonderfull.

-yogesh

On Thu, 3 Feb 2005 09:42:06 -0800 (PST), Francis Dobi
Post by Francis Dobi
Just a comment on this.
Jcifs (http://jcifs.samba.org/) which is an smb implementation also performs faster,
than java.io.File.
I think it retrieves all file attributes in a bunch.
Francis
__________________________________________________
Do You Yahoo!?
Tired of spam? Yahoo! Mail has the best spam protection around
http://mail.yahoo.com
-------------------------------------------------------
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
--
-----------------------------------------------
jEdit Developers' List
https://lists.sourceforge.net/lists/listinfo/jedit-devel
--
-Yogesh Kanitkar
Continue reading on narkive:
Loading...