FileStream.EndRead, Does it cause a context switch?

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

Hi,

I am using FileStream's Async API: BeginRead/EndRead, upon completion callback execution I use the read data and call EndRead, Taking that in mind, I Wonder... does calling EndRead will cause a context switch? What is the kernel object used for blocking EndRead calls? Event and mutex cause a context switch even when the object is signaled and no wait is needed, usage of critical section prevent this switch from happening... what is the object used by EndRead? will it cause a context switch? My Guess is that the EndRead uses an Event as the OVERLAPPED structure used with IO Completion routines use an event for completion indications, if my assumption is true calling EndRead from the completion callback will cause an un-neccesary context switch, one that can be saved by querying the amount of bytes read in a way other then calling EndRead... ( is there such a way? Is there a non-explicit interface to IAsyncResponce? Can it be cast to somewhat more detailed structure? )

Note that I use EndRead in the completion callback merely to get the amount of bytes read, if I could get this amount by in a way other then calling EndRead It would solve the problem... Is there another way of getting the amount of read bytes? is there a way of extracting the internal OVERLAPPED structure from the IAsyncResult object?

Nadav
http://www.ddevel.com
 
Nadav,

The FileStream does in fact use IO completion ports to handle async
operations. You can not cast the IAsyncResult to something more concrete to
get the result that you want. You will have to call the APIs through the
P/Invoke layer to do what you want.

Also, I am not quite sure what you are trying to do. You say that you
just want to get the number of bytes read. If you don't want to do anything
with the bytes, and you want to advance the stream pointer, then why not
just seek on the stream?

Finally, calling EndRead might call a context switch, depending on where
you call it. If you call it in a thread other than the callback thread,
then it might cause a context switch. However, if you call it in the thread
that fires the asynchronous notification, then you should not have a context
switch.

Hope this helps.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Nadav said:
Hi,

I am using FileStream's Async API: BeginRead/EndRead, upon completion
callback execution I use the read data and call EndRead, Taking that in
mind, I Wonder... does calling EndRead will cause a context switch? What is
the kernel object used for blocking EndRead calls? Event and mutex cause a
context switch even when the object is signaled and no wait is needed, usage
of critical section prevent this switch from happening... what is the object
used by EndRead? will it cause a context switch? My Guess is that the
EndRead uses an Event as the OVERLAPPED structure used with IO Completion
routines use an event for completion indications, if my assumption is true
calling EndRead from the completion callback will cause an un-neccesary
context switch, one that can be saved by querying the amount of bytes read
in a way other then calling EndRead... ( is there such a way? Is there a
non-explicit interface to IAsyncResponce? Can it be cast to somewhat more
detailed structure? )
Note that I use EndRead in the completion callback merely to get the
amount of bytes read, if I could get this amount by in a way other then
calling EndRead It would solve the problem... Is there another way of
getting the amount of read bytes? is there a way of extracting the internal
OVERLAPPED structure from the IAsyncResult object?
 
Thanks for the immediate response, my remarks are given bellow
Nadav,

The FileStream does in fact use IO completion ports to handle async
operations. You can not cast the IAsyncResult to something more concrete to
get the result that you want. You will have to call the APIs through the
P/Invoke layer to do what you want.

Also, I am not quite sure what you are trying to do. You say that you
just want to get the number of bytes read. If you don't want to do anything
with the bytes, and you want to advance the stream pointer, then why not
just seek on the stream?
Actually, I am analyzing the data that was read, to do that I have to know
how much of it was read.

Finally, calling EndRead might call a context switch, depending on where
you call it. If you call it in a thread other than the callback thread,
then it might cause a context switch. However, if you call it in the thread
that fires the asynchronous notification, then you should not have a context
switch.


SOOooo...., From what you are saying could I conclude that the EndRead API
check to see if it was called in the context of the completion thread, in
this case no wait will be done and the OVERLAPPED.hEvent will not be waited
on?



Do you base what you are saying on common scenes or there is a formal
Microsoft documentation for this type of data, I would be happy to get any
pointer leading to this kind of stuff.

Hope this helps.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Nadav said:
Hi,

I am using FileStream's Async API: BeginRead/EndRead, upon completion
callback execution I use the read data and call EndRead, Taking that in
mind, I Wonder... does calling EndRead will cause a context switch? What is
the kernel object used for blocking EndRead calls? Event and mutex cause a
context switch even when the object is signaled and no wait is needed, usage
of critical section prevent this switch from happening... what is the object
used by EndRead? will it cause a context switch? My Guess is that the
EndRead uses an Event as the OVERLAPPED structure used with IO Completion
routines use an event for completion indications, if my assumption is true
calling EndRead from the completion callback will cause an un-neccesary
context switch, one that can be saved by querying the amount of bytes read
in a way other then calling EndRead... ( is there such a way? Is there a
non-explicit interface to IAsyncResponce? Can it be cast to somewhat more
detailed structure? )
Note that I use EndRead in the completion callback merely to get the
amount of bytes read, if I could get this amount by in a way other then
calling EndRead It would solve the problem... Is there another way of
getting the amount of read bytes? is there a way of extracting the internal
OVERLAPPED structure from the IAsyncResult object?
 
Thanks for your responce, my remarks are bellow
Remember that the code is JIT compiled, the compiler may generate different
code for pinned references than unpinned references.
Still I would expect that the Assembler code provided by the unmanged
debugger while debugging the application will resemble the code AFTER it was
JITed so the corresponding GC '__pin' manipulations will have it's asm
signature...
If performance is that critical, I would consider using something else than
.NET. .NET provides a level of abstraction that comes with a cost. Just out
of interest, if you wrote this application in native C++, how would you
prevent Windows from moving the memory containing the buffers to the swap
file?
I would use the Win32 VirtualLock/Unlock API, this will prevent page faults
while accessing the 'locked' range.
If you allocate the objects at the start of program execution, they would be
located at the start of the managed heap. Objects are allocated continuously
from the start of the managed heap, as objects become disposed the GC will
compact the heap to reduce the number of actual memory pages used. This
still wouldn't prevent Windows from paging all the memory to the swap file.

Chris

Nadav said:
Thanks for your immediate response, concerning the '__pin' keyword causes
the GC to prevent moving the buffer in memory ( and not manipulate any
refcount ), how does it do that? there must be some assembler code to
instruct the GC that this is a '__pined' variable so it would know not to
move it, looking at the assembler code produced by the compiler
(provided
at
the root query) I can't see anything as such... It seems as the '__pin'
keyword has no effect on the assembler code being generated by the compiler,
why is that? how can it be guaranteed that the memory pointed to by
'pbtArray' will stay valid for the duration it is being used...



(*)Another thing: Taking in mind what you have said concerning the way
GC
is
operating, Is it possible to prevent the GC from moving memory in the first
place? e.g. lets say I have a performance critical application, I allocate
(apriory) a collection of buffers to be used by the App, those buffers
should be moved as less as possible during runtime, how can I achieve that
using the .NET Framework????



Nadav.


Christopher Kimbell said:
The garbage collection is done by the runtime, not the application, therefor
there is no GC code in your application code.
If Microsoft embedded GC manipulation code in the apllication code, it would
be impossible to change GC policy in the future.

Pinning an object prevents the GC from moving the reference in memory, it
has nothing to do with reference counting. The GC periodically moves things
around so that the memory used is located together in memory.

Chris

Hi,

I am writing a mixed mode application, I have a mixed mode Assembly
manipulating a managed byte[] array, to access this array in unmanaged code
I '__pin' the array, As I understand, pining an object guarantee that it
will not be collected by the GC ( by increasing it's refcount or so ),
Taking that in mind, looking at the code generated by the compiler I can't
see anything taking care of the GC refcount... following is the pinned
variable with the corresponding dis-assembly section:

****************** Mixed mode C++ code line ******************
BYTE __pin *pbtArray = &btArray[0];

******************** The dis-assembly ***********************
00000019 cmp dword ptr [esi+4],0 // makes sure that NULL !=
&btArray[0]
0000001d ja 00000026 // if it is not NULL go three
lines bellow
0000001f xor ecx,ecx
00000021 call 7227F90B // call some exception
handling procedure...
00000026 lea eax,[esi+8] // get the address of
&btArray[0] to eax
00000029 mov dword ptr [ebp-14h],eax // pbtArray = content of eax
********************************************************
Why there is no GC manipulation code? isn't it needed?

The original code:
********************************************************
virtual int NotArray(System::Byte btArray __gc[])
{
int i = 0;
BYTE __pin *pbtArray = &btArray[0];
for(i; i < btArray->Length; i++)
pbtArray <<= 1;
return 0;
}

Nadav
http://www.ddevel.com


 
Nadav,

See inline:
Actually, I am analyzing the data that was read, to do that I have to know
how much of it was read.

This number is returned to you on the call to EndRead.
SOOooo...., From what you are saying could I conclude that the EndRead API
check to see if it was called in the context of the completion thread, in
this case no wait will be done and the OVERLAPPED.hEvent will not be waited
on?

If you wait on the WaitHandle returned by the AsyncWaitHandle property
on the IAsyncResult interface, then the event will be waited on.

However, you don't necessarily have to do this. What you can do is
provide a callback to the call to BeginRead, and then when the callback is
completed, call EndRead. Calling EndRead at this point will not cause a
wait on the handle to be performed, because the operation is complete at
that point. The code that executes at that point is called in the thread
that received the IO Completion notification.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Hope this helps.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Nadav said:
Hi,

I am using FileStream's Async API: BeginRead/EndRead, upon completion
callback execution I use the read data and call EndRead, Taking that in
mind, I Wonder... does calling EndRead will cause a context switch? What is
the kernel object used for blocking EndRead calls? Event and mutex cause a
context switch even when the object is signaled and no wait is needed, usage
of critical section prevent this switch from happening... what is the object
used by EndRead? will it cause a context switch? My Guess is that the
EndRead uses an Event as the OVERLAPPED structure used with IO Completion
routines use an event for completion indications, if my assumption is true
calling EndRead from the completion callback will cause an un-neccesary
context switch, one that can be saved by querying the amount of bytes read
in a way other then calling EndRead... ( is there such a way? Is there a
non-explicit interface to IAsyncResponce? Can it be cast to somewhat more
detailed structure? )
Note that I use EndRead in the completion callback merely to get the
amount of bytes read, if I could get this amount by in a way other then
calling EndRead It would solve the problem... Is there another way of
getting the amount of read bytes? is there a way of extracting the internal
OVERLAPPED structure from the IAsyncResult object?
 
Well, Concerning I am calling the EndRead from within the callback context: win32 use the OVERLAPPED structure for IO completion operation, this struct has an event variable that could be waited on for the IO Completion call is completed ( similar to calling Stream.EndRead ).
Now, taking in mind what was just said, I guess the .NET Framework use the same language to communicate with the kerenl as win32 use, this means that the completion event of the Win32 OVERLAPPED structure used by Win32 may be used by the .NET Framework ( this is a part of the interface with the kernel ), I assume that EndRead internally waits on this event ( managed by the kernel ).
Waiting on an Event object will cause a context switch weather it is signaled or not ( in contract to a wait on a critical section ), some kernel implementation of the wait functionality should be executed in a kernel thread, to achive that a context switch is requiered. Taking that in mind, EndRead MUST ( and probabely do ) wait on this event when it is called in a context other then the AsyncCallback, however, it is possible that before waiting on the event a context check is done and the wait is called only for threads other then the one who called the AsyncCallback. I just want to make sure weather EndRead waits on the event and by doing so causes a context switch, if so I want to figure out a different way of extracting the amount of bytes read, a way that will not cause a context switch.

Nadav
http://www.ddevel.com


Nicholas Paldino said:
Nadav,

See inline:
Actually, I am analyzing the data that was read, to do that I have to know
how much of it was read.

This number is returned to you on the call to EndRead.
SOOooo...., From what you are saying could I conclude that the EndRead API
check to see if it was called in the context of the completion thread, in
this case no wait will be done and the OVERLAPPED.hEvent will not be waited
on?

If you wait on the WaitHandle returned by the AsyncWaitHandle property
on the IAsyncResult interface, then the event will be waited on.

However, you don't necessarily have to do this. What you can do is
provide a callback to the call to BeginRead, and then when the callback is
completed, call EndRead. Calling EndRead at this point will not cause a
wait on the handle to be performed, because the operation is complete at
that point. The code that executes at that point is called in the thread
that received the IO Completion notification.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Hope this helps.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Hi,

I am using FileStream's Async API: BeginRead/EndRead, upon completion
callback execution I use the read data and call EndRead, Taking that in
mind, I Wonder... does calling EndRead will cause a context switch? What is
the kernel object used for blocking EndRead calls? Event and mutex cause a
context switch even when the object is signaled and no wait is needed, usage
of critical section prevent this switch from happening... what is the object
used by EndRead? will it cause a context switch? My Guess is that the
EndRead uses an Event as the OVERLAPPED structure used with IO Completion
routines use an event for completion indications, if my assumption is true
calling EndRead from the completion callback will cause an un-neccesary
context switch, one that can be saved by querying the amount of bytes read
in a way other then calling EndRead... ( is there such a way? Is there a
non-explicit interface to IAsyncResponce? Can it be cast to somewhat more
detailed structure? )

Note that I use EndRead in the completion callback merely to get the
amount of bytes read, if I could get this amount by in a way other then
calling EndRead It would solve the problem... Is there another way of
getting the amount of read bytes? is there a way of extracting the internal
OVERLAPPED structure from the IAsyncResult object?

Nadav
http://www.ddevel.com
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Back
Top