 Okay. Maybe. Works? Good. Welcome to what the self unexpected things happening under the grid. So this is basically about about some things I encountered during developing a spreadsheet card. Yeah, just short overview about me, about accessibility as a friend, as a default. And some code doesn't know where to put things and with some performance examples. I'm Agiradge, known on the net at SE Rec, for example, an IRC, simple things. And most email addresses, working on StarOffice, OpenOffice.org, LibreOffice, for several companies, and since a long time I'm around here. So accessibility, or A11Y, as it shortened, can be your friend. Or most of the time it's your friend because it provides information to the screen readers, tells which object is active, is selected, whatever, and reads the text content of selected objects. So for example, from edit fields, list book entries, cells, the contents, and it also listens to object changes, which is good. Or maybe is it, or maybe not, because this accessibility can also be your fault. Especially if you're a coder. Because it listens to object changes, which can slow things quite significantly down. Because a modern system's accessibility, at least the framework, is enabled even if you don't have any screen reader in use. And it can get in the way at the most inconvenient occasions. And well, if it does, it's sometimes very hard to debug. So for example, we have an edit engine. We have a cell with a text, one line with text in this case, and we start to edit the text and type some text there. And so there's one line, funny stuff. It doesn't show the highlighted things. Okay, the piece of text with an inserted paragraph with a paragraph mark at the end, we just type in. So as soon as you reach the paragraph end and press enter, accessibility is notified, hey, we have a new paragraph here. So it can actually read the new content and tell the screen reader the next piece of text is moved to the next line. And that with text is now on the next line. So when doing something similar, when pasting text into a cell, starting with the same cell contents, and pasting piece of text and pasting paragraph and more, which we previously copied from another cell, including this paragraph break. So the same as the paragraph end is inserted, accessibility gets notified. Well, we are in the middle of a pace. Accessibility gets notified and wakes up and thinks, well, let's ask the edit engine for the new distribution of the text. But the text is not read from it yet, so the edit engine doesn't know how it is distributed actually. But it knows there is text following because we just paste it at some position, some piece of text, and it was not at the end of the cell. So the edit engine then, due to the internal algorithm, just tries to redistribute the text, but somehow cannot decide when to do it actually. So it actually allocates memory for the next line to put a piece of text there, but doesn't quite move the text there. So it is in some stage where it can't decide between its x-carousel positions that it remembers and the text that follows. Well, it adds this line but doesn't distribute the text. Instead, it goes to step zero, and when the text is not read from it yet, and asks itself again, let's read from this thing. I don't know where it starts. There is some text following, I know that. So I just append a line. So this goes on infinitely until either your memory is off, you crash if you're lucky, and you're using Windows system, or you have a limited Linux environment, or you go on until your swap space is finished and your system grinded to halt even before that. You can't do anything anymore, which made debugging this not very funny because you have to interrupt it early before that happens, and then try to figure out why this happens, and actually debugging the case took me about one and a half days or something. The actual fix was very simple. We suppressed only during the paste the notifications, so accessibility is not notified during the paste, but just right after the paste happened. So in that state, again, the edit engine is in a good state again, and it can operate just as usual. But that was just along the two lines fixed actually, so just suppress notification, and after the paste turn it on again, and just notify accessibility after. The other part was rewriting the part of the algorithm of the edit engine so that if for any other occasion it comes to this, it does not end up in the same situation, so allocating memory endlessly for this situation hopefully is not possible anymore. If you're interested in what was changed, the commit idea is given. Coming to performance, I was a bit involved the last half year with the performance of Calc because due to some bugs encountered and also some other things. So one example here is the loading self-formulas from an ODI file format, where we have to parse all the formulas, and significant time was spent in the determination whether a specific piece of string is a value, which comes after whether it's a function name or a reference or whatever, and at one point if it's not one of these, we have to determine if it's a value or not. That always called the number parser, which is usually done also in the user interface because the user can type in other things, and we have to, for example, process the localized separators like decimal separators or date formats, whatever. But in an ODI file format, it has to be a good English U.S. string like specified in the format, so we don't need all this overhead. And we could use the RGLMF string to double, which we have implemented in the base layers. That's brought down actually the numbers from instruction red to from, what was it here, 9 million, 899,000 something, which was spent under the SC Compiler S value and the other two calls, brought down to 298,000, which is a speedup of factor 32, 33. So quite some gain there, which this was a test case actually of just thousand numbers and formulas alternating on every second row, so we don't end up with any shared formula or something, so we have to actually parse everything. The next one was in the scenario I think it was inserting rows something, quite complex document, where it identified that a dynamic cast of a notification, formula, cell notification, where the cell actually was already notified before, so it actually did not have to do anything, but to determine that it doesn't have to do anything, it had to dynamically cast the hint that was passed in, because the simple hint we use is just a simple hint without any data and any other hint we use has some data on it is derived from that simple hint, so it always had to dynamically cast the hint before it could determine whether it has to do anything or not, and with this one commit I mentioned here, I eliminated all these SFX simple hints throughout the entire suite and moved all to SFX hint instead, which was previously derived from the SFX simple hint and made 150 dynamic cast superfluous. In the scenario where we inserted these rows into the document, I think 20% of time was spent in this notification call doing nothing because of the dynamic cast, because it was millions of calls because of all the cells involved. Then third step I did was at the part that tracks the formulas, which means if something changed in a document like a data or some other formula producing results on which other formulas depend, that these track formulas was called too often when modifying a document, for example inserting rows, columns, whatever, due to individual steps of the modification of the documents broadcasted changes to the formulas and on each change the formulas would track which depend on which and just to get notified. This was done multiple times, so instead of doing that, we just kept track of collecting and depending formulas and processed the actual track only once at the end. In this case, the instructions read was sped up by factor six and the wall clock speed up by factor two. Again, this is in complex documents, there's nothing you will see in smaller documents or something, but in large documents. A very short example, only a little innocent piece of code is called an atria hasattrip and this hasattrip is called for various scenarios just to find out if a block of rows within one column has a specific attribute for example and during the profiling it turned out that of what is this, 36 million times this was called only 9200 times row one and row two actually differed, so normally this piece of code is called for one cell, not for a block, we can just spare one search. So we had two searches before for each row one, row two and now we do the second only for the case that the two rows actually differs in the query which can save quite some time if you have lots of attribute in one column. I've known numbers for that, what I've actually said at the time there. Yeah, I speed it a little bit up here and I'm already at the end. Any questions? Yes. Where did you get the last number from? The last number, the big number was from profiling. It just occurred to me that when I browsed these profile results that we called this function that many times and then you get this annotation which line of the code is called how many times and so on and I spotted that the search function was actually called for every time but actually the other pieces that belong to the same code weren't, so one of them was superfluous. Thank you.