having issues when extracting char values, using unsafe char* in a struct [] - c#

in this code i am trying to simulate a task that populats an array of structs,
...unsafe to get as much throughoutput as can be achived.
the issue is that i when calling the fucntion and itterating on the result
shows different characters but within the scope of GetSomeTs() it's fine.
so just before the return i test one of the elements and it prints the correct value.
this is the testing struct.
public unsafe struct T1
{
public char* block = stackalloc char[5];<--will not compile so the process will be done within a local variable inside a method
}
public unsafe struct T1
{
public char* block;
}
static unsafe T1[] GetSomeTs(int ArrSz)
{
char[] SomeValChars = { 'a', 'b', 'c', 'd', 'e' };
T1[] RtT1Arr = new T1[ArrSz];
for (int i = 0; i < RtT1Arr.Length; i++)
{
char* tmpCap = stackalloc char[5];
for (int l = 0; l < 5; l++)
{
SomeValChars[4] = i.ToString()[0];
tmpCap[l] = SomeValChars[l];
}
RtT1Arr[i].block = tmpCap;//try 1
//arr[i].block = &tmpCap[0];//try 2
}
// here its fine
Console.WriteLine("{0}", new string(RtT1Arr[1].block));
return RtT1Arr;
}
but using it anywhere else printing garbage.
void Main()
{
T1[] tstT1 = GetSomeTs(10);
for (int i = 0; i < 10; i++)
{
Console.WriteLine("{0}", new string(tstT1[i].block));//,0,5, Encoding.Default));
}
}

When you allocate memory with stackalloc that memory only exists until the function returns in which you have allocated it. You are returning a pointer to memory that is no longer allowed to be accessed.
Hard to recommend a fix because it's unclear what you want to achieve. Probably, you should just use a managed char[].
Encoding.Default.GetBytes is pretty slow so that's likely to be your hotspot anyway and the rest is less important. i.ToString() also is quite slow and produces garbage. If you are after perf then stop creating unneeded objects all the time such as SomeValChars. Create it once and reuse.

Related

struct vs class performance test

I built a test and got following results:
allocating classes: 15.3260622, allocating structs: 14.7216018.
Looks like a 4% advantage when allocates structs instead of classes. That's cool but is it really enough to add in the language value types? Where I can find an example which shows that structs really beat classes?
void Main()
{
var stopWatch = new System.Diagnostics.Stopwatch();
stopWatch.Start();
for (int i = 0; i < 100000000; i++)
{
var foo = new refFoo()
{
Str = "Alex" + i
};
}
stopWatch.Stop();
stopWatch.Dump();
stopWatch.Restart();
for (int i = 0; i < 100000000; i++)
{
var foo = new valFoo()
{
Str = "Alex" + i
};
}
stopWatch.Stop();
stopWatch.Dump();
}
public struct valFoo
{
public string Str;
}
public class refFoo
{
public string Str;
}
Your methodology is wrong. You are mostly measuring string allocations, conversions of integers to strings, and concatenation of strings. This benchmark is not worth the bits it is written on.
In order to see the benefit of structs, compare allocating an array of 1000 objects and an array of 1000 structs. In the case of the array of objects, you will need one allocation for the array itself, and then one allocation for each object in the array. In the case of the array of structs, you have one allocation for the array of structs.
Also, look at the implementation of the Enumerator of the List class in the C# source code of .Net collections. It is declared as a struct. That's because it only contains an int, so the entire enumerator struct fits inside a machine word, so it is very inexpensive.
Try some simpler test:
int size = 1000000;
var listA = new List<int>(size);
for (int i = 0; i < size; i++)
listA.Add(i);
var listB = new List<object>(size);
for (int i = 0; i < size; i++)
listB.Add(i);
To store 1000000 integers in first case the system allocates 4000000 bytes. In second, if I'm not mistaken — about 12000000 bytes. And I suspect the performance difference will be much greater.

In C# datatype* means

what exactly this means
Datatype*
Example : int*, double*, char*,...
Can any one give some explanation for it please.
Thanks in Advance.
It's an unsafe pointer. Unsafe Code Tutorial
Here is an examples using it: How to pull out alpha and count digits using regex?
private static unsafe List<long> ParseNumbers(char[] input)
{
var r = new List<long>();
fixed (char* begin = input)
{
char* it = begin, end = begin + input.Length;
while (true)
{
while (it != end && (*it < '0' || *it > '9'))
++it;
if (it == end) break;
long accum = 0;
while (it != end && *it >= '0' && *it <= '9')
accum = accum * 10 + (*(it++) - '0');
r.Add(accum);
}
}
return r;
}
Have a look at Pointer types (C# Programming Guide)
In an unsafe context, a type may be a pointer type, a value type, or a
reference type. A pointer type declaration takes one of the following
forms:
type* identifier;
void* identifier; //allowed but not recommended
Those are Pointer types.
In an unsafe context, a type may be a pointer type as well as a value type or a reference type. A pointer type declaration takes one of the following forms:
type* identifier;
void* identifier; //allowed but not recommended
They are called Pointer types
In an unsafe context, a type may be a pointer-type as well as a
value-type or a reference-type. However, a pointer-type may also be
used in a typeof expression outside of an unsafe context
as such usage is not unsafe.
A pointer-type is written as an unmanaged-type or the keyword void,
followed by a * token:
The type specified before the * in a pointer type is called the
referent type of the pointer type. It represents the type of the
variable to which a value of the pointer type points.
Unlike references (values of reference types), pointers are not
tracked by the garbage collector—the garbage collector has no
knowledge of pointers and the data to which they point. For this
reason a pointer is not permitted to point to a reference or to a
struct that contains references, and the referent type of a pointer
must be an unmanaged-type.
This is pointer in c#
please take a time to read this Unsafe Code Tutorial
using System;
class Test
{
// The unsafe keyword allows pointers to be used within
// the following method:
static unsafe void Copy(byte[] src, int srcIndex,
byte[] dst, int dstIndex, int count)
{
if (src == null || srcIndex < 0 ||
dst == null || dstIndex < 0 || count < 0)
{
throw new ArgumentException();
}
int srcLen = src.Length;
int dstLen = dst.Length;
if (srcLen - srcIndex < count ||
dstLen - dstIndex < count)
{
throw new ArgumentException();
}
// The following fixed statement pins the location of
// the src and dst objects in memory so that they will
// not be moved by garbage collection.
fixed (byte* pSrc = src, pDst = dst)
{
byte* ps = pSrc;
byte* pd = pDst;
// Loop over the count in blocks of 4 bytes, copying an
// integer (4 bytes) at a time:
for (int n =0 ; n < count/4 ; n++)
{
*((int*)pd) = *((int*)ps);
pd += 4;
ps += 4;
}
// Complete the copy by moving any bytes that weren't
// moved in blocks of 4:
for (int n =0; n < count%4; n++)
{
*pd = *ps;
pd++;
ps++;
}
}
}
static void Main(string[] args)
{
byte[] a = new byte[100];
byte[] b = new byte[100];
for(int i=0; i<100; ++i)
a[i] = (byte)i;
Copy(a, 0, b, 0, 100);
Console.WriteLine("The first 10 elements are:");
for(int i=0; i<10; ++i)
Console.Write(b[i] + " ");
Console.WriteLine("\n");
}
}
and output
The first 10 elements are:
0 1 2 3 4 5 6 7 8 9
i tooth this will give you an idea to understated pointer in c# and also how to use it
best of luck

Getting an unsafe fixed pointer to the start of a rectangular array

Consider a 2D, rectangular array. Say:
int[,] values = new int[len1, len2];
How can you iterate through all of its values in unsafe code?
The following works in an unsafe context.
fixed (int* baseOffset = values)
{
var offset = baseOffset;
var count = len1 * len2;
for (int i = 0; i < count; i++)
{
int value = *offset;
// Do whatever you need to do here
offset++;
}
}
Note that to get a pointer to the first item in an array, the types must match. So if you have a byte* which you want to treat as ushort*, you cannot cast the pointer within the fixed statement's parentheses, although you can do this within the block.

Safe Indexing Inside Unsafe Code

Good morning, afternoon or night,
Foreword: The code below does nothing really useful. It is just for explanation purposes.
Is there anything wrong with allocating and using an array "the safe mode" inside unsafe code? For example, should I write my code as
public static unsafe uint[] Test (uint[] firstParam, uint[] secondParam)
{
fixed (uint * first = firstParam, second = secondParam)
{
uint[] Result = new uint[firstParam.Length + secondParam.Length];
for (int IndTmp = 0; IndTmp < firstParam.Length; Result[IndTmp] = *(first + IndTmp++));
for (int IndTmp = 0; IndTmp < secondParam.Length; Result[IndTmp + firstParam.Length] = *(second + IndTmp++);
return Result;
}
}
or should I instead write a separate, unsafe method accepting only pointers and lengths as parameters and use it in the main function?
Also, is there any way I can replace the allocation with
uint * Result = stackalloc uint[firstParam.Length + secondParam.Length]
so that I can use Result as a pointer and still be able to return Result as an uint[]?
Thank you very much.
I see nothing wrong with doing that, although if you're using pointers for speed, it probably makes sense to use a pointer into Result also. Maybe like this:
public static unsafe uint[] Test (uint[] firstParam, uint[] secondParam)
{
uint[] Result = new uint[firstParam.Length + secondParam.Length];
fixed (uint * first = firstParam, second = secondParam, res = Result)
{
for (int IndTmp = 0; IndTmp < firstParam.Length; IndTmp++)
*(res + IndTmp) = *(first + IndTmp);
res += firstParam.Length;
for (int IndTmp = 0; IndTmp < secondParam.Length; IndTmp++)
*(res + IndTmp) = *(second + IndTmp++);
}
return Result;
}
DO NOT return anything you stackalloc! Once the function returns, the area allocated on the stack is reused, giving you an invalid pointer.

Array.Reverse algorithm?

What kind of algorithm Array.Reverse(string a), uses behind the scene to reverse the string?
UPDATE: See the bottom of this answer for one truly horrifying ramification of reversing a string in-place in .NET.
"Good" Answer
In .NET, there's no Array.Reverse overload that takes a string. That said, here's how one might be implemented if it were to exist:
static string ReverseString(string str) {
char[] reversed = new char[str.Length];
for (int i = 0; i < reversed.Length; ++i)
reversed[i] = str[str.Length - 1 - i];
return new string(reversed);
}
Note that in .NET this method has to return a string, since the System.String type is immutable and so you couldn't reverse one in-place.
Scary Answer
OK, actually, it is possible to reverse a string in-place in .NET.
Here's one way, which requires compiling in unsafe mode:
static unsafe void ReverseString(string str) {
int i = 0;
int j = str.Length - 1;
fixed (char* fstr = str) {
while (i < j) {
char temp = fstr[j];
fstr[j--] = fstr[i];
fstr[i++] = temp;
}
}
}
And here's another way, which uses reflection and does not need to be compiled in unsafe mode:
static void ReverseString(string str) {
int i = 0;
int j = str.Length - 1;
// what a tricky bastard!
MethodInfo setter = typeof(string).GetMethod(
"SetChar",
BindingFlags.Instance | BindingFlags.NonPublic
);
while (i < j) {
char temp = str[j];
setter.Invoke(str, new object[] { j--, str[i] });
setter.Invoke(str, new object[] { i++, temp });
}
}
Totally inadvisable and reckless, yes -- not to mention that it would likely have horrendous performance. But possible nonetheless.
The Horror
Oh, and by the way, in case there's any doubt in your mind whatsoever that you should never do anything like this: be aware that either of the ReverseString methods I've provided above will actually allow you to write the following utterly bizarre program:
ReverseString("Hello!");
Console.WriteLine("Hello!");
The above code will output, believe it or not*:
!olleH
So yeah, unless you want all hell to break loose in your code, don't reverse a string in-place. Even though technically you can ;)
*You can try it for yourself if you don't believe me.
Probably a standard in-place reversal algorithm.
function reverse-in-place(a[0..n])
for i from 0 to floor(n/2)
swap(a[i], a[n-i])
Sources
Wikipedia/In-place algorithm
The algorithm is probably using two pointers i and j that start at 0 and length-1 respectively. Then the characters at position i and j are swapped (with the help of a temporal variable) and i is incremented and j decremented by 1. These steps are repeated until both pointers reach each other (i ≥ j).
In pseudo-code:
i := 0;
j := a.length-1;
while (i < j) do
tmp := a[i];
a[i] := a[j];
a[j] := tmp;
i := i+1;
j := j-1;
endwhile;
According to Reflector, Array.Reverse(Array) (there's no string variation) first calls something called TrySZReverse, for which I can't find the implementation. I assume it's some sort of heavily optimized native method..
If that fails, it does something like this:
int num = index;
int num2 = (index + length) - 1;
while (num < num2)
{
object obj2 = objArray[num];
objArray[num] = objArray[num2];
objArray[num2] = obj2;
num++;
num2--;
}
So, an in place algorithm, where it swaps the values at each end, then moves inward, repeatedly.
Here's a general-purpose, language-independent, question-appropriate answer: It copies the input string to the output string, reading from one end and writing to the other.
My suggestion:
private string Reverse(string text)
{
char[] c = text.ToCharArray(0, text.Length);
Array.Reverse(c);
return new string(c);
}

Categories

Resources