2017-06-12 3 views
1

私は画像のレンダリングのパフォーマンスを把握しようとし、可変画像とPNGを使用してフルスクリーン画像を描画するコードを作成しました。なぜこのイメージレンダリングベンチマークがIOSではクラッシュしますが、シミュレータではクラッシュしませんか?

コードはシミュレータでうまく動作しますが、iPhone SEでは50秒後にクラッシュしたり、100万個の画像がなくなります。

シミュレータでクラッシュせず、jvisualvmでメモリリークが見られないので、バグか別の説明がありますか?ここ

コードである:

public class FormMeasureImage extends Form implements Painter { 
    abstract class Wallpaper implements Painter { 
     private Component componentParent; 

     public Wallpaper(Component aComponentParent) { 
      componentParent = aComponentParent; 
     } 

     public void paint(Graphics aGraphics, Rectangle aRectangle) { 
      aGraphics.drawImage(
        getImage(new Dimension(componentParent.getWidth(), componentParent.getHeight())), 
        0, 
        0); 
     } 

     public abstract Image getImage(Dimension aDimension); 
    } 

    class WallpaperTiledIcons extends Wallpaper { 
     private Image image; 
     private Dimension dimension; 

     public WallpaperTiledIcons(Component aComponentParent) { 
      super(aComponentParent); 
     } 

     public Image getImage(Dimension aDimension) { 
      if ((null == image || !dimension.equals(aDimension)) && null != aDimension) { 
       dimension = new Dimension(aDimension); 
       Label labelPattern = new Label("1234567890"); 
       Style styleLabelPattern = labelPattern.getAllStyles(); 
       styleLabelPattern.setBorder(Border.createEmpty()); 
       styleLabelPattern.setMargin(0, 0, 0, 0); 
//    byte[] bytes = new byte[4]; 
//    Arrays.fill(bytes, Style.UNIT_TYPE_PIXELS); 
//    styleLabelPattern.setPaddingUnit(bytes); 
       styleLabelPattern.setPadding(0, 0, 0, 1); 
       Dimension preferredSizeLabelPattern = labelPattern.getPreferredSize(); 
       labelPattern.setSize(preferredSizeLabelPattern); 
       Image imagePattern = Image.createImage(
         preferredSizeLabelPattern.getWidth(), 
         preferredSizeLabelPattern.getHeight(), 
         0x00000000); 
       Graphics graphicsImagePattern = imagePattern.getGraphics(); 
       graphicsImagePattern.setAlpha(255); 
       labelPattern.paint(graphicsImagePattern); 
       image = Image.createImage(
         aDimension.getWidth(), 
         aDimension.getHeight(), 
         0xff606060); 
       Graphics graphics = image.getGraphics(); 
       if (graphics.isAntiAliasingSupported()) { 
        graphics.setAntiAliased(true); 
       } 
       int canvasWidth = preferredSizeLabelPattern.getWidth(), canvasHeight = preferredSizeLabelPattern.getHeight(); 
       int[] clip = graphics.getClip(); 
       Rectangle rectangleClip = new Rectangle(clip[0], clip[1], clip[2], clip[3]); 
       int columns = (rectangleClip.getX() + rectangleClip.getWidth())/canvasWidth + 1; 
       int rows = (rectangleClip.getY() + rectangleClip.getHeight())/canvasHeight + 1; 
       for (int row = 0; row < rows; row++) { 
        for (int column = 0; column < columns; column++) { 
         int x = canvasWidth * column; 
         int y = canvasHeight * row; 
         Rectangle rectangle = new Rectangle(x, y, canvasWidth, canvasHeight); 
         if (!rectangleClip.intersects(rectangle)) { 
          continue; 
         } 
         graphics.drawImage(imagePattern, x, y); 
        } 
       } 
      } 
      return image; 
     } 
    } 

    abstract class Stage { 
     long millisTotal; 
     long tally; 
     TextArea textArea; 

     public Stage(String aName) { 
      textArea = new TextArea(); 
      textArea.setEditable(false); 
      getContentPane().add(textArea); 
      stages.add(this); 
     } 

     abstract void perform(); 
     abstract boolean isPainted(); 
    } 

    private Wallpaper wallpaper; 
    private List<Stage> stages = new ArrayList<>(); 
    private Iterator<Stage> iteratorStages; 
    private Image imageEncoded; 

    public FormMeasureImage() { 
     super("FormMeasureImage", new BoxLayout(BoxLayout.Y_AXIS)); 
     setScrollableX(false); 
     setScrollableY(true); 
     Style styleForm = getAllStyles(); 
     styleForm.setBgTransparency(255); 
     styleForm.setBgPainter(this); 
     TextArea textArea = new TextArea(); 
     textArea.setEditable(false); 
     textArea.setText("Measuring image throughput."); 
     add(textArea); 
    } 

    @Override 
    public void paint(Graphics aGraphics, Rectangle aRectangle) { 
     if (null == iteratorStages) { 
      new Stage("create") { 
       void perform() { 
        long millisBefore = System.currentTimeMillis(); 
        wallpaper = new WallpaperTiledIcons(FormMeasureImage.this); 
        wallpaper.getImage(aRectangle.getSize()); 
        millisTotal += System.currentTimeMillis() - millisBefore; 
        tally++; 
        textArea.setText("create: " + millisTotal + "/" + tally); 
       } 

       boolean isPainted() { 
        return false; 
       } 
      }; 
      new Stage("mutable") { 
       void perform() { 
        long millisBefore = System.currentTimeMillis(); 
        for (int index = 0; index < 1000; index++) { 
         wallpaper.paint(aGraphics, aRectangle); 
         tally++; 
        } 
        millisTotal += System.currentTimeMillis() - millisBefore; 
        textArea.setText("mutable: " + millisTotal + "/" + tally); 
       } 

       boolean isPainted() { 
        return true; 
       } 
      }; 
      new Stage("encoding") { 
       void perform() { 
        long millisBefore = System.currentTimeMillis(); 
        try { 
         millisBefore = System.currentTimeMillis(); 
         ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); 
         ImageIO.getImageIO().save(wallpaper.getImage(null), byteArrayOutputStream, ImageIO.FORMAT_PNG, 1); 
         byteArrayOutputStream.close(); 
         imageEncoded = Image.createImage(new ByteArrayInputStream(byteArrayOutputStream.toByteArray())); 
         tally++; 
         millisTotal += System.currentTimeMillis() - millisBefore; 
         textArea.setText("encoding: " + millisTotal + "/" + tally); 
        } catch (IOException e) { 
         throw new RuntimeException(e.toString()); 
        } 
        millisTotal += System.currentTimeMillis() - millisBefore; 
        tally++; 
        textArea.setText("encoding: " + millisTotal + "/" + tally); 
       } 

       boolean isPainted() { 
        return false; 
       } 
      }; 
      new Stage("encoded") { 
       void perform() { 
        long millisBefore = System.currentTimeMillis(); 
        for (int index = 0; index < 1000; index++) { 
         aGraphics.drawImage(
           imageEncoded, 
           0, 
           0); 
         tally++; 
        } 
        millisTotal += System.currentTimeMillis() - millisBefore; 
        textArea.setText("encoded: " + millisTotal + "/" + tally); 
       } 

       boolean isPainted() { 
        return true; 
       } 
      }; 
      iteratorStages = stages.iterator(); 
     } 
     while (!perform().isPainted()) {;} 
    } 

    private Stage perform() { 
     if (!iteratorStages.hasNext()) { 
      iteratorStages = stages.iterator(); 
     } 
     Stage stage = iteratorStages.next(); 
     stage.perform(); 
     return stage; 
    } 
} 
+0

ここでコードが多すぎます。あなたが問題のある部分を絞り込んで、推測できるようになるまで、私は削除を提案します。 –

+0

内側のクラス 'Wallpaper'と' WallpaperTiledIcons'はバックグラウンドで変更可能な画像を作成してから、繰り返し実行する時間を繰り返し測定するということを知ったらあまりにも多くのコードはありません。 –

+0

iPad Air 2では、コードがiPhone SEよりもずっと速くクラッシュします。 –

答えて

0

テストケースは、EDTをオフ復号EDT違反が含まれていることと思われます。これはいくつかのケースでは機能しますが、使用量が多いためクラッシュします。

UIコードをスレッドセーフにすることは、プラットフォームが2倍になるという難しい作業です。

+0

ここのコードにはEDTの問題はありません。私は問題https://github.com/codenameone/CodenameOne/issues/2133から派生したプルーフコードを修正しました - それでもクラッシュします。 –

+0

あなたはまだ 'threadEncodingLoop.start()'を呼び出しています。サンプルが大きすぎるため、何かが見つからない可能性があります。 –

+0

はい、ループがループし、多くのデコードが行われます(オプションで多くのエンコーディングも可能です)。 EDTで画像を決定する必要はありませんか?とにかく私はここでコードを抽出しました。別の例ではEDTのみで実行され、同じものがクラッシュしました。 –

関連する問題