If you want criteria to choose directory structure, AFAIK usual approach is to take relevant benchmarks, code alternatives and test performance. The result may be something like "if less than 50 entries, then use linear search, otherwise use a search tree". AVL trees and similar approximately balanced search trees offer you upper bound on number of memory accesses which is similar to average. And this upper bound is explicit. Depending on point of view such trees give you warranty of modest access time (optimist point of view) or warranty that your access time will be close to worst case (pessimist point of view). As you noted, in system with cache upper bound gets much higher due to possible cache misses. Still, this upper bound is likely to be much lower than upper bound for linear search or for a hash table.
AVL trees are considered "in memory" data structure, you could try to use them in different setting, but this is non-standard use so do not expect much help from texts (or form other folks). For use on block media variants of B-trees are preferable (more modern variants are considered significantly better than orignal B-trees).
Various approximately balanced trees offer similar average performance. In many cases performance differences between them do not matter. If you care about differences, then you need to do your own measurements. In fact, binary trees without balancing have average search length only some tens of percents longer than approximately balanced trees, so without measurement it is hard to say if approximately balanced trees will give you better average performance than simple binary trees (of course without balancing worst case bound is gone).
Long ago I used (a little) OS/360. It gave you a lot of choices for "access methods" and various parameters. For users it was a pain to specify all that info and AFAIK frequently led to suboptimal performance. AFAIK it was rather common experience that various user controlled tuning parameters may be good for really stupid software, but usualy program has more info (due to statistics from past use) than users, so can better tune parameters.
Concerning directories in convential OS note that users are much slower than computer. So user-created directories by necessity will be quasi static with infrequent access. So other aspects will not matter much. Things may be different for directories used by a program, but OS interaction tends to be much heavier than purely user-space things, so normal programs are unlikely to make very heavy use of directories. Of course, heavy use may arise if programmer did not think about consequences of say user actions or configuration settings. But if programmer did not predict correctly directory use, would you trust him/her to correctly give you information about characteristis of usage?
I inherited a website. It has a single "data" directory which as of today contains 108771 files. This is on traditional Linux filesystem that AFAIK uses linear search to find directory entry. Yet the website works. Performance is rather unimpressive (about
5 pages/s) but seem to be a bit better than some other widely used approaches. And filesystem searches seem to have almost no impact on performance (most accesses to the site do not need to look at "data" directory). If I were to create site from scratch I would probably use a classic approach of tree of directories. But given that site works, up to now I did not try changing its use of "data" directory (well, I trimmed it a bit, so some tens (or maybe hundreds) of thousends of files are no longer there).Theoretical setup for large family of search trees is that you have otherwise arbitrary keys which you can compare. Since nature of keys is not specified, the best you can do is to compare number of comparisons. If you have extra information, you can use it. But densly packed unique integers as keys are really different thing. Already, say 256-bit integers as keys (for example they may be SHA-256 hashes of something) are really not much simpler than arbitray keys.
Well, for my non-filesystem purposes I looked at string storage. My conclusion was that for _my_ purpose hash table was the best. Basically, each tree node needs extra space for pointers. That nullifies most if not all savings due to sharing some characters in the keys. I store keys in aligned way, null padded to whole words. That way I can use word operations for comparison and hashing. Average number of trials per hash table access is low enough to make a difference compared to a tree. And IME hash table is slightly simpler to implement (I implemented AVL tree, did not try more fancy kinds of trees).
I would probably _not_ use hash table for filesystem case. In fact, I would probably start with linear search and look for alternatives only if I had evidence that linear search is inadequate for my use.
You rebalance AVL tree only on insertion or removal, each of them performs equvalent of a search as part of its work. When inserting you need at most one rebalancing step, when deleting you may have multiple rebalancing steps, but average tend to be low.
A guy wanted to optimize access to record fields in a compiler. Originally that was linear search on a list. The guy wrote code that sorted the fields and created table for binary search. Then he did measurements which indicated that above
50 fields new approach was faster, while below linear search was faster. So he put the threshold in the code to use faster method.This is well-known approach. It is for you to decide if you need something like this. And if you do, it is for you to do measurements. Similar things may appear as excercises in various books, but no text will spend a lot of time on this: basic idea is obvious once you heard it once, details depend too much on specific problem.
For me answer is "essentially never", I do not have '\Windows' on my machine. I can not access '\Users\Me' as there is no such thing on my machine. If you ask about "system directories" on my machine, programs access them to read configuration files and load shared libraries. And some things are accessible only to programs having appropriate priviledges. As you probably know part of OS interface is via fake filesystem.
I mean that there is general knowlege and there are specific situations. People can provide you with general knowlege and possibly with specific information about situations they met. You ask as if you thougt that issues specific to your problem are part of general knowlege. AFAICS they are not.
Effects of media are considerd via access time, that covers discs and reading from flash. Flash did not exist when classic texts were written, so they do not discuss it. Some newer texts mention flash.
Concerning distribution of keys, classic analysis uses uniform distribution. In systems with caches this is worst case, any other distribution tend to more or less prefer some location which tends to increase cache hits. Some data structures explicitely try to take advantage of nonuniform distribution. OTOH if you did excercises say in my copy of Tanenbaum "Computer architecture" you will see that with good data structure distribution must be very nonuniform to give you advantage (that is trying to "optimize" data structure for nonuniform use actually may loose).
A lot of folks write single-threaded applications. I never programmed a Mac, but I heard Mac programeres repeating basic mantra "you can call GUI operations only from GUI thread". AFAIK several major commercial packages are mostly single threaded. Only small performace critical part is multithreaded. Usually a machine runs a lot of things. OS is supposed to give illusion that a program has dedicated access to the machine. Which may work well enough or not. But if other things have negative impact, then program my be given dedicated machine. So assuming dedicated machine in many cases works well enough.
On slightly deeper level, if you want to spread computations onto multiple machines, then you face new issues. If those issues overlap enough with algorithmic issues, then you enter domain of parallel algorithms. But it makes no sense to study _all_ algorithms as parallel ones: same present troubles so that currently it makes no sense to spread algorithm work onto multiple threads/machines. In other cases trivial approach, that is running multiple independent copies gives all what is needed.
In slightly different spirit, small MCU-s are now cheap enough that you can dedicate one to various time critical tasks. I know that you decided to take different direction, but one can go quite far by using per-task CPU-s with modest amount of communication (so not in vacuum, but not far from independent).
That is what Minix did. Also Wirth in eighties advocated single thread for whole software stack (OS and applications). Works reasonably well in many cases, but there were serious drawbacks. Wirth approach lives up to now and has some fans, but instead of being a standalone OS it is now just a single single-threaded program running under conventional OS.
My impression is that Linux uses per directory locks.
Issues of this sort have a lot of commonalities between themselves and loose connection with algorithms. So they are considered a separate subject.
If other things have more need of cache, they are presumably more important and it does not matter that they evict (part of) your tree. The point is that under random access frequency of access decays pretty fast as you go down the tree. That is enough to understand interaction of the tree with the cache.
Well, atomic operation by definition is not interruptable, so in correct system it is _not_ interrupted. Concerning trees on disc: main issue is access to blocks and that is taken into account in algorithms from B-tree family. AVL trees do not address this concern.
Well, by paging above I understand having virtual memory bigger than physical RAM and implied by this exchange of data with backing store.
Sure, you can use paging hardware for various puropses. You need to look at page fauls and TLB misses. If handling of them takes only little time (which AFAICS is a frequent case), then there is no reason to think about it. If it takes so much time that this matter, then you are back to paging friendly data structures.