slightly reduce memory usage — move settingsSavingComponents from ComponentStoreImpl because for each module we have instance

This commit is contained in:
Vladimir Krivosheev
2018-05-18 14:19:06 +02:00
parent bccc089f29
commit 5bdd08522c
5 changed files with 78 additions and 84 deletions
@@ -25,7 +25,7 @@ const val APP_CONFIG = "\$APP_CONFIG$"
private const val FILE_STORAGE_DIR = "options"
private const val DEFAULT_STORAGE_SPEC = "${PathManager.DEFAULT_OPTIONS_FILE_NAME}${FileStorageCoreUtil.DEFAULT_EXT}"
class ApplicationStoreImpl(private val application: Application, pathMacroManager: PathMacroManager? = null) : ComponentStoreImpl() {
class ApplicationStoreImpl(private val application: Application, pathMacroManager: PathMacroManager? = null) : ComponentStoreWithExtraComponents() {
override val storageManager = ApplicationStorageManager(application, pathMacroManager)
// number of app components require some state, so, we load default state in test mode
@@ -23,7 +23,6 @@ import com.intellij.openapi.util.JDOMExternalizable
import com.intellij.openapi.util.JDOMUtil
import com.intellij.openapi.util.registry.Registry
import com.intellij.openapi.vfs.newvfs.impl.VfsRootAccess
import com.intellij.project.isDirectoryBased
import com.intellij.ui.AppUIUtil
import com.intellij.util.ArrayUtilRt
import com.intellij.util.SmartList
@@ -74,7 +73,6 @@ internal fun setRoamableComponentSaveThreshold(thresholdInSeconds: Int) {
abstract class ComponentStoreImpl : IComponentStore {
private val components = Collections.synchronizedMap(THashMap<String, ComponentInfo>())
private val settingsSavingComponents = com.intellij.util.containers.ContainerUtil.createLockFreeCopyOnWriteList<SettingsSavingComponent>()
internal open val project: Project?
get() = null
@@ -84,11 +82,7 @@ abstract class ComponentStoreImpl : IComponentStore {
override abstract val storageManager: StateStorageManager
override final fun initComponent(component: Any, isService: Boolean) {
if (component is SettingsSavingComponent) {
settingsSavingComponents.add(component)
}
override fun initComponent(component: Any, isService: Boolean) {
var componentName = ""
try {
@Suppress("DEPRECATION")
@@ -130,50 +124,27 @@ abstract class ComponentStoreImpl : IComponentStore {
return componentName
}
override fun save(readonlyFiles: MutableList<SaveSessionAndFile>, isForce: Boolean) {
var errors: MutableList<Throwable>? = null
override final fun save(readonlyFiles: MutableList<SaveSessionAndFile>, isForce: Boolean) {
val errors: MutableList<Throwable> = SmartList<Throwable>()
fun execute(handler: () -> Unit) {
try {
handler()
}
catch (e: Throwable) {
if (errors == null) {
errors = SmartList<Throwable>()
}
errors!!.add(e)
}
}
// component state uses scheme manager in an ipr project, so, we must save it before
val isIprProject = project?.let { !it.isDirectoryBased } ?: false
if (isIprProject) {
settingsSavingComponents.firstOrNull { it is SchemeManagerFactoryBase }?.let {
execute {
it.save()
}
}
}
beforeSaveComponents(errors)
val externalizationSession = if (components.isEmpty()) null else storageManager.startExternalization()
if (externalizationSession != null) {
errors = doSaveComponents(isForce, externalizationSession, errors)
doSaveComponents(isForce, externalizationSession, errors)
}
for (settingsSavingComponent in settingsSavingComponents) {
if (!isIprProject || settingsSavingComponent !is SchemeManagerFactoryBase) {
execute {
settingsSavingComponent.save()
}
}
}
afterSaveComponents(errors)
execute {
try {
saveAdditionalComponents(isForce)
}
catch (e: Throwable) {
errors.add(e)
}
if (externalizationSession != null) {
errors = doSave(externalizationSession.createSaveSessions(), readonlyFiles, errors)
doSave(externalizationSession.createSaveSessions(), readonlyFiles, errors)
}
CompoundRuntimeException.throwIfNotEmpty(errors)
}
@@ -181,10 +152,15 @@ abstract class ComponentStoreImpl : IComponentStore {
protected open fun saveAdditionalComponents(isForce: Boolean) {
}
private fun doSaveComponents(isForce: Boolean, externalizationSession: ExternalizationSession, _errors: MutableList<Throwable>?): MutableList<Throwable>? {
protected open fun beforeSaveComponents(errors: MutableList<Throwable>) {
}
protected open fun afterSaveComponents(errors: MutableList<Throwable>) {
}
protected open fun doSaveComponents(isForce: Boolean, externalizationSession: ExternalizationSession, errors: MutableList<Throwable>): MutableList<Throwable>? {
val isUseModificationCount = Registry.`is`("store.save.use.modificationCount", true)
var errors = _errors
val names = ArrayUtilRt.toStringArray(components.keys)
Arrays.sort(names)
val timeLogPrefix = "Saving"
@@ -223,9 +199,6 @@ abstract class ComponentStoreImpl : IComponentStore {
info.updateModificationCount(currentModificationCount)
}
catch (e: Throwable) {
if (errors == null) {
errors = SmartList<Throwable>()
}
errors.add(Exception("Cannot get $name component state", e))
}
@@ -259,7 +232,9 @@ abstract class ComponentStoreImpl : IComponentStore {
runUndoTransparentWriteAction {
try {
VfsRootAccess.allowRootAccess(absolutePath)
CompoundRuntimeException.throwIfNotEmpty(doSave(sessions))
val errors: MutableList<Throwable> = SmartList<Throwable>()
doSave(sessions, errors = errors)
CompoundRuntimeException.throwIfNotEmpty(errors)
}
finally {
VfsRootAccess.disallowRootAccess(absolutePath)
@@ -283,12 +258,11 @@ abstract class ComponentStoreImpl : IComponentStore {
protected open fun doSave(saveSessions: List<SaveSession>,
readonlyFiles: MutableList<SaveSessionAndFile> = arrayListOf(),
prevErrors: MutableList<Throwable>? = null): MutableList<Throwable>? {
var errors = prevErrors
errors: MutableList<Throwable>) {
for (session in saveSessions) {
errors = executeSave(session, readonlyFiles, prevErrors)
executeSave(session, readonlyFiles, errors)
}
return errors
return
}
private fun initJdomExternalizable(@Suppress("DEPRECATION") component: JDOMExternalizable, componentName: String): String? {
@@ -541,10 +515,7 @@ abstract class ComponentStoreImpl : IComponentStore {
}
}
internal fun executeSave(session: SaveSession,
readonlyFiles: MutableList<SaveSessionAndFile>,
previousErrors: MutableList<Throwable>?): MutableList<Throwable>? {
var errors = previousErrors
internal fun executeSave(session: SaveSession, readonlyFiles: MutableList<SaveSessionAndFile>, errors: MutableList<Throwable>) {
try {
session.save()
}
@@ -553,13 +524,8 @@ internal fun executeSave(session: SaveSession,
readonlyFiles.add(SaveSessionAndFile(e.session ?: session, e.file))
}
catch (e: Exception) {
if (errors == null) {
errors = SmartList<Throwable>()
}
errors.add(e)
}
return errors
}
private fun findNonDeprecated(storages: Array<Storage>) = storages.firstOrNull { !it.deprecated } ?: throw AssertionError(
@@ -0,0 +1,46 @@
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.configurationStore
import com.intellij.openapi.components.SettingsSavingComponent
import com.intellij.project.isDirectoryBased
abstract class ComponentStoreWithExtraComponents : ComponentStoreImpl() {
private val settingsSavingComponents = com.intellij.util.containers.ContainerUtil.createLockFreeCopyOnWriteList<SettingsSavingComponent>()
override fun initComponent(component: Any, isService: Boolean) {
if (component is SettingsSavingComponent) {
settingsSavingComponents.add(component)
}
super.initComponent(component, isService)
}
override final fun beforeSaveComponents(errors: MutableList<Throwable>) {
// component state uses scheme manager in an ipr project, so, we must save it before
val isIprProject = project?.let { !it.isDirectoryBased } ?: false
if (isIprProject) {
settingsSavingComponents.firstOrNull { it is SchemeManagerFactoryBase }?.let {
try {
it.save()
}
catch(e: Throwable) {
errors.add(e)
}
}
}
}
override final fun afterSaveComponents(errors: MutableList<Throwable>) {
val isIprProject = project?.let { !it.isDirectoryBased } ?: false
for (settingsSavingComponent in settingsSavingComponents) {
if (!isIprProject || settingsSavingComponent !is SchemeManagerFactoryBase) {
try {
settingsSavingComponent.save()
}
catch (e: Throwable) {
errors.add(e)
}
}
}
}
}
@@ -49,7 +49,7 @@ internal val PROJECT_FILE_STORAGE_ANNOTATION = FileStorageAnnotation(PROJECT_FIL
internal val DEPRECATED_PROJECT_FILE_STORAGE_ANNOTATION = FileStorageAnnotation(PROJECT_FILE, true)
// cannot be `internal`, used in Upsource
abstract class ProjectStoreBase(override final val project: ProjectImpl) : ComponentStoreImpl(), IProjectStore {
abstract class ProjectStoreBase(override final val project: ProjectImpl) : ComponentStoreWithExtraComponents(), IProjectStore {
// protected setter used in upsource
// Zelix KlassMaster - ERROR: Could not find method 'getScheme()'
var scheme = StorageScheme.DEFAULT
@@ -302,7 +302,7 @@ private open class ProjectStoreImpl(project: ProjectImpl, private val pathMacroM
}
}
override fun doSave(saveSessions: List<SaveSession>, readonlyFiles: MutableList<SaveSessionAndFile>, prevErrors: MutableList<Throwable>?): MutableList<Throwable>? {
override fun doSave(saveSessions: List<SaveSession>, readonlyFiles: MutableList<SaveSessionAndFile>, errors: MutableList<Throwable>) {
try {
saveProjectName()
}
@@ -310,17 +310,16 @@ private open class ProjectStoreImpl(project: ProjectImpl, private val pathMacroM
LOG.error("Unable to store project name", e)
}
var errors = prevErrors
beforeSave(readonlyFiles)
errors = super.doSave(saveSessions, readonlyFiles, errors)
super.doSave(saveSessions, readonlyFiles, errors)
val notifications = NotificationsManager.getNotificationsManager().getNotificationsOfType(UnableToSaveProjectNotification::class.java, project)
if (readonlyFiles.isEmpty()) {
for (notification in notifications) {
notification.expire()
}
return errors
return
}
if (!notifications.isEmpty()) {
@@ -336,7 +335,7 @@ private open class ProjectStoreImpl(project: ProjectImpl, private val pathMacroM
val oldList = readonlyFiles.toTypedArray()
readonlyFiles.clear()
for (entry in oldList) {
errors = executeSave(entry.session, readonlyFiles, errors)
executeSave(entry.session, readonlyFiles, errors)
}
CompoundRuntimeException.throwIfNotEmpty(errors)
@@ -345,8 +344,6 @@ private open class ProjectStoreImpl(project: ProjectImpl, private val pathMacroM
dropUnableToSaveProjectNotification(project, getFilesList(readonlyFiles))
throw IComponentStore.SaveCancelledException()
}
return errors
}
protected open fun beforeSave(readonlyFiles: MutableList<SaveSessionAndFile>) {
@@ -1,18 +1,4 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.openapi.components;
import com.intellij.openapi.application.Application;
@@ -21,7 +7,6 @@ import com.intellij.openapi.application.Application;
* Component or service which implements this interfaces will be asked to save ({@link #save}) custom settings (in their own custom way)
* when {@link Application#saveSettings()} (for Application level components) or {@link com.intellij.openapi.project.Project#save()}
* (for Project level components) is invoked.
* @see BaseComponent
*/
public interface SettingsSavingComponent {
void save();