|
A good reason not to use goto.
Social Media - A platform that makes it easier for the crazies to find each other.
Everyone is born right handed. Only the strongest overcome it.
Fight for left-handed rights and hand equality.
|
|
|
|
|
I am seeing an odd performance pattern that does entirely make sense to me. I am not asking for anything to be solved - just a confirmation of my observations, or not.
First, the background : I have tried a few options for a tracing library. Among them were Paul DiLascia's old TraceWin app and library. That worked pretty well and was the last one I used. It had a few drawbacks and the main was performance. I found it took on order of 6mS per message and that is just to slow for me and my app(s). I finally decided to write my own and it is looking really good. I now have overhead of about 3μS per message - yes, microseconds. This is where the weird part comes in.
That is the performance on my main development machine. It is a i9-9900X at 3.5Ghz and it runs W10. My testing machine is a Xeon i7-3820 at 3.6GHz and it runs W7, thank the heavens. The weird part is the Xeon has an overhead of less than 1μS per message, typically right at 0.9 and these numbers are quite repeatable.
My goal was to make this as low-overhead as possible and I think I have succeeded. Each message puts the message's text into a buffer (with sprintf) and then copies the buffer into a piece of shared memory using memcpy. However, first it acquires a mutex that guards access to the shared memory. I would not expect an i7 Xeon to be faster than an i9 Core-series processor at essentially the same clock rate at much of anything and certainly not three times faster. This leads to my main question : has anyone else seen this kind of performance difference accessing kernel-level OS objects between W7 and W10?
As I am writing this, I just thought of a possible explanation : clock throttling. I bet the i9 has its clock throttled back during this test. I will experiment a little and see if that's it.
-edit-
Upon further review, I think that is the explanation. In the task manager it shows the CPU idling at 1.2GHz and this would explain the performance difference. The test doesn't last long enough for the turbo mode to kick in so the CPU stays at its idle clock rate. Oh well.
I guess this means the trace library has a sub 1μ overhead and I am even happier about that. Yee haw.
"They have a consciousness, they have a life, they have a soul! Damn you! Let the rabbits wear glasses! Save our brothers! Can I get an amen?"
modified 18-Dec-19 16:21pm.
|
|
|
|
|
I suppose you speak about c/c++, don't you?
M.D.V.
If something has a solution... Why do we have to worry about?. If it has no solution... For what reason do we have to worry about?
Help me to understand what I'm saying, and I'll explain it better to you
Rating helpful answers is nice, but saying thanks can be even nicer.
|
|
|
|
|
The library I made is in c++.
"They have a consciousness, they have a life, they have a soul! Damn you! Let the rabbits wear glasses! Save our brothers! Can I get an amen?"
|
|
|
|
|
Any chance to publish an article about it?
M.D.V.
If something has a solution... Why do we have to worry about?. If it has no solution... For what reason do we have to worry about?
Help me to understand what I'm saying, and I'll explain it better to you
Rating helpful answers is nice, but saying thanks can be even nicer.
|
|
|
|
|
I am really not sure. It is so entwined with the rest of my framework it would be difficult to extract and isolate. I have stuff like multiple trace contexts, editable colors on a per-thread basis, and other stuff. I guess I could remove all of that and provide basic functionality without the accessories. I'll finish up a few other things and see what I can do.
"They have a consciousness, they have a life, they have a soul! Damn you! Let the rabbits wear glasses! Save our brothers! Can I get an amen?"
|
|
|
|
|
Rick York wrote: t is so entwined with the rest of my framework it would be difficult to extract and isolate. I have stuff like multiple trace contexts, editable colors on a per-thread basis, and other stuff What about a serie of articles?
M.D.V.
If something has a solution... Why do we have to worry about?. If it has no solution... For what reason do we have to worry about?
Help me to understand what I'm saying, and I'll explain it better to you
Rating helpful answers is nice, but saying thanks can be even nicer.
|
|
|
|
|
In my Android app (using Kotlin) I recently had some code running even when the List of items contained 0 items.
I was using a for loop with a range and I expected that if the list(array or whatever) contained zero items then the count() would be zero and the for loop wouldn't run.
Here's a fake example of the code that actually runs. You can try it at the kotlin playground:
Kotlin Playground: Edit, Run, Share Kotlin Code Online[^]
val emptySet = Array<Int>(0){0}
println("There are ${emptySet.count()} items in the array.")
for (i in 0..emptySet.count()){
println("Iniside the loop, one time.")
}
Here's the output:
There are 0 items in the array.
Iniside the loop, one time.
for (i in 0..0){
println("Iniside the loop, one time.")
}
I just didn't expect that would be how a range would work.
This feels different than the way C# would handle a for...loop like this.
But, again, I often stumble upon PEBKAC[^] errors.
I'm just lucky that way.
|
|
|
|
|
That does seem rather odd, but it matches the description in the documentation:
if (i in 1..4) { To iterate a number range which does not include its end element, use the until[^] function
Updating your example[^] to use until produces the expected result.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
|
The until keyword has nothing to do with ranges, it's just another way to write a classic for loop.
#SupportHeForShe
Government can give you nothing but what it takes from somebody else. A government big enough to give you everything you want is big enough to take everything you've got, including your freedom.-Ezra Taft Benson
You must accept 1 of 2 basic premises: Either we are alone in the universe or we are not alone. Either way, the implications are staggering!-Wernher von Braun
|
|
|
|
|
I just think in this case, for loops in C# are more intuitive and obvious:
for (int x=0;x<=0;x++){
Console.WriteLine($"x {x}");
}
for (int x=0;x<0;x++){
Console.WriteLine($"x {x}");
}
Is there a more equivalent example (are there ranges in C#?) in C#?
|
|
|
|
|
foreach (var in list) { ... }
In C# 8 you have ranges:
foreach(var item in 1..100)
{
Console.WriteLine(item);
} For other range info see: (especially for arrays) C# 8 Ranges and Recursive Patterns[^]
#SupportHeForShe
Government can give you nothing but what it takes from somebody else. A government big enough to give you everything you want is big enough to take everything you've got, including your freedom.-Ezra Taft Benson
You must accept 1 of 2 basic premises: Either we are alone in the universe or we are not alone. Either way, the implications are staggering!-Wernher von Braun
|
|
|
|
|
TheGreatAndPowerfulOz wrote: foreach (var in list) { ... }
Right, in C# it looks like this:
List<int> allInts = new List<int>();
Console.WriteLine($"There are {allInts.Count} items in the list");
foreach (var x in allInts){
Console.WriteLine(x);
}
The code inside the foreach never runs. Again, that is more what I was expecting.
|
|
|
|
|
TheGreatAndPowerfulOz wrote: foreach(var item in 1..100)
That code won't work:
CS1579 foreach statement cannot operate on variables of type 'Range' because 'Range' does not contain a public instance definition for 'GetEnumerator'
And if you change it to iterate over a range of an array, the upper-bound is exclusive:
int[] numbers = Enumerable.Range(0, 20).ToArray();
foreach (int i in numbers[1..10])
{
Console.WriteLine(i);
}
The start of the range is inclusive, but the end of the range is exclusive, meaning the start is included in the range but the end isn't included in the range.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Thanks, I guess the article from which I grabbed the code-snippet was from a proposed syntax. Too bad, it's much simpler and more readable than what does work.
I guess this is a little closer:
foreach(var item in Enumerable.Range(1, 10))
{
Console.WriteLine(item);
}
#SupportHeForShe
Government can give you nothing but what it takes from somebody else. A government big enough to give you everything you want is big enough to take everything you've got, including your freedom.-Ezra Taft Benson
You must accept 1 of 2 basic premises: Either we are alone in the universe or we are not alone. Either way, the implications are staggering!-Wernher von Braun
|
|
|
|
|
Since a range is a set, and you're asking to iterate the set, then it's working exactly as I would have expected.
#SupportHeForShe
Government can give you nothing but what it takes from somebody else. A government big enough to give you everything you want is big enough to take everything you've got, including your freedom.-Ezra Taft Benson
You must accept 1 of 2 basic premises: Either we are alone in the universe or we are not alone. Either way, the implications are staggering!-Wernher von Braun
|
|
|
|
|
TheGreatAndPowerfulOz wrote: Since a range is a set, and you're asking to iterate the set, then it's working exactly as I would have expected.
When I posted, I guessed that I'd get an answer like this. And, I'm not upset with your post, nor do I think it is incorrect.
I figured it was something I just didn't think entirely correctly about.
To me though, it seems like my original code was saying, iterate over this empty set and so I expected it to not run the code inside the for loop.
Another way to say this is, "I accept that I am incorrect about this, but the functionality of the structure as it is defined by Kotlin seems like it leads to grey understanding where the dev could be initially confused until dev obtains some experience with Kotlin Ranges."
But, again, I blame myself for not fully understanding the construct before using it.
I like to shoot first and ask questions later...after all the code is dead (not working).
Thanks for your input on this.
|
|
|
|
|
But the set from 0 to 0 is not empty, there is one item in it: 0.
If you'd said 0 to -1 (or 0 to count()-1 and assuming positive increment), then that would've been empty.
#SupportHeForShe
Government can give you nothing but what it takes from somebody else. A government big enough to give you everything you want is big enough to take everything you've got, including your freedom.-Ezra Taft Benson
You must accept 1 of 2 basic premises: Either we are alone in the universe or we are not alone. Either way, the implications are staggering!-Wernher von Braun
|
|
|
|
|
TheGreatAndPowerfulOz wrote: But the set from 0 to 0 is not empty, there is one item in it: 0.
I agree with you on that. Just a very odd construct when thinking about iterating over a set of items. This gets weird when you are attempting to get an element out of the set that is based upon an index value.
for (i in 0..allItems.count){
allItems.getItem(i);
}
I had fixed it using the notion that you mentioned (before I knew about Until), but it seemed odd
for (i in 0..allItems.count - 1){
allItems.getItem(i);
}
|
|
|
|
|
raddevus wrote: thinking about iterating over a set of item
You are thinking about the wrong set. While you can iterate over the items with a forEach, your code is not doing this. Your code loops over a range from 0 to the length of your (empty) set (0).
My first thought when I encounter a range based set generating construct in a language is always "which if either (or both!) of the bounds is inclusive". You can test this with a quick implementation of the languages version of the following:
for value in 1 to 3
print value
done
|
|
|
|
|
TheGreatAndPowerfulOz wrote: But the set from 0 to 0 is not empty, there is one item in it: 0. Usually, but not always.
The set of years from year 0 to year 0 is empty. Year -1 was immediately followed by year 1. There was no year 0.
Some people claim that this makes sense: There was no "year of Christ", the year before is birth was "year one before Christ" and the year after the birth was "year one". I have never met anyone who agrees that he was born in "year one before Christ", on Christmas day, neither will Christians agree that year one started 358 days before his birth. But the official view of the Christian church is that there was no year 0. This is so strong that even when non-Christians prefer to use the "Common Era" and "Before Common Era" rather than AD and BC, year 0 is skipped. Even in version 1.0 of the XML Schema language defined that for types date and dateTime, there is no year 0. (This definition was modified in later versions.)
The elevator in our office building is not very biblical of nature, yet there is no floor 0. It goes directly from floor 1 to floor -1. Since most of us are closer to mathematicians than to theologicans, to ease our minds we have declared that there is a floor 0, but it is virtual, and that is why the elevator doesn't stop there. Conceptually, it is there.
|
|
|
|
|
Since there is no year 0, then it's even worse than being the empty set, it's NULL.
As for your building, conceptually it is not there, so it is not an empty set, it is NULL.
#SupportHeForShe
Government can give you nothing but what it takes from somebody else. A government big enough to give you everything you want is big enough to take everything you've got, including your freedom.-Ezra Taft Benson
You must accept 1 of 2 basic premises: Either we are alone in the universe or we are not alone. Either way, the implications are staggering!-Wernher von Braun
|
|
|
|
|
The difference between inclusive & exclusive ranges... You (and most of us, thanks to zero based arrays in C, C#, Javascript and the like) are used to exclusive ranges (not including the endpoint), but Kotlin's range notation produces inclusive ranges.
Rust has similar notation, but it produces exclusive ranges (as you were expecting Kotlin to do), and uses ..= for inclusive ranges, so:
fn main() {
for i in 0..=0 {
print!("0..=0: {}\n", i);
}
for i in 0..0 {
print!("0..0: {}\n", i);
}
}
produces
0..=0: 0
Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p
|
|
|
|
|
Thanks for sharing that about Rust. I think that makes much more sense and is quite a bit more intuitively obvious.
I recently noticed that C# Enumerable.Range also works the way I would (intuitively) expect it to.
foreach (var index in Enumerable.Range( 0, 0 ))
{
Console.WriteLine(index);
}
|
|
|
|