[pulseaudio-discuss] [RFC PATCH] alsa-mixer: Cache failure to open inputs

David Henningsson david.henningsson at canonical.com
Mon Sep 24 08:02:55 PDT 2012


On 09/24/2012 03:33 PM, Tanu Kaskinen wrote:
> On Sun, 2012-09-23 at 19:27 +0200, David Henningsson wrote:
>> On 09/23/2012 07:09 PM, Tanu Kaskinen wrote:
>>> On Fri, 2012-09-21 at 10:37 +0200, David Henningsson wrote:
>>>> We spend most of our startup time probing soundcards, so I was hoping this
>>>> would improve bootup speed, but it doesn't seem to do so here.
>>>> Do we want this anyway? At least it reduces the logs a little.
>>>>
>>>> Signed-off-by: David Henningsson <david.henningsson at canonical.com>
>>>> ---
>>>>    src/modules/alsa/alsa-mixer.c |   25 ++++++++++++++++++++++---
>>>>    1 file changed, 22 insertions(+), 3 deletions(-)
>>>>
>>>> diff --git a/src/modules/alsa/alsa-mixer.c b/src/modules/alsa/alsa-mixer.c
>>>> index 8072fbb..1cf502d 100644
>>>> --- a/src/modules/alsa/alsa-mixer.c
>>>> +++ b/src/modules/alsa/alsa-mixer.c
>>>> @@ -3920,6 +3920,10 @@ static void profile_set_add_auto(pa_alsa_profile_set *ps) {
>>>>
>>>>        pa_assert(ps);
>>>>
>>>> +    /* Try input only first, for caching */
>>>
>>> This comment could be more explicit in explaining that for the caching
>>> to be useful, we depend on the fact that pa_hashmap iteration happens in
>>> the order in which the profiles were created. This reordering seemed
>>> nonsensical before I checked how the iteration is implemented.
>>
>> Ok, I could add more explanation in the comment.
>>
>>> I think it would make sense to also create all the output-only profiles
>>> before the combinations.
>>
>> It is actually an optimisation to have it as it is - the output_pcm is
>> less likely to be closed between (m, NULL) and (m, n) this way.
>
> Ok. Maybe a comment about this too?

Fixed in v2.

>
>>>> +    PA_HASHMAP_FOREACH(n, ps->mappings, n_state)
>>>> +        profile_set_add_auto_pair(ps, NULL, n);
>>>> +
>>>>        PA_HASHMAP_FOREACH(m, ps->mappings, m_state) {
>>>>            profile_set_add_auto_pair(ps, m, NULL);
>>>>
>>>> @@ -3927,8 +3931,6 @@ static void profile_set_add_auto(pa_alsa_profile_set *ps) {
>>>>                profile_set_add_auto_pair(ps, m, n);
>>>>        }
>>>>
>>>> -    PA_HASHMAP_FOREACH(n, ps->mappings, n_state)
>>>> -        profile_set_add_auto_pair(ps, NULL, n);
>>>>    }
>>>>
>>>>    static int profile_verify(pa_alsa_profile *p) {
>>>> @@ -4293,6 +4295,7 @@ void pa_alsa_profile_set_probe(
>>>>        void *state;
>>>>        pa_alsa_profile *p, *last = NULL;
>>>>        pa_alsa_mapping *m;
>>>> +    pa_hashmap *broken_inputs;
>>>>
>>>>        pa_assert(ps);
>>>>        pa_assert(dev_id);
>>>> @@ -4301,6 +4304,8 @@ void pa_alsa_profile_set_probe(
>>>>        if (ps->probed)
>>>>            return;
>>>>
>>>> +    broken_inputs = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
>>>
>>> Wouldn't it make sense to have broken_outputs too?
>>
>> Given the current ordering in the above function, I would say no.
>
> Let's say that we have a broken output. First it's tried with a profile
> that only contains that output. Then it's tried with all working inputs
> (broken inputs will be filtered out at this point). We could skip all
> combination profiles if the output is found broken.

I was confusing profiles and mappings. Good finding. Fixed in v2.

>
>>>> +
>>>>        PA_HASHMAP_FOREACH(p, ps->profiles, state) {
>>>>            uint32_t idx;
>>>>
>>>> @@ -4311,8 +4316,16 @@ void pa_alsa_profile_set_probe(
>>>>                profile_finalize_probing(last, p);
>>>>                p->supported = TRUE;
>>>>
>>>> +            if (p->input_mappings)
>>>> +                PA_IDXSET_FOREACH(m, p->input_mappings, idx)
>>>
>>> I see that it's still not codified in the coding style document, but
>>> didn't we agree a while ago in IRC that for multiline block contents
>>> braces should be always used, even if they are not strictly necessary?
>>
>> When we discussed it on IRC, it didn't occur to me that it would strike
>> against simple nested loops. Can I take it back? I think
>>
>> for (i)
>>     for (j)
>>        if (a[i] == b[j])
>>          match_found();
>>
>> ...looks much better than
>>
>> for (i) {
>>     for (j) {
>>        if (a[i] == b[j])
>>          match_found();
>>     }
>> }
>
> Ok, I don't have a problem with this example. But the code in your patch
> has different structure: instead of a simple match_found() call, the
> inner code contains a three-line block.

Well, I still think

for (i)
     for (j)
         if (a[i] == b[j]) {
             three();
             line();
             block();
         }

...looks better than

for (i)
     for (j)
         if (a[i] == b[j]) {
             three();
             line();
             block();
         }
     }
}

...but maybe that's just me.

>>>> +                    if (pa_hashmap_get(broken_inputs, m) == m) {
>>>> +                        pa_log_debug("Skipping - will not be able to open input:%s", m->name);
>>>
>>> A space would be nice before %s.
>>
>> the profiles are made up using e g
>> output:hdmi-stereo+input:analog-stereo, so this reflects the
>> "input:analog-stereo" construct we already use for profile naming.
>
> Right, sorry for not paying better attention.
>
>>>> +                        p->supported = FALSE;
>>>> +                        break;
>>>> +                    }
>>>> +
>>>>                /* Check if we can open all new ones */
>>>> -            if (p->output_mappings)
>>>> +            if (p->supported && p->output_mappings)
>>>>                    PA_IDXSET_FOREACH(m, p->output_mappings, idx) {
>>>>
>>>>                        if (m->output_pcm)
>>>> @@ -4340,6 +4353,11 @@ void pa_alsa_profile_set_probe(
>>>>                                                              default_n_fragments,
>>>>                                                              default_fragment_size_msec))) {
>>>>                            p->supported = FALSE;
>>>> +                        if (pa_idxset_size(p->input_mappings) == 1 &&
>>>> +                            ((!p->output_mappings) || pa_idxset_size(p->output_mappings) == 0)) {
>>>
>>> As far as I can see, p->output_mappings can never have zero size.
>>
>> Ok. Well, better safe than sorry?
>
> Fair enough. I don't like the check, because it implies that it's
> possible that output_mappings is empty, which is not true, but I see how
> this can prevent a bug in the future (not a severe bug, because only a
> minor optimization would be skipped, but a bug anyway). I think it would
> be best to always create the output_mappings idxset so that the code
> doesn't have to worry about it being NULL. If you agree, I'll file a
> bug, since the issue is separate from this patch and I don't plan to
> write the patch right away, nor ask you to do so.

I don't know if we have a generic opinion on whether we prefer NULL 
idxsets or empty idxsets? Or determine on a case-by-case basis?


-- 
David Henningsson, Canonical Ltd.
https://launchpad.net/~diwic


More information about the pulseaudio-discuss mailing list