[mythtv-users] Howto prevent MythTV flushing/Syncing disk writes (LiveTV/Recordings) [ SOLVED ]
Albert Graham
agraham at g-b.net
Wed Mar 19 21:07:00 UTC 2008
David Rees wrote:
> On Tue, Mar 18, 2008 at 3:21 PM, Albert Graham <agraham at g-b.net> wrote:
>
>> David Rees wrote:
>>
>>> If you want to fix this, you're going to have to dig into the source code.
>>>
>> I'm not a C programmer (spent 20 years programming in assembler) so I
>> may just learn C sometime soon and start
>> to contribute to MythTV.
>>
>
> Look at the other post I made shortly after the one you replied to,
> here's a link just to make sure:
>
> http://www.gossamer-threads.com/lists/mythtv/users/324108#324108
>
> Specifically, look at this post:
>
> http://www.gossamer-threads.com/lists/mythtv/users/270965#270965
>
> It tells you exactly what needs to be done to disable data syncing in
> MythTV to let Linux control all the data flushing.
>
> -Dave
>
Hi Dave,
Firstly, thanks for the links.
I patched the source, and now it's perfect, actually it's fantastic, it
only starts writing to the array when the program/recording ends or when
it closes the file in question, another spin off of this is Live TV
never accesses the disk now - that was a bonus I had not even thought
about at this stage, :), but basically the write cache is of course the
read cache, futhermore, XFS filesystem really shows it true colors
because when it sees more of the data it can really optimize the writes
:) - and even never flush the file to disk if you delete the recording -
It's like the front and the backend are running from a ram disk, this
means that my backend is a lot cooler and silent :)
Here are some of my /proc/sys/vm settings for reference, (I know they
are extreme for now, but for testing only).
dirty_ratio = 99
dirty_background_ratio = 99
dirty_expire_centisecs = 1000000 <--- Basically wait a long long time...
dirty_writeback_centisecs = 0
vfs_cache_pressure = 1
swappiness = 99
When reviewing the source I could see why things are done the way they
are, I'm thinking about writing a patch that would be called "The Night
Time Patch", the idea is to combine my "no_sync patch" detailed below,
but also track if any frontends are connected, if they are, everything
operates as normal, but when they are all disconnected, switch to
"no_sync mode", in other words when you stop watching TV, it records in
silent mode until you start watching TV again, or until it finishes
recording a program :) (in addition to a simple daemon script mentioned
later).
The patch would need to be an "on/off switch" in the backend
configuration (mythtv-setup) frontends would not know any difference.
The myth admin would need to be warned that that this feature may cause
data loss if the backend crashes or has power loss during the night
time, however, the admin "should :)" be asleep so the backend should be
safe :)
I tried many approaches, firstly increasing the size of internal buffer
from 2M to 256M (TFW_DEF_BUF_SIZE), and that in it's self was an
improvement, for example, it wrote about every 10/20 seconds or so
larger chunks, but that is not part of the real problem, if fact its a
bad idea to change this buffer size, because the frontend needs to stay
that much data behind the backend, which means you have to pause/stop
the frontend so it does not think it's reached the real EOF, whereas the
frontend has no problem waiting for 2M of buffered data before it resets
its timeout counters (I assume) - i.e. waiting for 256M, the frontend
just gives up! So, we leave buffers alone.
What I did was something like the following:
bool ThreadedFileWriter::Open(void)
{
+ no_sync = 1; /* This switch would be set from the backend
configuration - on/off - but for now its on)
Blah....
}
and
ThreadedFileWriter::~ThreadedFileWriter()
{
no_writes = true;
if (fd >= 0)
{
Flush();
in_dtor = true; /* tells child thread to exit */
bufferSyncWait.wakeAll();
pthread_join(syncer, NULL);
bufferHasData.wakeAll();
pthread_join(writer, NULL);
+/** just before the file is closed, I actually call Sync() **/
+ if (no_sync == 1) {
+ no_sync = 0;
+ Sync();
+ }
close(fd);
fd = -1;
}
if (buf)
{
delete [] buf;
buf = NULL;
}
}
and
In the Flush() function I simply return if no_sync switch is enabled
(ensuring flush=false for compatibly)
void ThreadedFileWriter::Flush(void)
{
flush = false;
+ if (no_sync == 1)
+ return;
+
+/** important not to execute this the following or we'll wait forever,
and lockup the thread! **/
while (BufUsed() > 0)
{
if (!bufferEmpty.wait(2000))
VERBOSE(VB_IMPORTANT, LOC + "Taking a long time to flush..");
}
flush = false;
}
At the start of Sync(), I return if sync=1, notice above when I close
the file, I must disable no_sync=0 switch so I can force a Sync() on close.
void ThreadedFileWriter::Sync(void)
{
+ if (no_sync == 1) /** This is the reall magic! - i.e. let the OS
decide what to do about syncing **/
+ return;
blah..
}
Thats all the changes I've made and it works a treat, however, I noticed
when the Linux cache fills up, say 6G in my case, Linux slowly starts to
trickle the data from the Linux cache to disk, which in a sense puts you
back to square one :(, however it much less noticeable and you do get
the initial 6G write free.
To solve this last problem, I have a little script which could run from
cron or just an endless loop while the backend is runnig (I prefer the
latter) that monitors the amount of cache memory used e.g. (free -m|grep
"Mem"|awk {'print $7'}) or (better still) use /proc etc.. and when it
reaches a threshold (in my case 6G) do the following:
echo "1" > /proc/sys/vm/laptop_mode
sync
echo "3" > /proc/sys/vm/drop_caches
sync
tw_cli /c0 flush
echo "0" > /proc/sys/vm/laptop_mode
This is a really nice use of the "laptop_mode" feature, because Linux
will flush everything on the next sync, I then drop the Linux caches
(which should always be preceded by a sync anyway - but at this point
all out data is safely on disk, (thanks to laptop_mode), now, in my case
I flush the raid controllers cache to disk too (I also have a Raid BBU),
then we disable laptop mode again, at this point we have to wait for
another 6G of data (or a file close) before we hear from our noisy disks
again :).
I know I've gone on a bit, but I wanted to share the experience to save
others interested in the same issues.
So what you think ?
Albert.
ps. I lot of people have made it very clear :) - they run MythTV on old
junk hardware! which most seem to have acquired for free! - Well, you
too can use the above method to extend the life of your junk even
further :).
More information about the mythtv-users
mailing list