Windows 10上的JavaFX 8性能问题

时间:2016-03-16 21:35:43

标签: java performance javafx javafx-8 windows-10

我有一个基本的JavaFX程序,包含一个带有一些标签和几个按钮等的窗口。在OSX和Linux上,一切都很好,但在Windows 10上,移动主窗口似乎给我的图形带来了巨大压力卡片,每当我在应用程序的窗口和另一个窗口之间切换时,整个屏幕都会闪烁一秒钟。这只适用于此应用程序,该系统是一款高性能游戏装备,配备G-Sync,980 GTX,i7-6700k,16 GB RAM,双显示器等,并且在各种CPU和GPU基准测试中表现非常出色,真的,真的,不应该在屏幕上移动窗口时遇到任何问题。

当我在任务管理器中观察Java进程时,RAM使用情况没有任何明显的变化,并且当在整个屏幕上移动窗口时,CPU使用率仅为~1.4%。当拖动窗口时,它似乎只在20 FPS左右更新,而在我的系统上移动任何其他窗口似乎以60+ FPS运行。简而言之,在视觉上渲染我的JavaFX窗口时会出现某种奇怪的性能瓶颈。

据我所知,我没有使用任何3D功能或任何类似的东西,而且我没有做任何奇怪的JavaFX。我的窗口创建代码基于Oracle的标准教程,介绍了如何初始化JavaFX窗口等等。

下面是我的JavaFX窗口的初始化代码,以及来自控制器的init方法:

Main.start():

@Override
public void start(Stage primaryStage) throws Exception {
    primaryStage.hide();
    lockInstance();
    Platform.setImplicitExit(false);
    hostServices = HostServicesFactory.getInstance(this);
    AccountManager.init();
    if(OS.isLinux()) {
        CURRENT_OS = OS_TYPE.LINUX;
    } else if(OS.isMacOS()) {
        CURRENT_OS = OS_TYPE.OSX;
    } else if(OS.isWindows()) {
        CURRENT_OS = OS_TYPE.WINDOWS;
    }
    System.out.println("detected os: " + CURRENT_OS);

    //AccountManager.urlPrefix = "http://localhost:8080/api/";

    String res = "ERROR";
    try {
        res = JWSystem.getAppBundleName();
    } catch (Exception e) {}
    if(!res.contains("ERROR"))
        DEPLOY_MODE = true;
    System.out.println("DEPLOY_MODE: " + DEPLOY_MODE);

    prefs = Preferences.userNodeForPackage(this.getClass());
    FIRST_RUN = prefs.getBoolean("first_run", true);
    prefs.putBoolean("first_run", false);
    System.out.println("FIRST_RUN: " + FIRST_RUN);

    if(FIRST_RUN && DEPLOY_MODE) {
        createDesktopIcon();
    }

    // setup
    Thread t = new Thread(new Runnable() {
        @Override
        public void run() {
            if(CURRENT_OS == OS_TYPE.LINUX)
                SystemIcons.initUbuntuMimeTypes();
            if(FIRST_RUN && DEPLOY_MODE) {
                addStartupEntry();
            }
        }
    });
    t.start();

    // load UI
    Parent root = FXMLLoader.load(getClass().getResource("assets/main.fxml"));
    primaryStage.resizableProperty().setValue(Boolean.FALSE);
    primaryStage.setTitle("DuroCloud");
    Scene scene = new Scene(root, 600, 400);
    mainScene = scene;
    primaryStage.setScene(scene);
    mainStage = primaryStage;
    scene.getStylesheets().addAll(getClass().getResource("assets/overrides.css").toExternalForm());
    primaryStage.show();

    primaryStage.setOnCloseRequest(new EventHandler<WindowEvent>() {
        public void handle(WindowEvent we) {
            Platform.exit();
            System.out.println("Stage is closing");
            System.exit(0);
        }
    });
}

Controller.initialize():

    public void initialize(URL fxmlFileLocation, ResourceBundle resources) {

        faFolderIconImage = new Image(this.getClass().getResourceAsStream("assets/fa-folder_256_0_464646_none.png"));
        faFileIconImage = new Image(this.getClass().getResourceAsStream("assets/fa-file_256_0_464646_none.png"));
        faTextFileIconImage = new Image(this.getClass().getResourceAsStream("assets/fa-file-text_256_0_464646_none.png"));
        faPdfFileIconImage = new Image(this.getClass().getResourceAsStream("assets/fa-file-pdf-o_256_0_464646_none.png"));
        faMovieFileIconImage = new Image(this.getClass().getResourceAsStream("assets/fa-file-movie-o_256_0_464646_none.png"));
        faImageFileIconImage = new Image(this.getClass().getResourceAsStream("assets/fa-file-image-o_256_0_464646_none.png"));
        faExcelFileIconImage = new Image(this.getClass().getResourceAsStream("assets/fa-file-excel-o_256_0_464646_none.png"));
        faCodeFileIconImage = new Image(this.getClass().getResourceAsStream("assets/fa-file-code-o_256_0_464646_none.png"));
        faAudioFileIconImage = new Image(this.getClass().getResourceAsStream("assets/fa-file-audio-o_256_0_464646_none.png"));
        faArchiveFileIconImage = new Image(this.getClass().getResourceAsStream("assets/fa-file-archive-o_256_0_464646_none.png"));

        // text files
        iconMap.put("txt", faTextFileIconImage);
        iconMap.put("doc", faTextFileIconImage);
        iconMap.put("docx", faTextFileIconImage);
        iconMap.put("rtf", faTextFileIconImage);
        iconMap.put("asc", faTextFileIconImage);
        iconMap.put("cfg", faTextFileIconImage);
        iconMap.put("log", faTextFileIconImage);
        iconMap.put("ini", faTextFileIconImage);
        iconMap.put("odt", faTextFileIconImage);

        // pdf
        iconMap.put("pdf", faPdfFileIconImage);

        // movie files
        String[] movie_formats = new String[] {"webm", "mkv", "flv", "vob", "ogv", "drc", "avi", "mov", "wmv", "yuv",
                "rm", "rmvb", "asf", "mp4", "m4p", "m4v", "mpg", "mp2", "mpeg", "mpe", "mpv", "svi",
                "3gp", "mxf", "roq", "nsv"};
        for(String format : movie_formats) {
            iconMap.put(format, faMovieFileIconImage);
        }

        // image files
        String[] image_formats = new String[] {"png", "bmp", "jpg", "jpeg", "tiff", "gif", "raw"};
        for(String format : image_formats) {
            iconMap.put(format, faImageFileIconImage);
        }

        // excel
        iconMap.put("xls", faExcelFileIconImage);
        iconMap.put("ods", faExcelFileIconImage);
        iconMap.put("xlsx", faExcelFileIconImage);

        // code
        iconMap.put("rb", faCodeFileIconImage);
        iconMap.put("js", faCodeFileIconImage);
        iconMap.put("html", faCodeFileIconImage);
        iconMap.put("htm", faCodeFileIconImage);
        iconMap.put("css", faCodeFileIconImage);
        iconMap.put("xml", faCodeFileIconImage);
        iconMap.put("php", faCodeFileIconImage);
        iconMap.put("exe", faCodeFileIconImage);
        iconMap.put("sh", faCodeFileIconImage);
        iconMap.put("py", faCodeFileIconImage);
        iconMap.put("bat", faCodeFileIconImage);
        iconMap.put("jar", faCodeFileIconImage);
        iconMap.put("java", faCodeFileIconImage);
        iconMap.put("c", faCodeFileIconImage);
        iconMap.put("cpp", faCodeFileIconImage);
        iconMap.put("h", faCodeFileIconImage);
        iconMap.put("makefile", faCodeFileIconImage);
        iconMap.put("make", faCodeFileIconImage);

        // audio
        iconMap.put("asf", faAudioFileIconImage);
        iconMap.put("mp3", faAudioFileIconImage);
        iconMap.put("flac", faAudioFileIconImage);
        iconMap.put("ogg", faAudioFileIconImage);
        iconMap.put("wav", faAudioFileIconImage);
        iconMap.put("wma", faAudioFileIconImage);
        iconMap.put("webm", faAudioFileIconImage);

        // archive
        iconMap.put("7z", faArchiveFileIconImage);
        iconMap.put("zip", faArchiveFileIconImage);
        iconMap.put("rar", faArchiveFileIconImage);
        iconMap.put("tar", faArchiveFileIconImage);
        iconMap.put("gz", faArchiveFileIconImage);
        iconMap.put("bz", faArchiveFileIconImage);


        VBox accountAltVbox = new VBox();
        HBox accountAltHbox = new HBox();
        accountAltHbox.setAlignment(Pos.CENTER);
        accountAltVbox.setLayoutX(60.0);
        accountAltVbox.setLayoutY(40.0);
        accountAltVbox.setSpacing(8);
        accountEmailLabel.setText("test");
        accountEmailLabel.setFont(new Font(18));
        accountAltContent.setPrefWidth(800);
        accountAltContent.setPrefHeight(800);
        accountAltContent.getChildren().add(accountAltVbox);
        accountAltVbox.getChildren().add(new Label("Logged in as:"));
        accountAltHbox.getChildren().add(accountEmailLabel);
        accountAltVbox.getChildren().add(accountAltHbox);
        accountAltVbox.getChildren().add(accountLogoutButton);

        UIFonts.setFontAwesomeGlyph(upButton, FontAwesomeIcon.LEVEL_UP);
        UIFonts.setFontAwesomeGlyph(refreshButton, FontAwesomeIcon.REFRESH);
        UIFonts.setFontAwesomeGlyph(openButton, FontAwesomeIcon.FOLDER_OPEN);
        UIFonts.setFontAwesomeGlyph(saveButton, FontAwesomeIcon.DOWNLOAD);
        UIFonts.setFontAwesomeGlyph(deleteButton, FontAwesomeIcon.TRASH);
        UIFonts.setFontAwesomeGlyph(addButton, FontAwesomeIcon.PLUS);
        UIFonts.setFontAwesomeGlyph(backupDirectoriesButton, FontAwesomeIcon.CLOUD);

        loginEmailField.setOnKeyPressed(this::handleEmailFieldEnter);
        loginPasswordField.setOnKeyPressed(this::handlePasswordFieldEnter);
        loginButton.setOnAction(this::handleLoginButtonAction);
        forgotPasswordLink.setOnAction(this::visitForgotPassword);
        accountLogoutButton.setOnAction(this::handleLogoutButton);
        refreshButton.setOnAction(this::handleRefreshButton);
        upButton.setOnAction(this::handleUpButton);
        addButton.setOnAction(this::handleAddButton);
        deleteButton.setOnAction(this::handleDeleteButton);

        fileBrowser.setCellFactory(new Callback<ListView<BrowserItem>, ListCell<BrowserItem>>() {
            @Override
            public ListCell<BrowserItem> call(ListView<BrowserItem> param) {
                return new BrowserItemCell();
            }
        });

        fileBrowser.setOnMouseClicked(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent event) {
                if(event.getClickCount() == 2) {
                    BrowserItem selected = fileBrowser.getSelectionModel().getSelectedItem();
                    if(selected != null) {
                        if(selected.isFile) {
                            downloadSelected();
                        } else {
                            currentDirectoryId = selected.file.file_id;
                            refresh();
                        }
                    }
                }
            }
        });

        openButton.setDisable(true);
        saveButton.setDisable(true);
        deleteButton.setDisable(false);

        if(!AccountManager.loggedIn()) {
            mainTabPane.getSelectionModel().select(accountTab);
            optionsTab.setDisable(true);
            myFilesTab.setDisable(true);
        }
    }

1 个答案:

答案 0 :(得分:0)

所以事实证明这是一个与JavaFX无关的线程相关问题,一旦我在我的应用程序中重新组织了一些东西,它就消失了。事实证明,每当拖动窗口时,就会调用列表视图上的更新方法,从而导致计算成本高昂的方法运行。但有趣的是,性能差异 仅在Windows 10系统上显而易见,并且确实会导致一些重大的图形问题。

TLDR:在控制绘图代码中不要做昂贵的计算,特别是在Windows 10上。