📜 ⬆️ ⬇️

From the black rectangle in Yandex. Browser to the acceleration of the whole Chromium

Today we will tell you a story about an interesting bug in Yandex. Browser, the correction of which led to a significant acceleration of rendering throughout the Chromium project. And Kirill drBasic Pleshivtsev and Vadim Lof Petrov, specialists from our team, who are fortunate enough to deal with the problem, will help me in this. Give them the word.



One not absolutely normal bug
')
My name is Kirill, I work in the group of internal components of Yandex. Browser in Novosibirsk. On one not-so-beautiful day, colleagues from testing Yandex Browser reproduced the problem with playing the video through Flash Player. And since it is our group that is responsible for this part of the browser (media, codecs, that's all), the task went to me. Bug, let's say, did not claim to originality. Clicking the Play button led to a black rectangle instead of correctly playing the video. I have met this symptom before, so I expected to locate the problem fairly quickly. But I was wrong.

Literally in the very first minutes, we managed to find out that a black rectangle does not always appear, but only for flash-elements with the type transparent, i.e. translucent. Great, there is already something to catch on when debugging. I collect the debug-version of the browser, I launch it, there is no bug. And this is a wake-up call. Differences in the work of the debug and release versions - it is always a lot of fun. Therefore, I decide to collect more and release version. Collected, I start, there is no bug.

Thought it out. What is the difference between my release build and the one that the server builds? Immediately remembered the library layout. Developers compile browser in shared_library mode. This increases the amount of dll, but it greatly saves layout time. The browser distributed in the static_library mode is distributed, in which only a few large dlls are collected. I expose a flag static_library, I do full assembly. I watch as link.exe slowly eats up all the RAM, but no, 16 GB of RAM is enough for everyone, the layout is completed without doping in the form of a paging file. I'm running. There is no bug.

Seriously thought. I remembered that the assembly server collects the release of Yandex. The browser with the official flag, which slightly changes the behavior (more about this later). I collect with this flag. With a shaking hand, I launch the browser. Have you already guessed? There is no bug.

Then I was really alarmed and began to think with all my might. After a while, I noticed that the server collects Yandex Browser using Visual Studio 2013. And I used the 2015 version. I collect in the 2013 version. I'm running. There is a bug! Who would have thought that I would be so happy about the mistake.

If you now thought that the whole problem was only in the VS version, then you are mistaken. The bug really did not reproduce in the debug version of the browser. Experimentally it was possible to establish that in order for an error with a black rectangle to appear, the browser should be compiled not only with VS 2013, but also in a static layout with the official flag. The reasons for this strange behavior, you will learn later.

The next two days were no less interesting. During debugging, I managed to understand that the Flash Player plugin itself performs its task correctly: the video plays. Its integration with the browser issues also did not cause. The result of his work was transmitted for rendering, but for some reason we saw something completely different on the screen. This means that the bug had to be searched in the part of the browser that is responsible for rendering. And here I give the word to Vadim.

Optimize it

As you already understood, now Vadim is in touch. I work in the development group of the rendering engine Yandex. Browser in Moscow. A few words about how the rendering in Yandex Browser or Chromium occurs in general. Everything that you see in the browser window is the result of combining different layers (web page, interface), almost like in Photoshop. Compositor component (or Chrome's Compositor == CC) is responsible for working with these layers. But to draw each layer of SS already, it calls the special open source Skia library.

Together with Cyril, we realized that traces of the bug go to Skia. It remained to understand exactly where. Fortunately, I had a valuable hint. Almost at the very beginning, Cyril mentioned it. The point is that the problem occurs only in the case of flash-elements with transparency. To draw such elements on the screen, the browser needs to combine the video image with the background. And for this, Skia has a special function SrcATop, which is responsible for blending. A few minutes of searching, and now I have already found a bug report with a similar problem in Chrome, which finally dispelled all doubts.

Hooray. We localized the source of the problem down to a specific function. And now, attention. This piece of code did not contain any errors. Not at all. And it worked perfectly for any builds except the final one, which is sent to users. And only for Visual Studio 2013. And at that moment I understood why Cyril called this bug "merry."

I begin to understand the other differences that affect the reproducibility of the error. The time has come to recall the official flag, which is used only at the very end. Among other things, this flag affects the optimization, or rather the / LTCG parameter. When it is specified, the compiler produces a fairly serious optimization of the entire program. It takes a lot of time, so these assemblies are not just assembled. But how can optimization lead to an error? To understand this, we need a small flashback.



In 2011, the Chromium project became so large and complex that the Visual Studio 2010 linker once failed to link it with all the optimizations due to lack of resources. To get around the problem, the developers decided by default to optimize all the subprojects (and there are more than a thousand) not by the speed of operation (/ O2), but by the size of the code (/ O1). And only for the elite and the most critical, or for those whose owners did not oversleep this situation, turned on / O2 back. For example, this was done for CC and Skia. That's just in 2013 when refactoring in Skia optimization accidentally lost. And no one would have noticed anything if in another two years another refactoring did not occur in Chromium, as a result of which a part of the code was made template and transferred to the header. And here it all began.

And that's what began. When a release browser is assembled with the official flag, libraries with different goals for optimization (in speed, in size) are in the same dll. In itself, this is not a sign of something bad. For example, in Visual Studio 2015 it does not cause any problems. The studio puffs an hour over optimization and gives out quite a working code. But if we replace it with the 2013 version, everything breaks down. Why?

The SrcATop function, which is responsible for the blending in Skia, takes two parameters through the xmm0 and xmm1 registers. And almost always it works correctly. But as I was able to figure out during debugging, it is worth adding VS 2013 and a difficult optimization, and the function degenerates to such an extent that it starts to return the contents of the first register in response. Hence, there was a constant black background instead of video. All the fault was the wrong code generation in VS 2013.

We accelerate web surfing

With a strong desire, the bug could be “fixed” locally, by slightly twisting SrcATop. But it seemed to me wrong that such a component important for rendering as Skia does not have speed optimization. Therefore, I have assembled a new assembly in which I set speed optimization for Skia. The bug, of course, was gone. It would seem that you can close the task and go to drink tea, but no. I needed to do something else.

The Yandex. Browser team has been involved in the development of Chromium for more than a year. And this concerns not only the correction of errors. At one time, colleagues helped with server push implementation for HTTP / 2 and with the project build system for Windows. Therefore, this time I offered a solution to the problem and sent a ready commit for consideration, which was adopted after a brief discussion.

The developers from Chromium, as well as me, were interested in looking at the changes in terms of browser performance. Therefore, they drove a whole set of performance tests. Almost all indicators for Windows have grown up. Some low-level tests showed improvements by a factor of 2-3. The integrated FPS test for key sites (in other words, everyday web surfing) grew by 6.5%. Responsiveness to input improved by 20-30%. In the Chromium project, it is not every day that optimization of this level happens.



Considering that VS 2010 has not been used for a long time, I suggested trying to turn on speed optimization for the entire project. Moreover, the usual release build (without the official flag) has always been optimized for speed, and there have never been any problems with testing. But that's another story.

PS This single issue has affected only two offices. In fact, the development of Yandex. Browser is conducted not only in Moscow and Novosibirsk. We also have teams in St. Petersburg, Yekaterinburg, Nizhny Novgorod, Minsk and Kiev. And if you would be interested to join them, then look at yandex.ru/jobs .

Source: https://habr.com/ru/post/277555/


All Articles