Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
dougdrums
Feb 25, 2005
CLIENT REQUESTED ELECTRONIC FUNDING RECEIPT (FUNDS NOW)

JawnV6 posted:

x86 branches a lot, one's expected every 3~5 instructions. Those optimizations seem more like wishful thinking than actual guidance. More of a waste of cache line resources than fetch/predict resources. It sucks for a trace cache since you can't go beyond that, but again they're limited enough that 32b shouldn't cause too much of that pressure.

None of those seem particularly nasty to predict either. Lots of direct branches, decisions arrived by test/cmp right before conditional jumps. Switch gets tricky to predict when it's optimized to use the passed in variable to index a jump table and do it indirectly like jmp [eax]. The first few passes can't be predicted without the back-end supplying that branch target.

Yeah I guess the only real meat in that switch is cmp, je, ..., and all of the breaks would go pretty quick. I forgot that the cmp/jmps get fused. I also never considered the switch case you brought up. The first time I read that you should have only one branch per 32 bytes, I got a chuckle because, yeah, that seems like an impossible thing! When trying to implement this, I've found that it's a trade off with xchgs or how much you can amortize your branching.

I think I'm just hung up on branch prediction because it seems like a tough hit. I'm trying to re-learn assembly by doing 64 bit now and processors got ... interesting. I was hoping you'd reply, your posting has taught me a few things.

Edit: You're right, it's xor ecx, ecx.

Also, is there a book you can recommend that focuses on AMD64? I don't wanna read about segmentation and stuff.

dougdrums fucked around with this message at 17:00 on Jul 3, 2015

Adbot
ADBOT LOVES YOU

Space Kablooey
May 6, 2009


comedyblissoption posted:

Mostly. But it's not just a syntactical difference. The main point is that the ternary is much safer since the ternary must evaluate to an expression.

What do you mean by safer?

dougdrums
Feb 25, 2005
CLIENT REQUESTED ELECTRONIC FUNDING RECEIPT (FUNDS NOW)
I think he means that, if you were to write that in a non-ternary way, as the programmer you're not forced to specify what would be the default case.

comedyblissoption
Mar 15, 2006

A chained if/else does not force assignment on all paths to a value when that is your intention.

Someone could easily forget the default case in if/elses, mess up the bracing on the if/elses, forget a break in the switch statements, forget an else in the chain of if elses, etc. They could do this by adding to the existing logic. Then you're possibly left scratching your head on if they intended to omit the break/else or not.

Also, it's been my experience that people really like to intermix assignment logic with other logic in the if/elses unnecessarily.

comedyblissoption fucked around with this message at 17:09 on Jul 3, 2015

Symbolic Butt
Mar 22, 2009

(_!_)
Buglord

comedyblissoption posted:

In some places, it is idiomatic and not universally hated for the reasons above.

Other than in bespoke artisanal C macros, I never saw it being used in any codebase. :shrug:

comedyblissoption
Mar 15, 2006

Here's an example:

code:
function getX() {
    Butt x = null;
    if (isFoo(x) {
        x = getFooValue();
    } else if (isBar(x)) {
        x = getBarValue();
    } else if (isBaz(x)) {
        x = getBazValue();
    }

    return x;
}
Did I forget a code path? Did I mean what it currently looks like:
code:
function getX() {
    return
        isFoo(x) ? getFooValue() :
        isBar(x) ? getBarValue() :
        isBaz(x) ? getBazValue() :
        null;
}
or did I actually mean:

code:
function getX() {
    return
        isFoo(x) ? getFooValue() :
        isBar(x) ? getBarValue() :
        isBaz(x) ? getBazValue() :
        getDefaultValue();
}

Space Kablooey
May 6, 2009


comedyblissoption posted:

A chained if/else does not force assignment on all paths to a value when that is your intention.

Someone could easily forget the default case in if/elses, mess up the bracing on the if/elses, forget a break in the switch statements, forget an else in the chain of if elses, etc. They could do this by adding to the existing logic. Then you're possibly left scratching your head on if they intended to omit the break/else or not.

Honestly, this stuff are what code reviews are for.

comedyblissoption posted:

Also, it's been my experience that people really like to intermix assignment logic with other logic in the if/elses unnecessarily.

This complaint doesn't make any sense. Sometimes you have to do other stuff besides assignments if a condition is met.

comedyblissoption
Mar 15, 2006

HardDisk posted:

Honestly, this stuff are what code reviews are for.
I find that I very often read code outside the context of a code review. Sometimes the author of the code is no longer an employee. Sometimes the specification is not clearly defined. Statically enforcing exhaustion of all cases is useful for program safety and indicating intent.

HardDisk posted:

This complaint doesn't make any sense. Sometimes you have to do other stuff besides assignments if a condition is met.
I agree.

Space Kablooey
May 6, 2009


comedyblissoption posted:

Here's an example:
*snip*

The first one.

comedyblissoption
Mar 15, 2006

HardDisk posted:

The first one.
You're wrong. I actually made a mistake and forgot about the default case. I actually meant the second one. I'll correct it right away! Thanks for catching it during our code review.

Space Kablooey
May 6, 2009


Both returning null and a default value are valid paths, so you can see why I got it wrong.

My biggest problem with it is that most people that use it just write garbage and think that's clever code, when it's just harder to read than a chain of if/elif/else.

I can see why it's safer, and the way you indented the clauses do help making it less of a lovely syntax. But I guess it's just preference at this point.

comedyblissoption
Mar 15, 2006

Some languages use an expression based syntax to programming. They force all ifs to have a corresponding else. They may have pattern matching. They will often have compiler flags that enforce exhausting all cases for pattern matching. These idioms very likely improve the safety of programs by forcing programmers to acknowledge all branches.

comedyblissoption
Mar 15, 2006

HardDisk posted:

Both returning null and a default value are valid paths, so you can see why I got it wrong.
It didn't matter which one you picked. I would've said the other one. That was the point of the example. You don't know what I intended by just looking at the code. Using a construct that forces exhausting all branches reveals intent and eliminates this problem.

Space Kablooey
May 6, 2009


I feel like we're discussing code style preferences at this point, and that never ends well, when it ends. And I guess that's on me.

Space Kablooey fucked around with this message at 17:41 on Jul 3, 2015

comedyblissoption
Mar 15, 2006

I think the crux of the issue is a preference between statement-based programming and expression-based programming.

Xerophyte
Mar 17, 2008

This space intentionally left blank
People complain about the conditional operator syntax in C but I remain happy I get to write fooficate(invert ? -x : x) instead of fooficate(-x if invert else x). Also, my eyebrows twitch a bit every time someone calls it "the ternary operator". :v:

TheBlackVegetable
Oct 29, 2006

comedyblissoption posted:

Here's an example:

code:
function getX() {
    Butt x = null;
    if (isFoo(x) {
        x = getFooValue();
    } else if (isBar(x)) {
        x = getBarValue();
    } else if (isBaz(x)) {
        x = getBazValue();
    }

    return x;
}
Did I forget a code path? Did I mean what it currently looks like:
code:
function getX() {
    return
        isFoo(x) ? getFooValue() :
        isBar(x) ? getBarValue() :
        isBaz(x) ? getBazValue() :
        null;
}
or did I actually mean:

code:
function getX() {
    return
        isFoo(x) ? getFooValue() :
        isBar(x) ? getBarValue() :
        isBaz(x) ? getBazValue() :
        getDefaultValue();
}

The ternary operators here are beautiful, complete and say what they do with certainty. If someone looks at them and balks, then they need to get more familiar with the ternary operator and be a better programmer.

TheBlackVegetable fucked around with this message at 18:24 on Jul 3, 2015

nielsm
Jun 1, 2009



Xerophyte posted:

People complain about the conditional operator syntax in C but I remain happy I get to write fooficate(invert ? -x : x) instead of fooficate(-x if invert else x). Also, my eyebrows twitch a bit every time someone calls it "the ternary operator". :v:

fooficate(x * -invert)

Symbolic Butt
Mar 22, 2009

(_!_)
Buglord

Xerophyte posted:

Also, my eyebrows twitch a bit every time someone calls it "the ternary operator". :v:

I thought it was mostly a PHP thing to call it "the ternary operator" but reading this thread I guess this isn't true...

TheBlackVegetable posted:

If someone looks at them and balks, then they need to get more familiar with the ternary operator and be a better programmer.

People must comply with my hipster coding preferences to be better, mmmyes...

VikingofRock
Aug 24, 2008




To add to what's been said here, IIRC there are some cases in C++ where you literally cannot use a chain of if/else and instead need to use a ternary expression. I think it's whenever you are within constexpr expression, but I might be wrong there (and I'm phone posting so it'll be a bit before I can verify).

nielsm
Jun 1, 2009



VikingofRock posted:

To add to what's been said here, IIRC there are some cases in C++ where you literally cannot use a chain of if/else and instead need to use a ternary expression. I think it's whenever you are within constexpr expression, but I might be wrong there (and I'm phone posting so it'll be a bit before I can verify).

Initializing references and consts are those cases, yes. Although I guess with C++11 you could use a lambda function to wrap more complex initialization logic.

New Yorp New Yorp
Jul 18, 2003

Only in Kenya.
Pillbug
My favorite use of ternary operator:

http://stackoverflow.com/questions/9101719/im-looking-for-a-free-tool-stand-alone-or-add-in-that-can-decompose-ternary-ex

JawnV6
Jul 4, 2004

So hot ...

dougdrums posted:

I think I'm just hung up on branch prediction because it seems like a tough hit. I'm trying to re-learn assembly by doing 64 bit now and processors got ... interesting. I was hoping you'd reply, your posting has taught me a few things.
Branch prediction is done in a few different pipeline stages. First with just the LIP, second with the decoded instruction, and way down at the end when things are retiring. Think of a direct branch like a call where the LIP and history are enough to predict where it's going 100%. With the decoded instruction some guesses like "jumps forward are not taken, jumps backwards are always taken" can be made without history.

We once had a failure where there were 5 mispredictions. Given that information and the code snippet an architect, full chip guy, and I all gave answers for where the mispredictions were. All the answers were different. All were wrong. Don't focus on tracing one sequence, think about classes of prediction and branch type. More statistical measures. Caching is going to dominate any branching wins.

dougdrums posted:

Also, is there a book you can recommend that focuses on AMD64? I don't wanna read about segmentation and stuff.
The only book I know is the PRM: http://www.intel.com/content/www/us/en/processors/architectures-software-developer-manuals.html or the optimization guidelines you were mentioning.

VikingofRock
Aug 24, 2008




nielsm posted:

Initializing references and consts are those cases, yes. Although I guess with C++11 you could use a lambda function to wrap more complex initialization logic.

Ah yeah that was it. Thank you.

TheBlackVegetable
Oct 29, 2006

Symbolic Butt posted:

I thought it was mostly a PHP thing to call it "the ternary operator" but reading this thread I guess this isn't true...


People must comply with my hipster coding preferences to be better, mmmyes...

It's a basic feature of the language, if you can't read it at a glance (properly formatted ) you need to learn more.

The if / else is also fine, but the point was it's potentially ambiguous in that case and there's a less ambiguous way to express the logic.

You don't have to write the way you don't want to, but you shouldn't have any problem with someone using those operators in that way.

TheBlackVegetable fucked around with this message at 19:21 on Jul 3, 2015

sarehu
Apr 20, 2007

(call/cc call/cc)

HardDisk posted:

Honestly, this stuff are what code reviews are for.

Please stop rounding your probabilities to 0 or 1.

Zopotantor
Feb 24, 2013

...und ist er drin dann lassen wir ihn niemals wieder raus...

nielsm posted:

fooficate(x * -invert)

That does something different.

nielsm
Jun 1, 2009



Zopotantor posted:

That does something different.

Yeah okay.
x * (int(!!invert)*2-1)

And let's assume x is a type that behaves like a normal number.

VikingofRock
Aug 24, 2008




nielsm posted:

Yeah okay.
x * (int(!!invert)*2-1)

And let's assume x is a type that behaves like a normal number.

You prefer that to what Xerophyte wrote?

Space Kablooey
May 6, 2009


sarehu posted:

Please stop rounding your probabilities to 0 or 1.

Can't help it, those numbers are the only things that goes through my head. :smith:

Mellow_
Sep 13, 2010

:frog:

VikingofRock posted:

You prefer that to what Xerophyte wrote?

Some people think ternaries are the devil despite being one of the simpler operators. I personally love ?: and ??

comedyblissoption
Mar 15, 2006

I dislike ?? because it just reminds me the language has null, the billion dollar mistake :(

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

JawnV6 posted:

I rest my case.

Just because PHP does something doesn't automatically make it a bad choice, notwithstanding that there are a lot of bad choices in PHP. I always think that restricting case statements to literals (in languages that do that) is artificial. Seems much more natural to have
code:
switch (x) {
    case y1:
        (instructions 1)
    case y2:
        (instructions 2)
    ...
}
just map directly to
code:
if (x == y1) {
    (instructions 1)
} else if (x == y2) {
    (instructions 2)
}
from which it follows that you should be able to use arbitrary expressions in the case labels. It just strikes me as inelegant that you are required to have literal values there; where else do we tend to make that demand of a language feature? But I don't know much about how compiled languages go about generating efficient code so there might be good reasons why switch tends not to work that way in those languages.

NB. I am aware that the above doesn't take account of fallthrough/goto-case, but a switch statement using these is equivalent to the if-else version if you add gotos in the appropriate places.

comedyblissoption
Mar 15, 2006

It's an archaic hold-over from C. Switch and break is just awful. My best guess is that switch and its attendant pitfalls were copied over into Java and C# and otherlangs to make language switching dubiously and very slightly easier. I would find it hard to believe a language designer actually thinking C-style switch is the best we can do.

Also the switch on literals will likely transform to efficient jumps once it becomes assembly/bytecode and not just a nested series of if/else. The switch semantics probably intentionally guarantee this for this specific reason.

comedyblissoption
Mar 15, 2006

Apparently in C# the compiler makes putting break at the end of a case in a switch both mandatory and explicit, so they fixed the dumb break semantics. But you need to be explicit because otherwise programmers from C or C++ backgrounds would be confused.
http://stackoverflow.com/a/3109495

ultramiraculous
Nov 12, 2003

"No..."
Grimey Drawer

comedyblissoption posted:

Also the switch on literals will likely transform to efficient jumps once it becomes assembly/bytecode and not just a nested series of if/else. The switch semantics probably intentionally guarantee this for this specific reason.

LLVM can transform switch-like if/else groups into a switch and then into jmps as well.

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

comedyblissoption posted:

Apparently in C# the compiler makes putting break at the end of a case in a switch both mandatory and explicit, so they fixed the dumb break semantics. But you need to be explicit because otherwise programmers from C or C++ backgrounds would be confused.
http://stackoverflow.com/a/3109495

Related to the content in that link, the answer by paxdiablo apparently originally claimed that you can use "continue" to mean explicit fallthrough, but it's pointed out in comments that this is incorrect - continue is not legal in a switch. But wait, that means (presumably) that if you have a switch statement inside a loop then you can use break and/or continue and they'll refer to different control structures - one will refer to the switch and the other to the loop. Whereas in general we'd expect break and continue to relate to the same control structure. How nasty is that? Again going on memory PHP treats continue as meaningful in a switch and defines it to have the same effect as break. I will risk being controversial and say that I think PHP made a better choice than other languages here.

comedyblissoption
Mar 15, 2006

cond or pattern matching or case expressions would've been a lot better decision than the crippled switch, but familiarity for programmers unfortunately trumps designing the language to be better

MachinTrucChose
Jun 25, 2009
I don't have the code anymore, but the senior dev at my last job (embedded dev) had some real gems.

For example he wanted to transfer an ordered list of strings to another application. So he serialized manually to XML (this is C++, so you usually have to do everything yourself, this isn't a WTF). Only this is how he did it:
code:
<list elem1="Monday" elem2="Tuesday" .../>
When deserializing, he would read the attribute names, remove "elem" from the name, convert the remaining string to a number to get the index in the list, and insert the attribute value at that index. He didn't even use names like list and element, I can't remember what it was but it was vague like "data". And of course, everything was written to avoid reuse. You'd think he'd just write 2 functions to serialize/deserialize string lists and use that everywhere. Instead, every sender/receiver used their own names, and their own code.

Other times, a simple key/value collection (just a serialized struct) would be something like this:
code:
<struct>
   <value>341234/abcdef/1/4534...14 more elements</value>
</struct>
So what does 4534 correspond to? idk, I gotta read his code to see what the information is, and document it because he won't. How do I get <specific field>? Read the value node's text, split the string by /, access the resulting list at the index which corresponds to specificField. What I don't get is, why would he write poo poo like that. To me it's more difficulty to write that code than to write something like:
code:
<struct>
   <id>341234</id>
   <name>abcdef</name>
   <model>1</model>
   ...
</struct>
I forgot most of it, but some things I won't forget. Like the time he had a service class where calling Stop() actually started the service.

He was considered a genius/hero by the CEO, because of how much work he did. This is what it's like in HW companies.

Adbot
ADBOT LOVES YOU

b0lt
Apr 29, 2005

Hammerite posted:

Just because PHP does something doesn't automatically make it a bad choice, notwithstanding that there are a lot of bad choices in PHP. I always think that restricting case statements to literals (in languages that do that) is artificial. Seems much more natural to have

Literally everything PHP does that differs from the mainstream is a bad choice

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply