[ccache] Duplicate object files in the ccache - possible optimization?

Martin Pool mbp at canonical.com
Tue Nov 8 02:36:38 MST 2011

Maybe you should try adding an option to check both hashes, and see how
that performs.
On Nov 8, 2011 1:03 PM, "Frank Klotz" <frank.klotz at alcatel-lucent.com>

>  On 11/07/2011 10:55 AM, Justin Lebar wrote:
>> Looking at a ccache with about 40,000 .o files in it (created with direct
>>> mode turned on); of the 55 largest files, I found 11 pairs and one
>>> triplet
>>> of identical object files.  That's almost 25% of redundant storage that
>>> could have been avoided by looking at the preprocessed hash when there
>>> is no
>>> hit in direct mode.
>> It's much more interesting to look at the whole cache, I think.
>> $ find -name '*.o' -type f | wc -l
>> 39312
>> jlebar at turing:~/.ccache$ find -name '*.o' -type f | xargs -P16 sha1sum
>> | cut -f 1 -d ' ' | sort | uniq -d | wc -l
>> 1230
>> So it looks like there's some duplication on my machine, but not a
>> ton.  I'd be curious if you got significantly different numbers.
> Hi Justin,
> Here's what I got:
> > find -name '*.o' -type f | wc -l
> 43507
> > find -name '*.o' -type f | xargs -P16 sha1sum | cut -f 1 -d ' ' | sort |
> uniq -d | wc -l
> 13087
> I would say the difference is significant - you got 3%, while I got 30%.
> This is in a project environment where we have fairly fast churn in a
> number of widely-used header files, and I am guessing that the changes in
> those files often consist of addition of or changes to macros and constants
> that are not used in all the files where the header files get included.
> Now I am more than ready to agree that there is room for improvement in
> the design and implementation of the header file layouts here, and we are
> working on that; but at the same time it looks to me like a fairly
> straightforward enhancement to ccache could give us some performance boost
> here.  Since ccache already knows how to do preprocessed hashes, I think
> all I am looking to do is to have it use that existing code when the direct
> mode hash doesn't get a hit.  Then put both hash names on the resulting
> object file, and voila: better hit rates and more unique files in the cache.
> It would be interesting to know if many others see anything at all similar
> to the numbers I have here (i.e., lots of people could use the enhancement
> I am suggesting), of if there is something unique about this environment
> that leads to this much duplication in the cache.
> Thanks,
> Frank
>> On Mon, Nov 7, 2011 at 12:49 PM, Frank Klotz
>> <frank.klotz at alcatel-lucent.**com <frank.klotz at alcatel-lucent.com>>
>>  wrote:
>>>  Hi Martin,
>>> Thanks for your responses.
>>> s/index hash/direct mode hash/g
>>> Apologies - I had a brain burp and was using the wrong terminology.
>>> That aside, however, with  the advent of direct mode, there ARE two
>>> hashes
>>> possible for any given object file - the direct mode hash (hashing all
>>> the
>>> sources that go into the compilation) and the preprocessed hash (hashing
>>> the
>>> result of running all those sources through the preprocessor).  And any
>>> time
>>> there is a cache miss, ccache has computed both those hashes, hasn't it?
>>>  (Or maybe not - if not, see discussion below.)  And it appears to me
>>> that
>>> in many cases, the resulting object file occurs twice in the cache, once
>>> under each hash.  And currently, those two occurrences are two separate
>>> files, which could be combined into a single inode with two hard-linked
>>> directory entries.
>>> Or am I confused about how direct mode interacts with preprocessed mode?
>>>  If
>>> running in direct mode, does ccache never compute the preprocessed hash?
>>>  If
>>> not, it obviously could, and I would recommend that it should.  Why?
>>>  Because when changes are made to a widely-used header file, it very
>>> commonly occurs that those changes only actually modify the preprocessor
>>> output of a small subset of the sources that include that header file,
>>> while
>>> many other sources don't use the changes (say, definition of new macros
>>> or
>>> new constants), so end up with the same preprocessed output, and the same
>>> object file, even though the input header files and direct mode hash did
>>> change).  In that case, ccache could still find hits in the cache with
>>> the
>>> preprocessed mode, even if it's a miss with the direct mode hash.  If
>>> ccache
>>> does not get a direct mode hit, it certainly will have to RUN the
>>> preprocessor to recompile the file - how much extra cost to compute the
>>> preprocessed hash, look it up (to avoid recompiling if it is found with
>>> THAT
>>> hash), and if a compile is still needed, store the resulting object file
>>> inode with 2 directory entries rather than just one?
>>> The way I read the doc about how direct mode works, I thought it would
>>> compute the direct mode hash, and if no hit, "fall back to preprocessed
>>> mode".  I thought that meant it would compute the preprocessed hash and
>>> look
>>> for that too.   Is that incorrect - does it only compute ONE hash in all
>>> cases - a direct mode hash if running in direct mode and a preprocessed
>>> hash
>>> if not in direct mode?  If so, then let's modify my suggested
>>> enhancement to
>>> be that in direct mode, calculate and use the preprocessed hash whenever
>>> there is no hit with direct mode, and create hard links using all
>>> computed
>>> hashes to the one single object file inode that eventually exists in the
>>> ccache.  I don't think direct mode and preprocessed mode HAVE to be
>>> mutually
>>> exclusive - when direct mode gets a miss, preprocessed mode can still
>>> often
>>> provide a hit.
>>> And if no preprocessed hash gets computed/stored when running in direct
>>> mode, then I suspect that the reason I see so many pairs of identical
>>> object
>>> files in my ccache is because of the situation I describe above, where a
>>> header file change has triggered a direct mode hash miss, but
>>> preprocessing
>>> the sources has resulted in an identical preprocessed file which was then
>>> passed to the compiler which produced an identical object file.  But
>>> ccache
>>> didn't KNOW that they were identical, because it didn't compute the
>>> preprocessed hash.
>>> Looking at a ccache with about 40,000 .o files in it (created with direct
>>> mode turned on); of the 55 largest files, I found 11 pairs and one
>>> triplet
>>> of identical object files.  That's almost 25% of redundant storage that
>>> could have been avoided by looking at the preprocessed hash when there
>>> is no
>>> hit in direct mode.
>>> Thanks,
>>> Frank
>>> On 11/07/2011 12:53 AM, Martin Pool wrote:
>>>> On 5 November 2011 11:12, Frank Klotz<frank.klotz at alcatel-**lucent.com<frank.klotz at alcatel-lucent.com>
>>>> >
>>>>  wrote:
>>>>>  I used ccache at my previous employer, and was very convinced of its
>>>>> value.
>>>>>  Now that I have started a new job, I am in the process of trying to
>>>>> bring
>>>>> the new shop on board with ccache, so I have been doing lots of test
>>>>> runs
>>>>> and looking at things.  Here is one thing I am thinking could add some
>>>>> value.
>>>>> Looking through the ccache, I find many pairs of files which have
>>>>> different
>>>>> names (different hashes), but exactly identical content.  This actually
>>>>> makes sense, as each file would have an index hash and a preprocessed
>>>>> hash,
>>>>> and since ccache needs to be able to find a match on either, then both
>>>>> need
>>>>> to be in the cache.
>>>> What is an index hash?
>>>>   (Actually, thinking about it, I'm a little surprised
>>>>> that there are any files in the ccache that DON'T appear twice -
>>>>> shouldn't
>>>>> EVERY compilation have 2 hashes?)
>>>> I don't understand why you would expect that.
>>>> It seems like you expect there is another indirection layer by which
>>>> ccache tries to find jobs that produce identical output.  I don't
>>>> think there is one at present.  I don't think this would happen very
>>>> often in reality, except perhaps for trivial cases like compiling
>>>> empty files, and that's not so important to accelerate, and it will
>>>> not use up much disk space.
>>>> If you're getting duplicated cache files due to for instance doing
>>>> builds in different directories or from different trees that produce
>>>> identical output you could change the ccache options to make it less
>>>> stringent.
>>>>  But it seems to me that it would make a lot of sense to store the data
>>>>> of
>>>>> these 2 files only once, by hard-linking the 2 names to the same inode.
>>>>>  (For filesystems that support hard links, of course!)  Every time
>>>>> ccache
>>>>> does an actual compilation and stores a file in the cache, it should
>>>>> store
>>>>> it under hard links for BOTH hashes - the indexed hash and the
>>>>> proprocessed
>>>>> hash.  And if it gets a hash miss on the indexed hash but a hit on the
>>>>> preprocessed hash, then it should add the missed index hash as a hard
>>>>> link
>>>>> to the file found.  So a given file (inode) in the cache could actually
>>>>> be
>>>>> referenced by MANY directory entries: one preprocessed hash, and
>>>>> multiple
>>>>> index hashes for various different combinations of source files and
>>>>> header
>>>>> files which end up producing the same output when passed through the
>>>>> preprocessor.
>>>> This mail is the first time google has heard of "ccache indexed hash"...
>>>>  This could increase the storage efficiency of the ccache.
>>>>> Of course, since not every filesystem supports hard links, the simplest
>>>>> solution was of course just to have multiple file copies.  So I guess
>>>>> adding
>>>>> code to do this would require some way to determine if the filesystem
>>>>> the
>>>>> cache is on can in fact support hardlinks.
>>>>> If you think this sounds like a good idea, but don't have bandwidth to
>>>>> do
>>>>> it, I would be willing to give it a try.  Any hints on where to start
>>>>> would
>>>>> of course be welcome.
>>>>> Thanks,
>>>>> Frank Klotz
>>>>> ______________________________**_________________
>>>>> ccache mailing list
>>>>> ccache at lists.samba.org
>>>>> https://lists.samba.org/**mailman/listinfo/ccache<https://lists.samba.org/mailman/listinfo/ccache>
>>>>>  ______________________________**_________________
>>> ccache mailing list
>>> ccache at lists.samba.org
>>> https://lists.samba.org/**mailman/listinfo/ccache<https://lists.samba.org/mailman/listinfo/ccache>

More information about the ccache mailing list