none
GraphicsPath.PathPoints very very slow RRS feed

  • Question

  • Hi all;

    This is a bit unusual. We have a program in Java that runs very fast creating PostScript files. We convert this program to .NET using IKVM. The IKVM version of the program takes forever.

    The cause of this is on a call to TextLayout.draw() it works its way down in the code to Drawing2D.GraphicsPath.PathPoints. And that call is 97% of the total processing time. Most calls to PathPoints require seconds, sometimes tens of seconds. And all this is is a line of formatted text.

    Any idea what could be causing this to take so long?

    thanks - dave


    What we did for the last 6 months - Made the world's coolest reporting & docgen system even more amazing

    Wednesday, May 30, 2018 12:07 AM

Answers

  • I found the issue. In the IKVM library it was creating the PathPoints array each time it needed to get an array element. So the array was being recreated once per array element - which was a horrible hit.

    In other words:

    for (int i = 0; i < points.Length; i++) {

    PointF point = path.PathPoints[i];


    Is changed to:

    PointF[] points = path.PathPoints;
    for (int i = 0; i < points.Length; i++) {
    PointF point = points[i];



    What we did for the last 6 months - Made the world's coolest reporting & docgen system even more amazing

    • Marked as answer by DavidThi808 Thursday, May 31, 2018 10:18 PM
    Thursday, May 31, 2018 10:18 PM

All replies

  • Hi DavidThi808,

    Thank you for posting here.

    According to your description, does the code works well in jave? I am not good at java. What is the TextLayout.draw() in .net when you convert the java to .net?

    After you convert it to .net, which code works very slow? Could you provide the code for us?

    Best Regards,

    Wendy


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Wednesday, May 30, 2018 6:50 AM
    Moderator
  • It's spending a lot of time in GraphicsPath.PathPoints that is PointF[] (i.e.: a simple array) because the code is looping against it. Of course it should spend most of the time there.

    IMO, the code converts path to awt.Shape, then need to convert back to .NET native GraphicsPath to draw on Graphics object. It's not very efficient. (In fact, it would be faster to run in Java because no such conversion is needed to be done at all - all classes are native Java classes, no unnecessary translation is needed) While this library does enable your Java code run on .NET with minimal modification, if you need performance you're strongly recommended to rewrite it.

    Btw, since your code is used to generate report instead of reading PostScript files, it should be very efficient to rollout your own proxy Graphics class that have Graphics member methods that your code use (there is no need to implement anything that you're not using, and since you can copy file header and footer from the old files you generated, the PostScript command you'll need to handle would be just a dozen or two), but just storing it as PostScript command List<string> that you can write to file (with Header and Footer) on saving.







    Wednesday, May 30, 2018 7:28 AM
    Answerer
  • I think you're right, we'd be better keeping this all in .NET.

    There are various 3rd party Java libraries where you write to a Graphics2D superclass object and that object then creates a .ps, .svg, .png, etc. file. Is there the equivalent in .NET for a Graphics superclass?

    ??? - thanks - dave


    What we did for the last 6 months - Made the world's coolest reporting & docgen system even more amazing

    Wednesday, May 30, 2018 12:12 PM
  • Bummer - using Graphics2D.drawString() ends up in the same place with the same problem.

    What we did for the last 6 months - Made the world's coolest reporting & docgen system even more amazing

    Wednesday, May 30, 2018 7:16 PM
  • From the profiling data, I'd try to see if I can intercept at LineBuffer.write() call or even earlier steps.

    You spent that many time on GraphicsPath.PathPoints because you really have that many points to draw. To reduce the number of elements to process I'd try to intercept when your "report commands" are still lines, rectangle, font and text, rather than the already "converted to curve" drawing data.

    Like what I previously said, it'd be good for you to produce something that is similar to Graphics class, but instead of calling corresponding GDI+ commands, save the corresponding PostScript instruction to string list that will be written to file in the end. So in your report generating code, you call the real Graphics class to draw the report to screen, and call the similar-to-Graphics class to prepare the PostScript file.
    Thursday, May 31, 2018 1:29 AM
    Answerer
  • Yeah - the problem is this is looking like a lot of work.

    And an even bigger worry - that I don't get the PostScript exactly right and so a long period of tweaking the code.


    What we did for the last 6 months - Made the world's coolest reporting & docgen system even more amazing

    Thursday, May 31, 2018 2:42 AM
  • I found the issue. In the IKVM library it was creating the PathPoints array each time it needed to get an array element. So the array was being recreated once per array element - which was a horrible hit.

    In other words:

    for (int i = 0; i < points.Length; i++) {

    PointF point = path.PathPoints[i];


    Is changed to:

    PointF[] points = path.PathPoints;
    for (int i = 0; i < points.Length; i++) {
    PointF point = points[i];



    What we did for the last 6 months - Made the world's coolest reporting & docgen system even more amazing

    • Marked as answer by DavidThi808 Thursday, May 31, 2018 10:18 PM
    Thursday, May 31, 2018 10:18 PM