print filter weirdness

So I gave up and wrote my own binary print filter. So far, so good.
Except, now large print jobs like screen dumps take over 4-1/2 minutes
to come out of the printer!

Would posting code do any good? I doubt it. We’re using a proprietary
string class, CMN_CString… Even if I write the filter to just send it
straight through, it takes 4-1/2 minutes, so I don’t believe for a
second that it has anything to do with what the filter is doing to the
PostScript.

The invocation of phs-to-ps in the code below is REPLY blocked on
/sbin/pipe while the filter is running. I don’t get it.

Here’s the entire guts of the filter:

int PrintFilter(char* zPHSFileName)
{
int RetStat = 0;
CMN_CString cReadLine;
int iPageWidth = 0;
int iPageHeight = 0;
FILE *fpPSPipe = NULL;
char zSystemCommand[CMN_MAX_FNAME_LEN + 1];

sprintf(zSystemCommand, “phs-to-ps %s”, zPHSFileName);

fpPSPipe = popen(zSystemCommand, “r”);

if ( fpPSPipe == NULL )
{
RET_STAT_SET_FAIL(RetStat, CMN_TRUE);
}

if (int_PASS(RetStat))
{
char zChar = NULL;

while( (zChar = getc(fpPSPipe)) != EOF)
{
while ( (zChar != ‘\n’) && (zChar != EOF) )
{
cReadLine += zChar;
zChar = getc(fpPSPipe);
}

if ( cReadLine.FindString("/setpagedevice") == 0 )
{
int iStartIndex = cReadLine.FindChar(’[’) + 1;
int iEndIndex = cReadLine.FindChar(’]’);
CMN_CString cPageDims(cReadLine.mid(iEndIndex - iStartIndex,
iStartIndex));
int iHeightIndex = cPageDims.FindChar(’ ');
CMN_CString cPageWidth(cPageDims.left(iHeightIndex));
CMN_CString cPageHeight(cPageDims.right(cPageDims.Length() -
iHeightIndex));

iPageWidth = atoi(cPageWidth.GetString());
iPageHeight = atoi(cPageHeight.GetString());
cReadLine.Empty();
}
else if ( (cReadLine.FindString(“2 setlinecap”) == 0) && (iPageWidth >
iPageHeight) )
{
cout << cReadLine << endl;
do
{
zChar = getc(fpPSPipe);
cReadLine += zChar;
} while ( zChar != ‘\n’ );

cReadLine.Empty();
cout << “90 rotate” << endl;
}
else
{
cout << cReadLine << endl;
cReadLine.Empty();
}
}
}
pclose(fpPSPipe);
return(RetStat);
}

Roger Smith <hamtaro@hotmail.com> wrote:

So I gave up and wrote my own binary print filter. So far, so good.
Except, now large print jobs like screen dumps take over 4-1/2 minutes
to come out of the printer!

Would posting code do any good? I doubt it. We’re using a proprietary
string class, CMN_CString… Even if I write the filter to just send it
straight through, it takes 4-1/2 minutes, so I don’t believe for a
second that it has anything to do with what the filter is doing to the
PostScript.

The invocation of phs-to-ps in the code below is REPLY blocked on
/sbin/pipe while the filter is running. I don’t get it.

REPLY blocked on /sbin/pipe means that it’s blocked in write() because,
apparently, it produces data more quickly than your filter can read
them. What state is your filter in – is it READY or REPLY-blocked on
something else?


Here’s the entire guts of the filter:

int PrintFilter(char* zPHSFileName)
{
int RetStat = 0;
CMN_CString cReadLine;
int iPageWidth = 0;
int iPageHeight = 0;
FILE *fpPSPipe = NULL;
char zSystemCommand[CMN_MAX_FNAME_LEN + 1];

sprintf(zSystemCommand, “phs-to-ps %s”, zPHSFileName);

fpPSPipe = popen(zSystemCommand, “r”);

if ( fpPSPipe == NULL )
{
RET_STAT_SET_FAIL(RetStat, CMN_TRUE);
}

if (int_PASS(RetStat))
{
char zChar = NULL;

while( (zChar = getc(fpPSPipe)) != EOF)
{
while ( (zChar != ‘\n’) && (zChar != EOF) )
{
cReadLine += zChar;
zChar = getc(fpPSPipe);
}

if ( cReadLine.FindString("/setpagedevice") == 0 )
{
int iStartIndex = cReadLine.FindChar(’[’) + 1;
int iEndIndex = cReadLine.FindChar(’]’);
CMN_CString cPageDims(cReadLine.mid(iEndIndex - iStartIndex,
iStartIndex));
int iHeightIndex = cPageDims.FindChar(’ ');
CMN_CString cPageWidth(cPageDims.left(iHeightIndex));
CMN_CString cPageHeight(cPageDims.right(cPageDims.Length() -
iHeightIndex));

iPageWidth = atoi(cPageWidth.GetString());
iPageHeight = atoi(cPageHeight.GetString());
cReadLine.Empty();
}
else if ( (cReadLine.FindString(“2 setlinecap”) == 0) && (iPageWidth
iPageHeight) )
{
cout << cReadLine << endl;
do
{
zChar = getc(fpPSPipe);
cReadLine += zChar;
} while ( zChar != ‘\n’ );

cReadLine.Empty();
cout << “90 rotate” << endl;
}
else
{
cout << cReadLine << endl;
cReadLine.Empty();
}
}
}
pclose(fpPSPipe);
return(RetStat);
}

Wojtek Lerch wrote:

REPLY blocked on /sbin/pipe means that it’s blocked in write() because,
apparently, it produces data more quickly than your filter can read
them. What state is your filter in – is it READY or REPLY-blocked on
something else?

My filter is REPLY blocked on devu-prn.

Roger Smith <hamtaro@hotmail.com> wrote:

Wojtek Lerch wrote:
REPLY blocked on /sbin/pipe means that it’s blocked in write() because,
apparently, it produces data more quickly than your filter can read
them. What state is your filter in – is it READY or REPLY-blocked on
something else?

My filter is REPLY blocked on devu-prn.

That suggests that it, too, produces data more quickly than devu-prn can
take them.

Could you make an experiment, and set up your filter to write to a file,
and then cp the file to the printer? And time both steps?

Wojtek Lerch wrote:

Could you make an experiment, and set up your filter to write to a file,
and then cp the file to the printer? And time both steps?

I’m one step ahead of you. I tried this, and it takes a LOT less time to
write to the file first, then copy it to the printer. In fact, it’s
nearly as fast as raw phs-to-ps.

HOWEVER, that’s not an acceptable solution. The filter is a kluge on top
of a kluge already. I can’t be going three-deep with the kluges. The QC
people would never accept it.

I think we’ve seen a similar problem before. USB write()'s
seem to have a high per-write overhead. Can you try increasing
the output stream buffer size of your filter (using something
like setvbuf())?

Roger Smith <hamtaro@hotmail.com> wrote:

Wojtek Lerch wrote:
Could you make an experiment, and set up your filter to write to a file,
and then cp the file to the printer? And time both steps?

I’m one step ahead of you. I tried this, and it takes a LOT less time to
write to the file first, then copy it to the printer. In fact, it’s
nearly as fast as raw phs-to-ps.

HOWEVER, that’s not an acceptable solution. The filter is a kluge on top
of a kluge already. I can’t be going three-deep with the kluges. The QC
people would never accept it.

Roger Smith <hamtaro@hotmail.com> wrote:

Wojtek Lerch wrote:
Could you make an experiment, and set up your filter to write to a file,
and then cp the file to the printer? And time both steps?

I’m one step ahead of you. I tried this, and it takes a LOT less time to
write to the file first, then copy it to the printer. In fact, it’s
nearly as fast as raw phs-to-ps.

HOWEVER, that’s not an acceptable solution. The filter is a kluge on top
of a kluge already. I can’t be going three-deep with the kluges. The QC
people would never accept it.

I didn’t think about it as a solution – that’s why I called it an
“experiment”. I meant for this experiment to tell us which of the two
steps is responsible for the slowness and deserves to be investigated
further. If both steps turned out to be fast, it suggests that the
cause of the slowness must have something to do with the diference
between how your CMN_CString class writes the data to the device and how
cp does it. I agree with Angela’s suggestion that it’s likely related
to buffering.