dotnet / roslyn

The Roslyn .NET compiler provides C# and Visual Basic languages with rich code analysis APIs.
https://docs.microsoft.com/dotnet/csharp/roslyn-sdk/
MIT License
18.57k stars 3.95k forks source link

VS 2015 memory usage and perf after some hours of use #7082

Closed davidroth closed 7 years ago

davidroth commented 8 years ago

Hi guys,

I am currently working on a relatively decent solution and I am having problems with high memory usage of VS2015 after some time of usage.

I usually have to restart VS some times a day, because memory usage goes up to > 2 GB and the IDE becomes sluggish.

When opening the solution and building it the first time, VS usually consumes about 750MB. After some hours I usually have > 1.8 GB and the IDE gets slower and slower.

I have also noticed, that when using VS on multiple desktops (ex. undocking a code window on the 2nd screen), memory consumption increases even faster and the IDE becomes laggy in a relative short amount of time.

Are there any known issues regarding increasing memory consumption of VS2015? Or if not, whats the best way to debug this and provide you with some information to improve this? I could use a memory profiler and check which objects are alive if this is helpful for you?

Edit: I am not using resharper. I am using coderush for roslyn on one machine, however the issue remains when uninstalling coderush, so it's not related to it.

2015-11-26_114324

axel-habermaier commented 8 years ago

I also have to restart VS from time to time in order to get it fast again. I have Resharper installed, though, they're a known source for sluggishness. So I'm not sure whether it actually is Microsoft's fault. Do you use Resharper as well?

All in all, VS2012 was the fastest VS I've ever used for C# development. VS2015 is almost as bad as the horrible VS2010 performance-wise. I do realize that Roslyn was a huge change for VS and that it initially might sacrifice some performance now to get VS ready for the future (like the switch to WPF was with VS2010). But I really hope that VSnext will focus on performance again like they did with VS2012...

davidroth commented 8 years ago

@axel-habermaier No, i don't use Resharper. I use coderush for roslyn on one machine, however the issue remains when uninstalling coderush, so it's not related to it. Yes, I also hope that perf will be improved in upcoming updates. Roslyn is great, but perf was better in VS2013 (especially due to the memory leaks described in this issue).

ViIvanov commented 8 years ago

Do you use a CodeLens? I have the same problems with it in the big (60-70 projects) solution.

davidroth commented 8 years ago

I already disabled CodeLens. Performance with CodeLens enabled is worse though.

asvishnyakov commented 8 years ago

As @axel-habermaier says, Visual Studio require more memory at last versions. But I have no problems with it when I work with small projects. VS may use up to 1 GB of memory, but it acceptable price for convenience: I use a lot of features (like WPF designer or CodeLenses) and extensions (like ReSharper) which use a lot of memory. But when I twice rebuild Roslyn solution, VS consumes up to 2 GB of memory, that is a limit for 32-bit process. So, it may periodically freeze until I force gc (Ctrl+F12 twice). Memory profiling + move to 64-bit processes as soon as possible would be the best solution. Building VS with /LARGEADDRESSAWARE may be temporary solution.

kuhlenh commented 8 years ago

@davkean Can you take a look at this, particularly the possible issue around undocking code windows.

davidroth commented 8 years ago

@davkean

There is definitely something wrong when working with undocked code windows or with multiple windows in a horizontal/vertical split view. (Update1 installed)

VS becomes slower and slower, and memory usage increases. I have also noticed, that once closing all windows after working in multi window mode for some time, VS seems to run "amok". I constantly have 15-20% CPU usage on a 4K I7 4790K. Furthermore memory usage increases and decreases between 1400MB up to 2000MB, and it doesn't stop.

I took these 2 screenshots, while VS was just opened (with no code windows, samples taken within a 1 minute range ). When it hits the 2GB bar, GC runs and it jumps back to ~ 1400MB. It then constantly increases up to 2GB.

vsbugv2

vsbug

davkean commented 8 years ago

@davidroth I cannot repro this - I'm constantly using three screens of undocked windows, so it doesn't appear to be a general issue, it might be related to what tools windows or projects you have opened.

Does this occur with all projects? Does it occur when projects are closed?

Can you Send A Frown (Report a Problem) if you are using Update 1 and include "davkean" in the description of the issue, make sure you do this from another instance of VS and click Start Recording when it's at its worse: image.

davidroth commented 8 years ago

@davkean I have sent you a feedback with the recording. Although I just recorded once i noticed that memory started to increase up to 2.2 GB while doing nothing. Is this enough? You should get a heap dump from this right? Or do I have to record my whole VS session from the beginning?

To answer your other questions:

davidroth commented 8 years ago

@davkean

Here is a screenshot from some basic memory monitoring with dotMemory:

timeline

As you can see, there are three major collections/allocation phases within 20s timeframe. Memory ranges between 1.4 - 1.9 GB in this sample. (Solution opened, no windows opened, not working with VS)

alloc

In the above screenshot you can see the top allocated managed objects.

I took this after about an hour of work. However this time I did not undock any windows. So my previous assertion about this being an undocking issue may be invalid. However working with multiple windows certainly does accelerate the issue I am describing here.

jedidja commented 8 years ago

We have exactly the same problem. Even after closing a project, VS CPU usage will continue to be high and memory usage often climbs to 2GB. It's bad enough that this happens while working on a solution when it's open but unexplainable that it happens after closing it.

Drauka commented 8 years ago

To further build the case for some investigation into this issue, I would add that we have the same issue in our dev team. Memory consumption increases to over 2.5Gb causing visual studio to become unresponsive to the point where the only option is to restart.

WayneEllery commented 8 years ago

We are having the same issue with our Dev team. Our solution is very big. It has 46 projects. I've also installed Update 2 RC and it still has not fixed the issue. We are using Resharper and CodeLens. When first opening the solution it is about 1Gb and then memory increases and after 4 hours or so it goes over 2GB and then Visual Studio becomes unresponsive.

jmarolf commented 8 years ago

Out of curiosity, how many of those reporting problems on this thread are using resharper?

jedidja commented 8 years ago

I'm not running ReSharper or any other similar extension and there are a couple others on our team with the same issue. We also have people with ReSharper installed who experience the same issue.

jmarolf commented 8 years ago

Thanks @jedidja, good to narrow things down. For everyone on this thread that has this happen to them, it would be greatly appreciated if you clicked Send A Frown (Report a Problem) as per @davkean 's instructions

jedidja commented 8 years ago

@jmarolf Ok, submitted. We have about 20 projects in our solution and are running Community Edition. We've tried 2015 Update 2 RC and still see the same problem. I'd be happy to do a screen-sharing session with anyone on the team if that would help.

jedidja commented 8 years ago

Also, the 30-35% CPU usage happens regardless of machine. It's the same on both my desktop (i5-3570K 3.4Ghz) and also on my 2015 Macbook Pro (i7 2.5 Ghz) under Parallels.

asvishnyakov commented 8 years ago

@jmarolf I had this issue both in clear Visual Studio and with ReSharper

davidroth commented 8 years ago

I have updated to VS2015 Update 2 today, and now I am getting this new message bar when the memory consumption is over about 1.5 GB:

image

However, my overall system memory consumption looks like this: image

@davkean Have you been able to reproduce this issue in your labs or do you need additional reports?

davkean commented 8 years ago

+@heejaechang do you know what's going on here? Are we fragmented?

DanielRowe1 commented 8 years ago

Update 2 has make VS just about unusable for our large project:

Description: The application requested process termination through System.Environment.FailFast(string message). Message: System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown. at Microsoft.CodeAnalysis.Diagnostics.AnalysisState.<>c.b16_2() at Roslyn.Utilities.ObjectPool1.CreateInstance() at Roslyn.Utilities.ObjectPool1.AllocateSlow() at Roslyn.Utilities.ObjectPool1.Allocate() at Microsoft.CodeAnalysis.Diagnostics.AnalysisState.PerAnalyzerState.OnCompilationEventGenerated(CompilationEvent compilationEvent, AnalyzerActionCounts actionCounts) at Microsoft.CodeAnalysis.Diagnostics.AnalysisState.OnCompilationEventsGenerated_NoLock(ImmutableArray1 compilationEvents, SyntaxTree filterTreeOpt, AnalyzerDriver driver, CancellationToken cancellationToken) at Microsoft.CodeAnalysis.Diagnostics.AnalysisState.GenerateSimulatedCompilationSourceEvents(SyntaxTree tree, Compilation compilation, Func`4 getCachedSemanticModel, AnalyzerDriver driver, CancellationToken cancellationToken) at Microsoft.CodeAnalysis.Diagnostics.AnalysisState.d18.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.CodeAnalysis.Diagnostics.CompilationWithAnalyzers.d52.MoveNext() Stack: at System.Environment.FailFast(System.String, System.Exception) at Microsoft.CodeAnalysis.FailFast.OnFatalException(System.Exception) at Microsoft.CodeAnalysis.FatalError.Report(System.Exception, System.Action`1) at Microsoft.CodeAnalysis.FatalError.ReportUnlessCanceled(System.Exception) at Microsoft.CodeAnalysis.Diagnostics.CompilationWithAnalyzers+d52.MoveNext() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(System.Threading.Tasks.Task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(System.Threading.Tasks.Task) at Microsoft.CodeAnalysis.Diagnostics.CompilationWithAnalyzers+d52.MoveNext() at System.Runtime.CompilerServices.AsyncMethodBuilderCore+MoveNextRunner.InvokeMoveNext(System.Object) at System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean) at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean) at System.Runtime.CompilerServices.AsyncMethodBuilderCore+MoveNextRunner.Run() at System.Threading.Tasks.AwaitTaskContinuation.RunOrScheduleAction(System.Action, Boolean, System.Threading.Tasks.Task ByRef) at System.Threading.Tasks.Task.FinishContinuations() at System.Threading.Tasks.Task.FinishStageThree() at System.Threading.Tasks.Task`1[[System.Canon, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]].TrySetResult(System.Canon) at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1[[System.Canon, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]].SetResult(System.Canon) at Microsoft.CodeAnalysis.Diagnostics.CompilationWithAnalyzers+d53.MoveNext() at System.Runtime.CompilerServices.AsyncMethodBuilderCore+MoveNextRunner.InvokeMoveNext(System.Object) at System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean) at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean) at System.Runtime.CompilerServices.AsyncMethodBuilderCore+MoveNextRunner.Run() at System.Threading.Tasks.AwaitTaskContinuation.RunOrScheduleAction(System.Action, Boolean, System.Threading.Tasks.Task ByRef) at System.Threading.Tasks.Task.FinishContinuations() at System.Threading.Tasks.Task.FinishStageThree() at System.Threading.Tasks.Task1[[System.Threading.Tasks.VoidTaskResult, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]].TrySetResult(System.Threading.Tasks.VoidTaskResult) at System.Threading.Tasks.UnwrapPromise1[[System.Threading.Tasks.VoidTaskResult, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]].TrySetFromTask(System.Threading.Tasks.Task, Boolean) at System.Threading.Tasks.UnwrapPromise1[[System.Threading.Tasks.VoidTaskResult, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]].Invoke(System.Threading.Tasks.Task) at System.Threading.Tasks.Task.FinishContinuations() at System.Threading.Tasks.Task.FinishStageThree() at System.Threading.Tasks.Task1[[System.Threading.Tasks.VoidTaskResult, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]].TrySetResult(System.Threading.Tasks.VoidTaskResult) at System.Runtime.CompilerServices.AsyncTaskMethodBuilder1[[System.Threading.Tasks.VoidTaskResult, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]].SetResult(System.Threading.Tasks.VoidTaskResult) at System.Runtime.CompilerServices.AsyncTaskMethodBuilder1[[System.Threading.Tasks.VoidTaskResult, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]].SetResult(System.Threading.Tasks.Task1<System.Threading.Tasks.VoidTaskResult>) at Microsoft.CodeAnalysis.Diagnostics.AnalyzerDriver+<>c__DisplayClass36_0+<<Initialize>b__0>d.MoveNext() at System.Runtime.CompilerServices.AsyncMethodBuilderCore+MoveNextRunner.InvokeMoveNext(System.Object) at System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean) at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean) at System.Runtime.CompilerServices.AsyncMethodBuilderCore+MoveNextRunner.Run() at System.Threading.Tasks.AwaitTaskContinuation.RunOrScheduleAction(System.Action, Boolean, System.Threading.Tasks.Task ByRef) at System.Threading.Tasks.Task.FinishContinuations() at System.Threading.Tasks.Task.FinishStageThree() at System.Threading.Tasks.Task1[[System.Canon, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]].TrySetResult(System.Canon) at System.Runtime.CompilerServices.AsyncTaskMethodBuilder1[[System.__Canon, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]].SetResult(System.__Canon) at Microsoft.CodeAnalysis.Diagnostics.AnalyzerDriver+<GetAnalyzerActionsAsync>d__83.MoveNext() at System.Runtime.CompilerServices.AsyncMethodBuilderCore+MoveNextRunner.InvokeMoveNext(System.Object) at System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean) at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean) at System.Runtime.CompilerServices.AsyncMethodBuilderCore+MoveNextRunner.Run() at System.Threading.Tasks.AwaitTaskContinuation.RunOrScheduleAction(System.Action, Boolean, System.Threading.Tasks.Task ByRef) at System.Threading.Tasks.Task.FinishContinuations() at System.Threading.Tasks.Task.FinishStageThree() at System.Threading.Tasks.Task1[[System.Canon, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]].TrySetResult(System.Canon) at System.Runtime.CompilerServices.AsyncTaskMethodBuilder1[[System.__Canon, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]].SetResult(System.__Canon) at Microsoft.CodeAnalysis.Diagnostics.AnalyzerManager+<GetAnalyzerActionsAsync>d__12.MoveNext() at System.Runtime.CompilerServices.AsyncMethodBuilderCore+MoveNextRunner.InvokeMoveNext(System.Object) at System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean) at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean) at System.Runtime.CompilerServices.AsyncMethodBuilderCore+MoveNextRunner.Run() at System.Threading.Tasks.AwaitTaskContinuation.RunOrScheduleAction(System.Action, Boolean, System.Threading.Tasks.Task ByRef) at System.Threading.Tasks.Task.FinishContinuations() at System.Threading.Tasks.Task.FinishStageThree() at System.Threading.Tasks.Task1[[System.Canon, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]].TrySetResult(System.Canon) at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1[[System.Canon, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]].SetResult(System.Canon) at Microsoft.CodeAnalysis.Diagnostics.AnalyzerManager+d__8.MoveNext() at System.Runtime.CompilerServices.AsyncMethodBuilderCore+MoveNextRunner.InvokeMoveNext(System.Object) at System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean) at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean) at System.Runtime.CompilerServices.AsyncMethodBuilderCore+MoveNextRunner.Run() at System.Threading.Tasks.AwaitTaskContinuation.RunOrScheduleAction(System.Action, Boolean, System.Threading.Tasks.Task ByRef) at System.Threading.Tasks.Task.FinishContinuations() at System.Threading.Tasks.Task.FinishStageThree() at System.Threading.Tasks.Task.FinishStageTwo() at System.Threading.Tasks.Task.Finish(Boolean) at System.Threading.Tasks.Task.ExecuteWithThreadLocal(System.Threading.Tasks.Task ByRef) at System.Threading.Tasks.Task.ExecuteEntry(Boolean) at System.Threading.Tasks.Task.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem() at System.Threading.ThreadPoolWorkQueue.Dispatch() at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()

awbushnell commented 8 years ago

@davkean I was just working back and forth with Marc Paine from the debugger team as I was seeing crashes consistently in our large solution when debugging. We have tracked it to high memory usage in both Rosalyn and the debugger, see the problem report here:

https://connect.microsoft.com/VisualStudio/feedback/details/2524533/crash-when-debugging

The size of our solution is 246 projects, which are native C++/Managed C++ and C#. Anyway, another vote, if you will regarding this memory issue... I am on Visual Studio 2015 Update 2.

AndrewGretton commented 8 years ago

We're experiencing this issue too (gradual memory creep over process lifetime that often results in a crash). We have:

Removing our Code Analysis rulesets has helped the most to reduce memory usage (but now we have no Code Analysis :-1: )

VS Update 2 fixed issue #7784, which greatly reduced occurrences of runaway RAM usage, but we still experience excessive memory creep over time.

Our event logs are similar to @DanielRowe1 - always an OutOfMemoryException in a Roslyn stack trace.

davkean commented 8 years ago

tag @KevinH-MS @heejaechang @ManishJayaswal

davkean commented 8 years ago

Sorry @mavasani

ManishJayaswal commented 8 years ago

@srivatsn

mavasani commented 8 years ago

@DanielRowe1 The issue you mentioned is a dupe of https://github.com/dotnet/roslyn/issues/10365, for which there is an open PR for the fix. Meanwhile, you can try to avoid this by using the workaround mentioned in https://github.com/dotnet/roslyn/issues/10365#issuecomment-207107438, which avoided the OOM.

mavasani commented 8 years ago

@AndrewGretton you probably want to try the workaround as well.

improwise commented 8 years ago

Visual Studio 2015 is probably the worst Visual Studio ever. It is so bad that we have it listed as the biggest threat to our current software project, far above stuff like lack of resources and money. Our GUI developers are threatening to quit if we don't switch to AngularJS instead. We've tried EVERYTHING but no luck. Microsoft really need to get their act together here.

mavasani commented 8 years ago

@improwise Can you please share a memory dump so we can investigate the issues?

morrisjoe commented 8 years ago

@improwise , Is it possible to connect with you over email or a phone call to understand your issues deeper. I work for Microsoft and have helped customers solve problems related to VS crashes/performance. My email is jomorris@micorosoft.com. Please, let us connect off-line and I can help you.

morrisjoe commented 8 years ago

@DanielRowe1 @davidroth @AndrewGretton @axel-habermaier , I would like to connect with you folks as well to dig deeper and understand issues. My email is jomorris@micorosoft.com. Please, let us connect off-line and I can help you.

marcells commented 8 years ago

@DanielRowe1 @davidroth @AndrewGretton @axel-habermaier @morrisjoe

We had that "Low memory" problem, the crashes and the high CPU load, too. It disappeared, when we switched off the full solution analysis in Visual Studio. It now has almost the same speed as VS 2013.

Options -> Text Editor -> C# -> Advanced -> Enable full solution analysis

I've made a blog entry with all of our performance tweaks, if you're interested in. https://mspi.es/blog/5-Performance-Tweaks-for-Visual-Studio-2015-and-large-solutions

morrisjoe commented 8 years ago

@marcells Indeed the 1st workaround suggested in your blog, we are planning to make that (Disable full solution analysis) the default in a micro update that we are planning to do to VS2015 Update2 in the coming days.

davidroth commented 8 years ago

Disabling full solution analysis does not help a lot. Another observation: Switching between git branches with lots of changes shows the same issue at my machine, with much faster memory increase. Just had to review several branches and VS grew from 600MB up to 2.1 GB in just ~10 minutes. This is probably because VS reloads/re-analyzes the solution when switching branches wich lots of changes.

DanielRowe1 commented 8 years ago

We have disable full solution analysis and code lens and it has helped but we still get OOM just not as often.

Our solution has 170 projects or so and approx 2.2million lines of code. VS2015 is just so slow.

It there going to be a update we can install to fix these leaks?

heejaechang commented 8 years ago

related issue - https://github.com/dotnet/roslyn/issues/10365

awbushnell commented 8 years ago

FYI, I worked with @morrisjoe off-line and tried private fix and it seemed to help and am ok with shipping it.

morrisjoe commented 8 years ago

That's good news @awbushnell . If others who have 100's of .NET projects in their solution and want to try the private fix that will being relief to mem usage and CPU utilization when doing full solution analysis with lots of analyzers involved, please let me know and I can work with you off-line for you to try out the private fix. Once I get more confirmation that it is indeed good, then I can work towards making it available as public release with VS2013 Update3.

davkean commented 8 years ago

By VS 2013, I think you mean VS 2015.

davidroth commented 8 years ago

Is this private fix somewhere on GitHub or is it too private? :D

Our solution has about 40 projects, would like to try the fix.

jmarolf commented 8 years ago

You can get the vsix here I'm working on making getting this stuff simpler so you can easily try out builds at your discretion. Usual caveats apply, these are nightly builds, there may be issues.

heejaechang commented 8 years ago

@jmarolf can people use roslyn insider feed "https://www.myget.org/F/roslyn-master-nightly/vsix/" to get latest nightly build if they want to live at the edge?

jmarolf commented 8 years ago

@heejaechang they can, though there have been some mef composition failures that I wanted to fix before people jumped in with both feet.

ilmax commented 8 years ago

@jmarolf how can we restore to the official vsix in case of problems?

jmarolf commented 8 years ago

@ilmax yes, uninstall the extension and remove the vsix gallery.

ilmax commented 8 years ago

@jmarolf thank you, just to double check, this vsix applies to VS 2015 update 2 right?

jmarolf commented 8 years ago

@ilmax right, it will only work on Update 2. I don't think I added any install restrictions, so it may allow you to install it on Update 1 or RTM, but it won't work (or if anything works its by accident).

SamJongenelen commented 7 years ago

Same here, I'd like to try. Otherwise, in what timeframe will this be released (or available in a hotfix?)