[squid-dev] [PATCH] Coverity(-inspired) fixes part four, HttpHeader refactor
Kinkie
gkinkie at gmail.com
Sun Aug 23 22:01:35 UTC 2015
On Sun, Aug 23, 2015 at 7:55 PM, Alex Rousskov <
rousskov at measurement-factory.com> wrote:
> On 08/21/2015 11:31 AM, Kinkie wrote:
> > On Fri, Aug 21, 2015 at 6:39 PM, Alex Rousskov wrote:
> >
> > On 08/21/2015 04:37 AM, Kinkie wrote:
> >
> > > the attached patch does:
> >
> > ... a long list of mostly unrelated changes ...
> >
> > Sigh. Some of the patch changes are not necessary at all. Some are
> > useful. Some should be redone to minimize conflicts. Some are
> > performance optimizations that should be considered very carefully.
> It
> > would take too much time to sift through all of this and separate the
> > good from the bad, so we would have to accept pretty much all of
> them,
> > create a lot of conflicts, and probably miss bugs.
>
>
> > To defend the code, ...
>
> Your code was not under attack. Your choice to assemble many unrelated
> and/or supposed-to-be-sequential changes into one patch was.
>
I'm sorry about that. I tend to go depth-first, unfortunately.
I'll try to resist, but it's really hard for me.
> > > - Tolower(name);
> > > -
> > > - if (strcmp(name, "*") == 0) {
> > > - /* Can not handle "Vary: *" withtout ETag support */
> > > - safe_free(name);
> > > + SBuf name(item, ilen);
> > > + if (name.cmp("*",1) == 0) {
> > > vstr.clean();
> > > break;
> > > }
> > > -
> > > - strListAdd(&vstr, name, ',');
> > > + name.toLower();
> >
> > Do you know why we need to convert header names to lowercase here?
> The
> > header names are not a part of some Store hash, right? This
> conversion
> > is expensive because most header names will be changed here, breaking
> > SBuf reuse. If you know the reason, let's add a comment since you are
> > changing this code anyway.
>
>
> > Since lowerCase("*") == "*", I'd hope that the behavior is unchanged,
>
> I did not say something has changed. I asked *why* we need to convert
> header names to lower case. I am not trying to sneak in some veiled
> attack on your code inside an innocent-looking question. I asked exactly
> what I wanted to know. An "I do not know" would be a perfectly
> acceptable response, of course, but if you do know, it would be good to
> add a comment.
>
You are right, I got defensive over nothing.
Truth is, I don't know.
>
>
> > // XXX: will reallocate if toLower() above is removed
> >
> >
> > .. and strListGetItem will start emitting SBufs in place of (char*,
> > length).
>
> Right, so perhaps s/will/may/ to be less precise since there are many
> factors here. The toLower() call is the most hidden factor though. This
> is not important -- if you disagree that a comment would be useful, do
> not add it. This is not an attack on your code.
>
Adding comment: "will reallocate if ilen happens to equal pool size"
>
>
> > > - while ((e = getEntry(&pos))) {
> > > - if (e->id == id)
> > > - delAt(pos, count);
> > > - }
> > > + int sz_before = entries.size();
> > > + entries.erase(std::remove_if(entries.begin(), entries.end(),
> > > + [=](HttpHeaderEntry *e) { return e && e->id == id; }),
> > > + entries.end());
> >
> > This change is a performance regression AFAICT: Unlike the old
> delAt(),
> > std::remove_if is very expensive for std::vector. Consider using
> > std::replace_if without .erasing instead.
> >
> >
> > yes, it is a small regresson (from N to 2N)
>
> I suspect a factor of 2 does not describe the overhead accurately. If
> remove_if removes a field, then all subsequent fields (except those that
> are also removed) would have to be moved, which is probably much more
> expensive than just checking their values twice.
>
>
> > ). Reimplemented using replace_if - readability goes a bit down the
> > drain, unfortunatley.
>
> Perhaps a little bit. Personally, I could not interpret the earlier
> erase(remove_if) combination without looking things up anyway :-).
>
>
This is what it looks like right now:
//set all items in entries where item is not nullptr and
// has same id as argument, to nullptr. Increment count variable
// as a side-effect on matches during sweep
std::replace_if(entries.begin(), entries.end(),
[&](HttpHeaderEntry *e) {
if (e && e->id == id) {
++count;
return true;
}
return false;
},
nullptr);
Hopefully the comment will clarify intent :)
> > > +enum HdrKind {
> >
> > Use C++11 class enums for global enums, especially when such use does
> > not increase the amount of old code changes. In this specific case,
> it
> > does not AFAICT.
> >
> >
> > Unfortunately it's not possible in ordeer to use it as a bit-field (I
> > have tried and the compiler refused)
>
> Interesting! If you still have an example of what goes wrong, can you
> post it? I tried a few tests myself, but they seem to be working fine if
> I specify the underlying class storage type (as we should, per [1]):
>
Using clang on MacOS:
------------------------ source code
#include <iostream>
enum class foo : std::int8_t {
zero = 0,
one = 1,
two = 1<<1,
three = 1<<2,
four = 1<<3
};
std::int8_t var = foo::one | foo::four;
int main() {
std::cout << var << std::endl;
return 0;
}
---------------------------- compiler output
example.cc:11:28: error: invalid operands to binary expression ('foo' and
'foo')
std::int8_t var = foo::one | foo::four;
~~~~~~~~ ^ ~~~~~~~~~
1 error generated.
-----------------------------
>
>
> > "bzr send" unfortunately doesn't allow to specify context to be added :(
>
> Yes, that is unfortunate indeed. Fortunately, "bzr send" is not the only
> way to post a patch for review :-).
>
Yes :)
Attached current patch.
If I understand correclty, that the only point to clear before merge is how
many lines away from a touched line should a HERE be to be removed (I'll
try to come up with a script to do blanket HERE removal as said elsewhere
in this thread).
Thanks!
--
Francesco
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.squid-cache.org/pipermail/squid-dev/attachments/20150824/b0ee569d/attachment.html>
More information about the squid-dev
mailing list