 Yeah, welcome. I would like to show you a little bit about the backgrounds in performance tuning in the Eclipse platform and give you an insight on that. Shortly introduced myself. I'm Carsten, working for ITIMIS, a company in Germany, and my main duty is working on a framework called Eclipse X-Text. That's for creating programming languages, and we heavily use Eclipse. I do it every day. And when I work with huge projects, X-Text is one of the largest projects at Eclipse, I hate to do wait for my IDE. So the thing is, what can we do to speed it up again? Yeah. What I actually do is, when I see something which is not as fast as I imagine, I immediately start a profiler and look what's actually happening behind the scenes. Actually, using a profiler is a good idea, unless you're a guy like that. Performance tuning is a little bit the hunt of the iceberg. So what you see is actually always the surface. And only if you cut off the surface, then another peak comes up, and then you see different things. So to tune code, you have to cut off everything what you see, and then the next thing comes up, and then you work on that. So it's quite a recursive action. Performance matters in many ways. First of all, there's a difference between tuning the performance in means of speed of the environment, but also in means of memory consumption. So these are often diverse to each other. When I want to improve the speed, I usually need more memory and vice versa. It is important that the start-up of the eclipse is fast. The eye must be snappy. Build processes are also long-running. For example, if you install software on the eclipse, this is a long-running task, and so there are many places to improve. And I would like to show you some examples of how we did this and where. For example, we recognize that if you have a large search result, 5,000 matches of string, and expand that tree, left side was eclipse oxygen, right side is eclipse photon, and we expand that at the same time. You see, okay, that's pretty fast now, and this is still blinking and waiting. Yeah, it's ugly, but what was happening behind the scenes, this tree here got refreshed all the time, and which each child that was expanded, it got refreshed again. And also the cursor came back and switched between the busy mode and the idle mode. Once you see that, it's quite easy to fix. It's actually very few, okay, you can't really read it, but the old code was just saying, okay, do expand everything, and the new code just turn off refreshing, then do the expand, and when the tree was expanded, you can refresh again the UI. So you just wait until the computation has happened, and then you just display it once and not with each node. Project build is also something which bothers me. I have a huge amount of projects in my workspace, and actually the project is a single thread. It's running on different threads, but it's running sequentially for each project, and each project has a set of project builders, like a Java builder and schema builder and whatever builders, and they run sequentially for each project. So what we are working now on is to enable parallelization of that. There's a new option which allows you to set, I want to build multiple projects at once, but this means that this works only when the builders configured on that project allow this also, and this is ongoing work at the moment. The Java builder has now the option that it can participate in such a process, but when you have a second builder which is not enabled in such a relaxed rule, then it will block again the workspace, and it will again run sequentially. But this is now what we improve. One builder after each other, that they allow locking of partial trees of the workspace. And when this is done, and you have unrelated projects in your workspace, the Eclipse built framework recognizes, okay, I can build these projects in parallel, and these must be sequential because I have a project relationship between them. When you work on macOS, there has also something being improved in the event dispatching. The code in the SWT implementation of macOS was whenever there was an event in the UI, and there are many events in UI, like mouse move, clicking, keyboard entering, whatever. It decided through a long, if else, cascade, what did you actually do? And in the 20th switch, it would maybe decide, okay, I moved the mouse. So you did 19 operations that did not make sense. So this was refactored to switch case. So now it could be decided on branch table what is actually the event that you did. The effect is, we have, that's actually a screenshot from profiler called Yorket that I'm heavily using. The effect is that here we saw that in the display class, the processing, this is within dispatching, took 13 seconds while measuring. The measuring case is actually 100,000 lines Java code, screwing that down. So you have plenty of events running in the UI. And both in new change, we could cut off almost one second of UI processing. And UI processing happens in just one single thread. So whatever you can save on the UI thread, this makes the UI more responsive. So it's, okay, it's just 5% but it's 5% more performance on UI at all. Let's take another example. We have Git project. We want to import projects. Can't really see what's written there but I'm not selecting the Git project. Say import projects and now I see a dialogue and you see here that it shows me very fast, which files and folders are now scanned. It looks fast but isn't. Let's do it nowadays and actually I did not see really anything. What's behind that? The thing is when the directory is scanned, it shows each and every single file on the UI thread. So, yeah, it makes a synchronous call to the UI thread for each file and folder. But actually you're only interested in knowing, okay, there's something happening. It's processing roughly that directory. We introduced a new API which is called the Frotler, which you can now use. And the idea is that you can suppress some messages. You can say, okay, it's not necessary to read more than one message per 100 milliseconds, for example. So, every message between is received but swallowed. And then by using that Frotler and to say, okay, use the update label function just only 100 milliseconds, that's fast enough for the human eye. So, you can report as many information as possible to the provis monitor, but you get only updates on the UI every 100 milliseconds. So, the UI is not slowed down. One hotspot that we identified is also where, during a complete build, is that the string replace all function are popped up in one use case. It's always dependent on the use case. This won't happen in many different other scenarios. But in this use case, it was a full project build of a huge workspace. It showed up that the replace all function costs six seconds of time. Okay, that's quite much on a machine that can compute an endless loop in four seconds. And actually what the suspicious method was here process name in the API tooling doesn't matter, but actually this is one of the hotspots that showed up. And the problematic code was this here. So, here you see, okay, replace all slash by dot looks quite normal. What's the problem here? Exactly. This is here using an irregular expression. Actually you can just replace that by the replace method and say, okay, replace character by character, but some unskilled programmer just use replace all because the intention was to replace all slashes by dots. But it's not fast. And, yeah, after that, the method got down here is string replace in this example to three milliseconds from six seconds to three milliseconds. Check for updates. If you use that function to search for new updates of plugins installed to Eclipse, it showed up that here we had hotspot in the XML writer. So, write in XML during that process cost two minutes. Of course, there's much happening there. The registries in Eclipse are XML based. And when you do updates and they are processed and edited and so on. Of course, you do many XML stuff there. But two minutes during an update process, only for writing XML seems a lot of time. What was the problem here? You can't really hear it's using an XML writer and print out characters or strings. The problem was only it was unbuffered. So, just simply writing this, wrapping this into a buffered writer, removed that completely. But, again, you have to, you need to have a use case where you see, okay, there might be a problem. Start a profile, look at what is happening, and then you will find that. By reading the code, you won't find this. Again, another use case was that, scoring down the 100,000 lines of Java code, we saw that many SWT errors were raised during that. And they actually cost some time. It's not much. It was, again, just a second. But looking into that was that, yeah, there was a function called, that tried to get an offset of a character at a specific point. And, yeah, this method can return, throw an exception when there is no character at this place. This is totally expected. So it was just swallowed this exception. And the problem just is, if you do this very frequently and use exceptions as return types, then the construction of exceptions is costly, because you have to create a new object and fill in the stack trace. And if you make this very often, then this costs time. We introduced just a new method in the new API method, which does the same, but returns a negative value in the case that there's no return value. Effect was, for this case, before the change, there were 10,000 illegal argument exceptions thrown. And we now saved 1.6 seconds processing time just by changing that. So small changes make an effect. Talking about memory a little bit, if you start up Eclipse, then you would recognize that it consumes not so much memory anymore. We are really tweaking that. For example, in JDT, we're tweaking the zero length arrays. So when you do not have annotations, for example, or whatever, then often the case is that you create a new array with zero length. And this wastes memory. We infected this by using constants, so that you have a single constant and say, okay, if you want to have an empty array, just use the constant. We can perfect all that. This is one change where we did this. For example, the code was children is new Java element with children size. Maybe you should check first, is the children collection empty? And if it's empty, then just use no elements constant. This is happening in Java tooling very frequently, and so you are wasting memory otherwise. And here we have another place where annotations in Java code, each method can have annotations and each parameter can have annotations and so on, but often you don't have any annotations. In the same case here, again, it was half a megabyte of waste. Sounds much, so it sounds few, but we are already micro tuning this. Java docs was another place, and so on. You can also optimize data structures to use. In this example, this is from P2. There's a class which is called the audit properties. It basically holds a map of properties, and often this map is either empty or just has one element. And by default, this data structure just uses a hash map, but a hash map is, yeah, huge. For the case that you don't have any element, we now initialize this map lazily, so it's zero. When you do not have any properties, and if you have just a single value, then a single map is now used from the collections framework. And only if you add a second property to this object, then it will use a hash map. So in many, many, many cases, you can, yeah, use less memory for these maps. It showed up here that the retained size of the object of that kind used six megabytes in this example of memory, and 6.2, and after optimization 4.6. So again, 1.5 megabytes of memory saved. Then there was something in JET found. We have here something which is called the class path access rule. There were two million objects of that held, and they used 200 megabytes of heap space. The class path access rule is an information which is available for each package, for each project in each jar that you have in the workspace. I have a huge workspace, and so this showed up in that amount. But when looking into that, one can see that actually you don't need so many instances, because many instances are equal. So what we did now is analyze that, and you see it's already really wasting many times. 200 duplicates that are wasting 100 kilobytes of memory than the next duplication, 199, and so on. Many, many, many. This multiplies really much. With introducing a weak cache, we could reduce the same thing to 3,000 instances from 2 million and using 300 kilobytes instead of 200 megabytes of memory. So we saved 200 megabytes by using this cache, but it erased a buck in Eclipse. Strangely, due to the introduction of this cache, Eclipse started to raise a full build on startup, totally somehow unrelated, but you could not know that this was causing that buck. And unfortunately, we actually delivered this with Eclipse Photon, but fortunately, it was discovered then and with the new release cycle of Eclipse, now every three months, we could provide a fix in Eclipse 2018-09. So now we have both the working birds and also less memory consumption. So what I want to show you here is, this is my development workspace for Eclipse platform. It's building around one gigabyte of heap. So we have to make this into a relation. This old gen space is around 600 megabytes and we use Eden space between 100 and 400 megabytes for that building, that workspace. So it's totally sufficient with one gigabyte of heap. These are 40 Git repositories. All projects from these Git repositories. Let's count them. Let's count how many projects are in this workspace. And 1,600 projects are in this workspace. Let's count Java files and round about 60,000 Java files that are in this workspace. And the IDE is happy with one gigabyte of heap. That's almost nothing. Compare that to your slack client. But we still have problems. The slow scrolling on macOS is one of the longest running performance problems and we still not have a solution really for that. Actually, some of these things that I showed you are the illegal argument exceptions that are thrown. And so these came from examination of that problem. On macOS it's so that the scrolling of files doesn't feel nice. We're still searching for that. That's one of the most common bugs on Eclipse. I think we are roughly at a common number, 360 or so. And many attempts to change that. But we are still struggling with that. We also identified maybe hotspots in SWT where we can maybe improve something. There's a class called text-worth. It tries to compute the width of tabs. And often it's the same. Maybe it's a candidate for caching but we still do not know if it's valid to cache it here. And we hope to improve that in the future. So if you make a text search with very fast results, then you can experience blocking of threads. So this is the red bars show that threads are waiting on each other. And you see sometimes they do. It's actually not really a deadlock but close to it. Actually we're working on UI freezes. So you know this typical spinning wheel of death. And this always happens when heavy computations are done in the UI thread. And what we try to do is to put the computations in the background, in background threads, and come back to the UI thread only to do the display thing. And what you see here is a screenshot of an application called the error reporting system. Maybe if you use Eclipse, you saw the pop-up. Here something happened. Do you want to report this? So for UI freezes, we get reports to that. And the Eclipse developers can now see, okay, where did we have UI freezes? And then we can focus on that places. But still ongoing. The problem that we have is at Eclipse, we are strongly API compatible. So API never changes. And this makes it sometimes hard to really provide fixes. And we can't really make use of all the fancy stuff that Java provides us for concurrency. Because the API was not designed that way. And we can just say, okay, we changed the API. Because there are plenty of tools outside that really depend on the stability of the API. For this native thing, the scrolling issue, we are lacking deep knowledge about Kakoa. We are good Java programmers, but there's not much knowledge about the internals of the Mac implementation. So yeah, that's one of the problems. Last thing that I want to show is something that I'm currently working on. The use case is again the software update. So if you issue that search for updates, then you see, okay, it contacts all the update locations that you configured. And yeah, it finds that, okay, you have a location which is actually a composite of locations. And then it finds again it's a composite. And this is all happening sequentially. And you easily end up with hundreds of update locations that you process sequentially. And the idea is now, why can't this be paralyzed? And in a prototype, this is now the new prototype. On the left side, I see the debug perspective and I will now issue the software update. And now I see that many threads are doing things. What I'm actually doing right now is just to say, okay, when I have a composite, which contains certain amounts of children, then issue a job in the background for each of the children. And then synchronize again when the work is done. And this must just be now polished a little bit. We need a preference for that in Eclipse UI so that you can say how many threads are allowed to query the network at once. Because there are limitations depending on infrastructure. Some companies don't allow to process 20 network connections at once or so. And so we need to throttle this. And with some luck, we get this into the next Eclipse IDE. But if not, then for sure with the version after that. We are already now in milestone two release. And it's not much time until milestone three is issued. And then we can't change anything for next release. And then it has to go in the release after. Yep, I have to stop. So thank you. You saw many things can help. And every change that we do there in the Eclipse platform helps millions of users every day. I think I don't have free time for questions now. The next speaker can already show up. But if you have questions, I can answer them outside.