Why is it slower to print directly to console/terminal than redirecting? - linux

Why does it take significantly more time to print multiple lines to the terminal rather than redirecting it to a file which seems to be almost instant ?

Primarily, terminals are just plain slow. For every update, they have to:
Parse and interpret any control codes.
Parse, interpret and render any escape codes.
Interpret and account for any multibyte and composed characters.
Update appropriate screen and scroll buffers.
Render this with appropriate fonts.
and possibly do all of the above over again if you use screen or tmux.
Meanwhile, for redirecting to a file, you just have to:
Dump data into RAM (for later writeback to storage).
This step is so minor that it doesn't even register on the terminal's checklist.
This is not something people optimize for, because the speed of your terminal is rarely an issue. The difference between terminals can be 50x (VGA vs fbcon back in the day), and you can time it with a simple time cat somebigfile.txt.

Related

How does console/shell caching/restoration work?

This question is purely out of curiosity; there's no problem to be resolved.
Note: I'm using Konsole on CentOS 7.
When I SSH to a remote box and leave the session inactive for a while, it times out. As a workaround, I use less [some-file] to keep the session active.
Obviously the sessions still break when I suspend the VM at the end of the day.
The next day when I start a new SSH session, everything is normal except that some Konsole functionality doesn't work (namely, clearing scrollback, which I use a lot) for the same terminal window used for the SSH session.
However, after I less a file and quit, two things happen:
Konsole resumes working normally.
Whatever output was in the terminal before I used less is replaced with whatever output was there the previous day, before the session was broken by shutting down the VM I'm SSHing from.
Curiously, this happens for all ~4 concurrent terminals/sessions (each one having its output from the previous day restored). [edit: clarification: each of the ~4 terminals exhibits this behavior when I SSH/less in that particular terminal. Each one resumes its output from the day before. Doing this in one terminal/session is not affecting the other terminals/sessions]
I assume this would happen with any terminal app (e.g. vi, nano, etc.) with its own "gui" and isn't specific to less.
Seems like there's some caching going on. I assume quitting less (or vi, nano, etc.) triggers some sort of shell output restoration in general, but this particular manifestation seems somewhat odd.
Any idea what's going on?
The terminal feature described in the question the alternate screen feature (originally xterm, but copied/imitated by several other terminals including konsole). Depending on the terminal description, you may/may not use this feature.
less and most full-screen terminal programs such as vi send the escape sequences to switch to/from alternate screen if they're defined in the terminal description (i.e., TERM=xterm).
From the description, it sounds as if you're using different tabs in the same instance of konsole, and that it's remembering that your terminal was set to the alternate screen. konsole and some other programs attempt to save/restore "session" information when halted, so that probably seemed like a good thing to save/restore.
While in the alternate screen, terminal programs typically have little or no access to the scrollback region.
You can use tput to send the same escape sequence (without running less):
tput rmcup
(If the terminal description doesn't have a definition for that, it'll do nothing).
Further reading:
Why doesn't the screen clear when running vi?

Remove delay after first symbol on key hold

When I press and hold a key, a first symbol is typed, then there is a little delay, and then other symbols are typed fast. Something like this:
Same happens in Terminal. Same happens in linux console (tty), even though this delay is smaller there.
I'm working on a console app in Python that uses curses, and it processes the presses of arrow keys and this delay is present there as well.
I want to get rid of this delay, so that when I press and hold a key - it would send signals with uniformly, without any specific delays after first (or whichever) symbol.
How can I do it? Should I use something from the arsenal of curses? Or tinker with some system-wide settings?
EDIT1: I think I've found one way. I can go to keyboard settings and set delay of autorepeat. But it changes it globally and only for my graphical interface. It doesn't change anything in linux console. So, I'm looking fo a way to do it in console as well, and also so it would affect only my app, not the whole system.
and a way for linux console: https://unix.stackexchange.com/questions/58651/adjusting-keyboard-sensitivity-in-a-command-line-terminal
but still looking for an app-only way.

How to query the character under the current cursor position or anywhere on the screen in bash

I know that the following statement is a way to query the current cursor position:
echo -en '\033[6n'
Does anyone know how to query the character under the cursor or populate a array with the contents of the current screen/window? I've searched through the ANSI terminal commands however a lot of these are pretty abstract and it doesn't look like they would do this properly. I also looked into doing it with the tcup command with no luck.
Thank you for your help.
An ANSI terminal is not really required to be able to tell you what is on the screen. You're supposed to remember that yourself, if you need the information. The popular ncurses library does that, for example, although it only allows you to export the screen to a file, and the fileformat is not documented. In any event, bash doesn't use ncurses, so it really doesn't know anything about the state of the console.
Most probably, the screen you are talking about is actually an artifact of some terminal emulation program like xterm. Those programs run in userspace, and rarely (if ever) have an external query interface. However, linux does have a console (actually, a number of emulated consoles, but using the display's console mode) and it maintains the display memory for those consoles. And furthermore, it provides an interface for reading the console memory, usually available as /dev/vcsN (for values of N between 0 and the number of virtual consoles linux was compiled with). /dev/vcs0 is the "current" console (the one which is visible).
Most linux distributions restrict access to /dev/vcsN, so if you want to play around with them you'll either need special privileges or you'll need to use root privileges to change the access permissions on the device files. (Ubuntu appears to provide rw access to users in group tty; check ls -l /dev/vcs0 to see how your system does it.) (And, of course, you'll need to find the console :-) Try CtlAlt1; CtlAlt7 will probably give you back your GUI.)
Once you've worked out the access issues, you could do something like cp /dev/vcs0 console_memory to take a look at it. What you'll find is that it is just a 2D array of characters with no newlines, and no indication of what the dimensions are. (You can get the dimensions with an ioctl or by looking at the environment variables $LINES and $COLUMNS.)
You could use /dev/vcsa0 instead; it has a slightly different format using two bytes per character in order to store display attributes (foreground and background colours, mostly) as well as the character. Also, the first four bytes of /dev/vcsaN are the screen dimensions and cursor position (one byte per coordinate), which will save you the work of querying the cursor position.
Note that the console does not support a full Unicode character set. In fact, it can only display 512 different glyphs at once. In order to maximize the available glyph space, Linux may reassign some codes to needed symbols, and this mapping is not part of the console memory. So the code extracted from console memory might not have an obvious mapping to a Unicode code, but it should work fine for standard ANSI characters.

How to create a log file that "pop_front"s?

Suppose I have a console program that outputs trace debug lines on stdout, that I want to run on a server.
And then I do:
./serverapp > someoutputfile
If I need to see how the program's doing, I would just log into the server and do:
tail -f someoutputfile
However, understandably over time, someoutputfile would become pretty big.
Is there a way to make it so that someoutputfile is limited to a certain size, and only the most recent parts of it?
I mean, the hard way would be to make a custom script/program that cycles the output between different files, but that seems like overkill.
You can truncate the log file. One way to do this is to type:
>someoutputfile
at the shell command-line. It's a redirect with no output and it will erase all the contents of the file.
The tricky bit here is that any program writing to that file will continue to write into the file at its last output position. So the file will immediately gain a "hole" from 0 to X bytes, where X is the output position.
In most Linux file systems these holes result in sparse files, which don't actually use the space in the hole. So the file may contain many gigabytes of 0's at the beginning but only use 500 KB on disk.
Another way to do fast logging is to memory map a file on disk of fixed size: 16 MB for example. Then the logging writes into a memory pointer which wraps around when it reaches the size limit. It then continues to write at the front of the file. It's a good idea to have some kind of write position marker. I use <====>, for example. I find this method to be ridiculously fast and great for debug logging.
I haven't used it, but it gets good reviews here on SO, try logrotate
A more general discussion of managing output files may show you that a custom script/solution is not out of the question ;-) : Problem with Bash output redirection
I hope this helps.

How to only allowed certain text to be printed on Emacs Console?

This question maybe not related to Emacs only, but to all development environment that use Console for its debugging process. Here is the problem. I use Eshell to run the application we are being developed. It's a J2ME application. And for debugging, we just use System.out.println(). And now, suppose I want to allow only text that started with Eko: to be displayed in the console (interactively), is it possible?
I installed Cygwin in my Windows environment, and try to grep the output like this :
run | grep Eko:. It surely filtered only output with Eko: as the beginning, but it's not interactive. The output suppressed until the application quit. Well, that's useless anyway.
Is it possible to do it? What I mean is, we don't have to touch the application code itself?
I tag to linux also, because maybe some guys in Linux know the answer.
Many thanks!
The short: Try adding --line-buffered to your grep command.
The long: I assume that your application is flushing its output stream with every System.out.println(), and that grep has the lines available to read immediately, but is choosing to buffer output until it has 'enough' output saved up to make writing make sense. (This is typically 4k or 8k of data, which could be several hundred lines, depending upon your line length.)
This buffering makes great sense when the output is another program in the pipeline; reducing needless context switches is a great way to improve program throughput.
But if your printing is slow enough that it doesn't fill the buffer quickly enough for 'real time' output, then switching to line-buffered output might fix it.

Resources