Mark Knecht posted on Mon, 01 Feb 2010 06:42:24 -0800 as excerpted:

> On the new machine I've set it up as dual-head which is working nicely
> for all the basic stuff, and in general pretty nicely for running
> VMWare/WinXP on the second screen for most of the day. I have a few
> issues, like the mouse can become __very__ laggy in VMWare at times
> but other than that all the basics are there and working well enough
> to get some work done. I'm using XFCE4 at the moment.

I wouldn't do vmware as it's servantware, and thus don't know a /whole/ 
lot about it, but here's a bit of general wisdom on lagginess/latency 
issues.  Was it you that did a bunch of sound related stuff?  If so, you 
likely know (and have it set as appropriate) some of this already.

First, what's your kernel tick time set for, 100, 250, 300, 1000 ticks per 
second?  Obviously higher ticks will help with latency, but it negatively 
affects thruput.  Also note that with SMP (multiple CPUs/cores), each one 
ticks at that, so you can often turn down the ticks a notch or two from 
what you'd normally have to run, if you're running SMP.

Second, what's your kernel preemption choice?  No-preemption/server, 
voluntary-preemption/desktop, or full-preemption/low-latency-desktop?  
Again, there's a trade-off between latency and thruput.  If you're worried 
about mouse lagginess, server isn't appropriate, but you can choose from 
the other two.

Third, there's additional low-latency kernel patches available...  I'll 
leave that alone as I run vanilla kernel.

Fourth, there's I/O scheduling.  Due to the way I/O works, often, the 
kernel stops doing much of whatever else it was doing when it's handling
I/O.  What I/O scheduler are you running, and have you noted the disk 
activity LEDs blinking furiously (or conversely, no disk activity at all) 
during your latency?  How's your memory situation?  How far into swap do 
you typically run?  Do you run /tmp and/or /var/tmp on tmpfs?  
Particularly when you're emerging stuff in the background, having 
PORTAGE_TMPDIR pointed at a tmpfs can make a pretty big difference, both 
in emerge speed, and in system responsiveness, because there's much less
I/O that way.  That's assuming, of course, that you have at least a couple 
gigs of memory and aren't already starved for memory with your typical 
application load.

Fifth, priority.  Have you tried either higher priority for the vmware 
stuff or lower priority for other things, portage, anything else that may 
be hogging CPU?  (For portage, I like to set PORTAGE_NICENESS=19, which 
automatically sets scheduler batch mode for it as well.  The priority is 
as low as possible so it doesn't interfere with other things to the extent 
possible, while the batch mode means it gets longer timeslices, too, thus 
making it more efficient with what it does get.)

The above, save for priority, is mostly kernel related, so should have an 
effect regardless of whether your vmware vm is mostly kernel or userland 
implementation.  The below is mostly for userland so won't work as well if 
vmware is mostly kernel.  I don't know.

Sixth, are you using user-group or control-group (aka cgroup) kernel 
scheduling, or not, and how do you have it configured?  The kernel options 
are under general setup.  Cgroup scheduling gets rather complicated, but 
user-group scheduling is reasonably easy to configure, and it can make a 
**BIG** difference on a highly loaded system.  Thus, I'd suggest user-
group scheduling.

To enable user-group scheduling, enable Group CPU scheduler, and 
(normally) Group scheduling for SCHED_OTHER, which is everything OTHER 
than real-time threads.  I leave the scheduling for SCHED_RR/FIFO off, as 
unless you know what you are doing and have specific reason to mess with 
real-time scheduling, it's best NOT to mess with it, because it's a VERY 
easy way to seriously screw your system!

Again, you probably do NOT want to mess with control group support, unless 
you have specific needs beyond what user-group scheduling will do for you, 
because that gets quite complicated.  Therefore, leave that option off, 
and under Basis for grouping tasks, make sure it says "(user id)".  
That'll be the only option unless you have control group support enabled.

Now, how do you use it?  Simple.  For each user currently running at least 
one application, there's a /sys dir with the user id number (not name, 
number, you need to know the number), /sys/kernel/uids/<uid>.  In this 
directory, there's a file, cpu_share.

The contents of this file is the relative CPU share the user will get, 
compared to other users, when the system is under load and thus has to 
ration CPU time.  The default share for all users save for root is 1024.  
Root's default share is double that, 2048.

So here's how it works.  With user-group scheduling enabled, instead of 
priority alone determining scheduling, now priority and user determine 
scheduling.  Once the system is under load so it matters, no user can take 
more than their share, regardless of what priority their apps are running 
at.  If you want a particular user to get more time, double its share.  If 
you want to restrict a user, half its share.  Just keep in mind that root 
has a 2048 share by default, so it's wise to be a bit cautious about 
increasing too many users up to that or beyond unless you boost root as 
well, just to be sure.  Various system housekeeping threads, kernel 
threads, etc, use time from the root share, so you want to be a bit 
careful about increasing other users above it, or the housekeeping 
threads, disk syncs, etc, might not have the time to run that they need.  
However, increasing just one single user to say 4096 shouldn't starve root 
too badly even if that user gets a runaway app, as root will still be 
getting half that time, as long as everything else remains at 1024 or 
below.  But obviously, you won't want to put say the portage user at 4096!

I routinely bump my normal user to 2048 along with root, when I'm running 
emerges, etc.  This is with FEATURES="userfetch userpriv usersync" among 
others, so portage is spending most of its time as the portage user, thus 
with its default 1024 share.  Boosting my normal user to 2048 thus ensures 
that it (along with root) gets twice the time that the portage user does, 
but even should one of my normal user apps go into runaway, root still 
gets nearly half the CPU (more precisely, just under 40%, since root and 
my normal user would each be getting double the portage user, with other 
users not taking much as they'd not be in runaway, so root and the normal 
user would get nearly 40% each, while portage would get nearly 20%, with 
perhaps the other non-runaway users taking a percent or two, thus the 
"nearly") if it needs it, which should be plenty to login as root and kill 
something, if I have to, or to shut down the system in an orderly way, or 
do whatever else I'd need to do.

Even if I were to run my normal user at 4096 and it would have a runaway, 
it would get 4 shares, portage would get one, and root would get two, so 
even then, root would get nearly 2/7 or about 28% share, with the runaway 
user getting double that or about 56% and portage getting about 14%.  Even 
28% share for root should be enough, so that's reasonably safe.  However, 
I'd be extremely cautious about going over 4096, or increasing a second 
user's share to that too, unless I increased root's share as well.

That's actually simplifying it some, tho, as the above assumes all the CPU 
hogs are running at normal 0 priority/niceness.  But as I mentioned, I 
have PORTAGE_NICENESS=19, so it's running at idle priority, which would 
lower its claim to the portage user share dramatically.  Basically, at 
idle priority, it'd get very little share if there was another run away 
(normal priority) process, as ANY user.  (The scheduler /does/ normally 
give /every/ process at least one timeslice per scheduling period, even at 
idle priority, to prevent priority inversion situations in case of lock 
contention and the like.)  So the above percentage scenarios would be more 
like 48/48/1/3 (root/user/portage/other) in the 2048/2048/1024s case, and 
32/65/1/2 in the 2048/4096/1024s case.  Basically, the portage user, even 
tho it's using all the CPU it can get, would still fall into the noise 
range along with other users, because it's running at idle priority, and 
root would thus get close to half or close to a third of the CPU, with the 
normal user at equal share or double share of root, respectively.

I've had very good results using that setup.  Just for curiosity' sake, I 
tried running ridiculous numbers of make jobs, to see how the system 
handled it.  With this setup (PORTAGE_NICENESS=19, portage user at 1024 
share, root at 2048, and normal user at either 1024 or 2048), I can 
increase make jobs without limit and still keep a reasonably usable 
system, as long as the memory stays under control.  This is MUCH more so 
than simply running PORTAGE_NICENESS=19 but without per-user scheduling 
enabled.  In practice, therefore, the limit on make jobs is no longer CPU 
scheduling, but the amount of memory each job uses.  I set my number of 
make jobs so that I don't go into swap much, if at all, even with 
PORTAGE_TMPDIR pointed at tmpfs.  Because swapping is I/O, and I/O, due to 
the way the hardware works, increases latency, sometimes unacceptably.

Actually, my biggest thread test has been compiling the kernel, since it's 
so easily parallellizable, to a load average of several hundred if you let 
it, without using gigs and gigs of memory (yes it takes some, but nowhere 
near what a typical compile would take at that number of parallel jobs) to 
do it.  I do my kernel compiles as yet another user (what I call my 
"admin" user), so like portage, it gets the default 1024 share.  But I 
don't set niceness so it's running at normal 0 priority and taking its 
full share against other 0 priority users.  Compiling the kernel, I can 
easily run over a hundred parallel make jobs without seriously stressing 
the system.  But even there, with user scheduling enabled and at normal 
priority so the kernel compile is taking all the share it can, the memory 
requirements are the bottleneck, not the actual jobs or load average, 
because the kernel per-user scheduling is doing its job, giving my other 
non-hog users and root the share they need to continue running normally.

So assuming vmware is running in userspace and thus affected by priority 
and user-groups, I'd definitely recommend setting up user-groups and 
fiddling with its share, as well as that of the rest of the system, along 
with the other steps above.

The one caveat with user-group scheduling, is that the
/sys/kernel/uids/<uid> directories are created and destroyed dynamically, 
as apps run and terminate as those users.  It's thus not (easily) possible 
to set a static policy, whereby a particular UID /always/ gets a specific 
non-default share.  There was a writeup I read back when the feature was 
first introduced, that was supposed to explain how to set up an automatic 
handler such that every time a particular UID appeared, it'd write a 
particular value to its cpu_share file, but as best I could tell, the 
writeup was already out of date, as the scripts that were supposed to be 
called automatically according to the writeup, were never called.  The 
kernel hotplugging (and/or udev, or whatever was handling it) had changed 
out from under the documentation, even as the feature was going thru the 
process of getting the peer approval necessary to be added to the mainline 
kernel.  So I've never had an automatic policy setup to do it.  It could 
certainly be done using a file-watch (fnotify/dnotify, etc, or polling of 
some sort), without relying on the hotplugging mechanism that was supposed 
to work that I could never get to work, but I've not bothered.  I've 
simply created scripts to echo the desired numbers into the desired files 
when I invoke them, and run them manually when I need to.  That has worked 
well enough for my needs.

(Now you see why I'm not going into cgroups?  user-group scheduling is 
actually quite simple.  Imagine the length of the post if I was trying to 
explain cgroups!)

> The one place where I've been a bit disappointed is when the VGA
> drivers need to switch resolutions to play a game like Tux Racer then
> instead of two desktops I'm seeing one desktop duplicated on both
> monitors. Is this normal or is there some general way to control this?
> I'd really like the game on one monitor and just have the other stay
> black.

The problem here is that most resolution switchers simply assume a single 
monitor.  Before the X RandR extension, there was really no standard way 
to reliably handle multiple monitor setups (xinerama, merged-framebuffer, 
and proprietary or semi-proprietary methods like that used by the nvidia 
and frglx drivers, were all in use at various times by various hardware/
drivers, and for all I know there were others as well), so assuming a 
single monitor was pretty much the best they could do.

RandR has solved the standardization problem, but few games have upgraded 
to it, in part because it's apparently "rocket science" to properly 
program it.  The xrandr CLI client works, but all too often, the X 
environment tools are simply broken.  KDE for example has had a tool 
that's supposed to handle multiple monitors, changing resolutions, etc, 
for some time, but on all three sets of hardware and drivers I've tried it 
on, both the kde3 version and the kde4 version thru 4.3.4, it has screwed 
things up royally if you're using more than one monitor.  Only xorg's own 
xrandr gets it right, and that's a CLI client, with a slew of options to 
read about and try to master, before you can properly run it.  I've 
scripted a solution here using it, hard-coding some of the options I don't 
change into the script (could be a config file) thus making my script 
simple enough to run from the command line (or invoke from a menu entry) 
without having to remember all the complicated syntax, but that's not 
going to work for the CLI-phobic.  And if the X environments can't get it 
working correctly for many users even with the documentation and the 
xrandr code to follow, what are the games folks supposed to do?  So they 
simply continue to assume only a single monitor... and screw things up for 
those of us with more than one, at least if we prefer to run them in other 
than clone mode.

Because that's what's happening.  When the games, etc, trigger the old 
single-monitor resolution change API, it causes xorg to switch to clone 
mode, running all monitors at the same resolution, showing the same thing.

FWIW, the solution I've found, as I mentioned, is a script setup to invoke 
my preferred resolutions, in my preferred non-clone modes, retaining my 
preferred "stacked" monitor orientation, by invoking xrandr with the 
appropriate parameters to do so.

Thus I use my script (which uses xrandr) to set the resolution I want, and 
set the game not to change resolution -- to run in a window or whatever, 
instead.  I run kde, and with kwin's per-app and per-window config 
options, I set it up to always put the windows for specific games at 
specific locations, sometimes without window borders etc.  Between that 
and triggering the resolution settings I want with my xrandr script, I can 
get the game running in a window, but that window set to exactly the size 
and at exactly the location of the monitor I want it to run on, while the 
other monitor continues at its configured size and showing the desktop or 
apps it normally shows.

"Works for me!" =:^)

>    More disturbing is when I exit the game I'm left with both desktops
> displaying the same things and neither is exactly my original first or
> second desktop but rather a combination of the two which is fairly
> strange. (Desktop #1 icons with Desktop #2 wallpaper)

Both desktops (monitors, I assume, that's quite different from virtual 
desktops, which is how I'd normally use the term "desktop") displaying the 
same thing is simply clone mode.  You can try using your X environment 
resolution tool (if xfce has such a thing, kde does and I think gnome 
does) to switch back to what you want, but as I said, don't be surprised 
if it doesn't work as expected, because they've really had problems 
getting the things working right.  xrandr gets it right, and you'd /think/ 
they could if /nothing/ else read its code and use similar tricks, it /is/ 
open source, after all, but kde certainly hasn't gotten it right, at least 
not for many drivers and hardware, and from what I've read, gnome's 
version isn't a lot better.

But, if you're up for a bit of reading, you can figure out how xrandr 
works well enough to get it to do what you want.  Here's an example, 
actually the debug output of the script I run, showing the xrandr command 
as it's setup and invoked by the script (all one command line):

xrandr --verbose --fb 1920x2400 --output DVI-0 --mode 1920x1200 --panning 
1920x1200+0+0/1920x1200+0+0/20/20/20/20 --output DVI-1 --mode 1920x1200 --
panning 1920x1200+0+1200/1920x1200+0+1200/20/20/20/20

That results in:

1) an overall framebuffer resolution of 1920x2400

2) output DVI-0 being set to resolution 1920x1200, with its top-left 
corner at position 0,0.

3) output DVI-1 being set to a similar resolution (I have two of the same 
model of monitor, 1920x1200 native resolution), but with its top-left 
corner at position 0,1200, thus, directly under DVI-0.

The panning mode stuff (except for the positioning bit) wouldn't be 
necessary here as there's no panning to do, but those are the script 
defaults.  For use of panning mode, see this one:

xrandr --verbose --fb 1920x2400 --output DVI-0 --mode 1280x800 --panning 
1920x1200+0+0/1920x1200+0+0/20/20/20/20 --output DVI-1 --mode 1280x800 --
panning 1920x1200+0+1200/1920x1200+0+1200/20/20/20/20

This keeps the same overall framebuffer size and output orientation 
(stacked), but the outputs are both run at 1280x800, with the panning 
domain set for each one such that as the mouse gets to 20 px from any edge 
of the 1280x800 viewport, it moves the viewport within the corresponding 
1920x1200 panning domain.

Here's one with different resolutions, and with panning when the mouse 
reaches the edge itself (instead of 20 px in) on the lower resolution and 
position one (DVI-1), so I can run a game there, without it trying to pan 
out as near the edge.  I then put the viewport over the game and let the 
game grab the mouse, so I can then play the game without having to worry 
about panning.  If I need to, I can have it "ungrab" the mouse, and have 
panning again on the lower one, or move to the "fixed" upper one and do 
stuff there.

xrandr --verbose --fb 1920x2400 --output DVI-0 --mode 1920x1200 --panning 
1920x1200+0+0/1920x1200+0+0/20/20/20/20 --output DVI-1 --mode 960x600
--panning 1920x1200+0+1200/1920x1200+0+1200/

When I'm finished with the game, or if I want to run normal resolution and 
do something else for a bit, I just run that first command again, and it 
returns me to normal mode as set by that first command.

Unfortunately, kde4 still has a few bugs with multiple monitors, 
especially when switching resolutions.  As mentioned, the kde4 resolution 
switcher itself is entirely screwed up as all it can handle is clone mode 
(there's no way to set separate non-identical top-left corners for each 
monitor), but there's bugs with the plasma desktop as well.  If I do 
happen to select clone mode, or disable one of the monitors using xrandr, 
upon return to normal mode, plasma-desktop is screwed up.  I can fix it 
without restarting X/kde, but it's a hassle to do so, and somewhat trial 
and error, zooming in and out the various plasma "activities", until I get 
it setup correctly once again.  Hopefully, 4.4 has improved that as well.  
I read it has.  We'll see...

>    I'm wondering if other environments handle this better. XFCE is
> pretty lightweight, which I like. I'd gone away from Gnome because of
> the time spent maintaining it on Gentoo but on this machine it probably
> wouldn't be all the bad. Not sure I want KDE but I'm curious as to
> whether anything solves this problem?

Well... kde 3 worked reasonably well in this regard (except its resolution 
switcher wasn't much good either, I used X's ctrl-alt-numplus/numminus 
zooming while it worked, then developed the xrandr scripts I still use 
today when x switched to randr based switching and the numplus/numminus 
zooming didn't work any more, but the desktop at least stayed put), but as 
you can tell, I'm rather frustrated with kde4.

But definitely try xrandr.  It's a pain to learn as it's all CLI options 
not point and click, but it's remarkably good at doing what it does, once 
you know how to run it, and possibly hack up a script or several to take 
the complexity out of it.

>    Logging out of XCFE and then running startx gets everything back
> the way I want, and I don't think I'll play Linux games much, but I'm
> curious as to how well other environments handle this.

As explained, the base problem is that games assume single monitor, which 
X construes as a command to go into clone mode.  The solution is to use an 
external app (such as the xrandr invoking scripts I use) to set the 
resolutions you want, and don't invoke the games' options to change 
resolution or whatever, just have them run in a window.  Then match the 
window size to your desired resolution (enforcing it using your window 
manager, if that's more convenient or necessary), and invoke the script 
(or other external to the game resolution switcher app) changing the 
resolution right before you run the game.

Alternatively, since we're talking about a script already, you could set 
it up so the script runs xrandr to change the resolution as desired, then 
runs the game, then when the game is done, changes the resolution back.

-- 
Duncan - List replies preferred.   No HTML msgs.
"Every nonfree program has a lord, a master --
and if you use the program, he is your master."  Richard Stallman


Reply via email to