| [ Return to Bugs & Features | Roadmap 1.1 | SVN ⇄ GIT ]
STR #654
Application: | FLTK Library |
Status: | 1 - Closed w/Resolution |
Priority: | 2 - Low, e.g. a documentation error or undocumented side-effect |
Scope: | 3 - Applies to all machines and operating systems |
Subsystem: | Core Library |
Summary: | Fl_File_Chooser: file completion to large directory can loose entire pathname |
Version: | 1.1.6 |
Created By: | greg.ercolano |
Assigned To: | mike |
Fix Version: | 1.1.7 (SVN: v4010) |
Update Notification: | |
Trouble Report Files:
Trouble Report Comments:
|
#1 | greg.ercolano 14:30 Dec 15, 2004 |
| When typing in a pathname, as you encounter a large network directory, the interface will freeze up while the directory is loading. (problem #1)
If you continue typing while the interface is frozen, keystrokes are buffered.. then when the directory finishes loading up, it catches up with the missed keystrokes, which apparently cause the entire pathname to become selected briefly, causing the entire pathname, or apparently random parts of it to be replaced with the buffered keystrokes, loosing the path the user typed so far. (problem #2)
#1 isn't so bad to the user, but it sounds like this can maybe be avoided by doing eg. an Fl::check() while loading the directory contents. Keystrokes should at least cancel the directory loading so the keystrokes can be shown to the user.
#2 is bad, because the user's typing can be completely lost. A user typing in a long pathname to a network volume can get zapped at any transition to a new directory, loosing all their text if they don't pause their typing each time they traverse into a new directory.
| |
|
#2 | greg.ercolano 14:40 Dec 15, 2004 |
| Followup: in the case of #2, what appears to be happening is the CWD is getting tossed into the Filename field when the interface recovers, causing the cursor to appear in the middle of the cwd path, where subsequent typing is inserted at that new position.
For instance if my cwd is /usr/local/src/fltk/test, and I surf to a big directory:
Filename: /net/tmp/
..and continue typing while the interface is briefly frozen, when it recovers, and starts unbuffering the keystrokes, the Filename field changes to:
Filename: /usr/local/src/fltk/test ^
..with the cursor positioned above the '^' shown above, which appears to be the old cursor position of the /net/tmp path.
Continued typing causes text to be inserted into the middle of the word 'local'.
| |
|
#3 | greg.ercolano 15:16 Dec 15, 2004 |
| Another very weird behavior, possibly related to "Problem #2" in the original report:
1) Run the file chooser
2) Click the folder button
3) Hit the letter 'a' over and over. The cwd is appended to the line each time, causing numerous copies of the cwd each time you hit 'a'. Meanwhile, the cursor remains at the beginning of the line. | |
|
#4 | greg.ercolano 10:54 Jan 09, 2005 |
| Regarding slowness; I think I identified why it's so slow for large network directories.
I noticed that the older file browser (Bill's original browser?) was very fast at loading the directory in question; <1 second. But the new browser took ~5 seconds.
I ran strace() on the fltk binary at one point, and found that just opening a browser to a large directory stat()ed each file a total of 5 times..! (not typing or navigating anything). eg:
---- [..] stat64("//meade/net/tmp/Doc1.htm", stat64("//meade/net/tmp/Doc1.htm", stat64("//meade/net/tmp/Doc1.htm", stat64("//meade/net/tmp/Doc1.htm", stat64("//meade/net/tmp/Doc1.htm", stat64("//meade/net/tmp/Doc1_files", stat64("//meade/net/tmp/Doc1_files", stat64("//meade/net/tmp/Doc1_files", stat64("//meade/net/tmp/Doc1_files", stat64("//meade/net/tmp/Doc1_files", stat64("//meade/net/tmp/Doc1_files", stat64("//meade/net/tmp/Document.rtf", stat64("//meade/net/tmp/Document.rtf", stat64("//meade/net/tmp/Document.rtf", stat64("//meade/net/tmp/Document.rtf", stat64("//meade/net/tmp/Document.rtf", stat64("//meade/net/tmp/DropScript-0.5.dmg", stat64("//meade/net/tmp/DropScript-0.5.dmg", stat64("//meade/net/tmp/DropScript-0.5.dmg", stat64("//meade/net/tmp/DropScript-0.5.dmg", stat64("//meade/net/tmp/DropScript-0.5.dmg", [..] ----
Since each stat() operation is a network operation on drives served by remote fileservers, this means really slow performance for large directories with hundreds of files, let alone the thousands people often encounter in computer graphics production companies (my target users).
Will try to track this down if I can.. | |
|
#5 | greg.ercolano 20:42 Jan 09, 2005 |
| One problem explaining the slow initial startup time for the Fl_File_Chooser is Fl_File_Chooser::showChoiceCB() effectively calls Fl_File_Browser::load() twice in a row (rescanning the entire dir twice) via this code:
---- snip void Fl_File_Chooser::showChoiceCB() { [..] fileList->filter(pattern_); // calls load() the first time rescan(); // calls load() the second time } ---- snip
..so either 'filter()' shouldn't be calling load(), or the rescan() call is extraneous..?
DEBUG PROCEDURE This was found by using gdb on the test/file_chooser app, and setting a breakpoint to the Fl_File_Browser::load() method:
# gdb file_chooser (gdb) break Fl_File_Browser::load(char const*, int (*)(dirent**, dirent**)) (gdb) run [..]
..then doing several 'cont's until the browser is opened by clicking on the folder button. Here's a copy of the stack for each of the two calls:
*** First time: #0 0x08057dfe in Fl_File_Browser::load(char const*, int (*)(dirent**, dirent**)) () #1 0x080581a4 in Fl_File_Browser::filter(char const*) () <-- filter() calls load() #2 0x0805ad9b in Fl_File_Chooser::showChoiceCB() () <-- showChoiceCB() calls filter() #3 0x0805a986 in Fl_File_Chooser::filter(char const*) () #4 0x0804c1fc in show_callback() () [..]
*** Second time: #0 0x08057dfe in Fl_File_Browser::load(char const*, int (*)(dirent**, dirent**)) () #1 0x0805acd9 in Fl_File_Chooser::rescan() () <--- rescan() calls load() #2 0x0805ada3 in Fl_File_Chooser::showChoiceCB() () <--- showChoiceCB() calls rescan() #3 0x0805a986 in Fl_File_Chooser::filter(char const*) () [..]
| |
|
#6 | greg.ercolano 21:38 Jan 09, 2005 |
| Another cause of extra calls to load():
Before the browser is even opens, the directory can end up being scanned several times during Fl_File_Chooser construction.
The Fl_File_Chooser() constructor calls value() and type() after the dir is set, which both end up calling load():
First time: #0 Fl_File_Browser::load(..) #1 Fl_File_Chooser::rescan() <-- rescan() calls load() #2 Fl_File_Chooser::directory(..) <-- directory() calls rescan() #3 Fl_File_Chooser::value(char const*) <-- value() calls directory() #4 Fl_File_Chooser (..)
Second time: #0 Fl_File_Browser::load(..) #1 Fl_File_Browser::filetype(..) <-- filetype() calls load() #2 Fl_File_Chooser::type(..) <-- type() calls filetype() #3 Fl_File_Chooser() <-- constructor
There's a lot of ways to prevent this, but I'm not sure how to patch it, as it seems to have more to do with how the designer wants the API to work.
One approach is to use 'damage' flags, so that rescans are deferred until an event loop, similar to fltk's own widget redraw approach.
Another would be to disallow rescans unless the window is open.
Yet another, either a global flag, or per-method flag that lets one prevent rescans for efficiency, eg:
void value(val, int rescan=1); void type(val, int rescan=1);
It seems the question of 'when to scan' needs to be incorporated in the design of Fl_File_Chooser, as that appears to be where a lot of the slowness is caused.
| |
|
#7 | mike 10:27 Feb 05, 2005 |
| Fixed in Subversion repository.Please try the attached patch for a fix for at least the large directory speed issue.
| |
|
#8 | mike 13:47 Feb 24, 2005 |
|
| |
[ Return to Bugs & Features ]
|
| |