Serial Write Performance

Hi All,

I am using serial.sys to send and receive the data, where the upper edge is
NDIS connectionless miniport .
I am trying to improve my driver’s perforamance. After analysising, my
SerialWritePort function (Sends the data out) takes more time than any
other function call .
Please see the code snippet for reference. How can I make it better.
All your suggestions are welcome.

Thanks in Advance,
Cyril

NTSTATUS SerialWritePort(PDEVICE_OBJECT pDevObj,
UCHAR *Buffer,
UINT BufferLength)
{

NTSTATUS Status = STATUS_SUCCESS;
PIRP pNewIrp = NULL;
PIO_STACK_LOCATION IoStackLocation = NULL;
KEVENT KEvent;

SERIAL_STATUS comStat;

KdPrint((“SerialWritePort ===>\n”));

KeInitializeEvent(&KEvent,NotificationEvent,FALSE);

pNewIrp = IoAllocateIrp ( pDevObj->StackSize, FALSE );

if(pNewIrp == NULL)
{
Status = STATUS_UNSUCCESSFUL;
KdPrint((“IoAllocateIrp FAILED\n”));
KdPrint((“<=== SerialWritePort\n”));
return Status;
}
else
{
IoStackLocation = IoGetNextIrpStackLocation ( pNewIrp );

IoStackLocation->MajorFunction = IRP_MJ_WRITE;
IoStackLocation->Parameters.Write.Length = BufferLength;
pNewIrp->AssociatedIrp.SystemBuffer = Buffer;

/* The Event status will be set in Serial_IoCompletionRoutine */

IoSetCompletionRoutine(pNewIrp,Serial_IoCompletionRoutine,&KEvent,TRUE,TRUE,
TRUE);

Status = IoCallDriver(pDevObj, pNewIrp);

if (Status == STATUS_PENDING)
{
Status = KeWaitForSingleObject(&KEvent,
Executive,
KernelMode,
FALSE, // Not alertable
NULL);
}

if (Status == STATUS_SUCCESS)
{
KdPrint((“WritePort SUCCESS\n”));
Status = pNewIrp->IoStatus.Status;
}
else
{
PrintStatusInfo(Status);
}

IoFreeIrp( pNewIrp );
KdPrint((“<=== SerialWritePort\n”));
return Status;
}
}

Cyril,

Removing the KdPrint would be a start, I suppose…

When analyzing the timing, were you using VTune or a similar tool? If so,
it should be able to isolate which part of SerialWrite is being the part
that takes the most time. If you’re using a “How much time does it take
from calling this function until I get back”, that’s not a good measure for
a function that calls KeWaitForSingleObject, as it’s not actually doing
anything whilst waiting for the event, just letting some other process or
thread run.

I’m a little bit surprised that you’re able to get even close to hoging a
reasonably modern CPU using the serial port, because at 115200 bps, the a
1GHz CPU does about 8600 cycles per BIT, and thus about 70K cycles per byte
output on the serial port. Assuming that you’re not experiencing a
full-duplex operation, at which point you’ve “only” got about 35K cycles
per byte. But even then, I’d be very surprised that you manage to use up
that many cycles…

If you’re not using 100% of the cpu cycles (or near it), why are you
worried about performance?


Mats

xxxxx@lists.osr.com wrote on 03/17/2005 08:10:08 AM:

Hi All,

I am using serial.sys to send and receive the data, where the upper edge
is
NDIS connectionless miniport .
I am trying to improve my driver’s perforamance. After analysising, my
SerialWritePort function (Sends the data out) takes more time than any
other function call .
Please see the code snippet for reference. How can I make it better.
All your suggestions are welcome.

Thanks in Advance,
Cyril

NTSTATUS SerialWritePort(PDEVICE_OBJECT pDevObj,
UCHAR *Buffer,
UINT BufferLength)
{

NTSTATUS Status = STATUS_SUCCESS;
PIRP pNewIrp = NULL;
PIO_STACK_LOCATION IoStackLocation = NULL;
KEVENT KEvent;

SERIAL_STATUS comStat;

KdPrint((“SerialWritePort ===>\n”));

KeInitializeEvent(&KEvent,NotificationEvent,FALSE);

pNewIrp = IoAllocateIrp ( pDevObj->StackSize, FALSE );

if(pNewIrp == NULL)
{
Status = STATUS_UNSUCCESSFUL;
KdPrint((“IoAllocateIrp FAILED\n”));
KdPrint((“<=== SerialWritePort\n”));
return Status;
}
else
{
IoStackLocation = IoGetNextIrpStackLocation ( pNewIrp );

IoStackLocation->MajorFunction = IRP_MJ_WRITE;
IoStackLocation->Parameters.Write.Length = BufferLength;
pNewIrp->AssociatedIrp.SystemBuffer = Buffer;

/* The Event status will be set in Serial_IoCompletionRoutine */

IoSetCompletionRoutine(pNewIrp,Serial_IoCompletionRoutine,&KEvent,TRUE,TRUE,

TRUE);

Status = IoCallDriver(pDevObj, pNewIrp);

if (Status == STATUS_PENDING)
{
Status = KeWaitForSingleObject(&KEvent,
Executive,
KernelMode,
FALSE, // Not alertable
NULL);
}

if (Status == STATUS_SUCCESS)
{
KdPrint((“WritePort SUCCESS\n”));
Status = pNewIrp->IoStatus.Status;
}
else
{
PrintStatusInfo(Status);
}

IoFreeIrp( pNewIrp );
KdPrint((“<=== SerialWritePort\n”));
return Status;
}
}


Questions? First check the Kernel Driver FAQ at http://www.
osronline.com/article.cfm?id=256

You are currently subscribed to ntdev as: xxxxx@3dlabs.com
To unsubscribe send a blank email to xxxxx@lists.osr.com

ForwardSourceID:NT0000ED2A

Thanks Mat

Cyril

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com]On Behalf Of Mats PETERSSON
Sent: Thursday, March 17, 2005 7:11 PM
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] Serial Write Performance

Cyril,

Removing the KdPrint would be a start, I suppose…

When analyzing the timing, were you using VTune or a similar tool? If so,
it should be able to isolate which part of SerialWrite is being the part
that takes the most time. If you’re using a “How much time does it take
from calling this function until I get back”, that’s not a good measure for
a function that calls KeWaitForSingleObject, as it’s not actually doing
anything whilst waiting for the event, just letting some other process or
thread run.

I’m a little bit surprised that you’re able to get even close to hoging a
reasonably modern CPU using the serial port, because at 115200 bps, the a
1GHz CPU does about 8600 cycles per BIT, and thus about 70K cycles per byte
output on the serial port. Assuming that you’re not experiencing a
full-duplex operation, at which point you’ve “only” got about 35K cycles
per byte. But even then, I’d be very surprised that you manage to use up
that many cycles…

If you’re not using 100% of the cpu cycles (or near it), why are you
worried about performance?


Mats

xxxxx@lists.osr.com wrote on 03/17/2005 08:10:08 AM:

Hi All,

I am using serial.sys to send and receive the data, where the upper edge
is
NDIS connectionless miniport .
I am trying to improve my driver’s perforamance. After analysising, my
SerialWritePort function (Sends the data out) takes more time than any
other function call .
Please see the code snippet for reference. How can I make it better.
All your suggestions are welcome.

Thanks in Advance,
Cyril

NTSTATUS SerialWritePort(PDEVICE_OBJECT pDevObj,
UCHAR *Buffer,
UINT BufferLength)
{

NTSTATUS Status = STATUS_SUCCESS;
PIRP pNewIrp = NULL;
PIO_STACK_LOCATION IoStackLocation = NULL;
KEVENT KEvent;

SERIAL_STATUS comStat;

KdPrint((“SerialWritePort ===>\n”));

KeInitializeEvent(&KEvent,NotificationEvent,FALSE);

pNewIrp = IoAllocateIrp ( pDevObj->StackSize, FALSE );

if(pNewIrp == NULL)
{
Status = STATUS_UNSUCCESSFUL;
KdPrint((“IoAllocateIrp FAILED\n”));
KdPrint((“<=== SerialWritePort\n”));
return Status;
}
else
{
IoStackLocation = IoGetNextIrpStackLocation ( pNewIrp );

IoStackLocation->MajorFunction = IRP_MJ_WRITE;
IoStackLocation->Parameters.Write.Length = BufferLength;
pNewIrp->AssociatedIrp.SystemBuffer = Buffer;

/* The Event status will be set in Serial_IoCompletionRoutine */

IoSetCompletionRoutine(pNewIrp,Serial_IoCompletionRoutine,&KEvent,TRUE,TRUE,

TRUE);

Status = IoCallDriver(pDevObj, pNewIrp);

if (Status == STATUS_PENDING)
{
Status = KeWaitForSingleObject(&KEvent,
Executive,
KernelMode,
FALSE, // Not alertable
NULL);
}

if (Status == STATUS_SUCCESS)
{
KdPrint((“WritePort SUCCESS\n”));
Status = pNewIrp->IoStatus.Status;
}
else
{
PrintStatusInfo(Status);
}

IoFreeIrp( pNewIrp );
KdPrint((“<=== SerialWritePort\n”));
return Status;
}
}


Questions? First check the Kernel Driver FAQ at http://www.
osronline.com/article.cfm?id=256

You are currently subscribed to ntdev as: xxxxx@3dlabs.com
To unsubscribe send a blank email to xxxxx@lists.osr.com

ForwardSourceID:NT0000ED2A


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

You are currently subscribed to ntdev as: xxxxx@future.futsoft.com
To unsubscribe send a blank email to xxxxx@lists.osr.com