Finally i decided to change my lovely job in Playtika where i worked for 4 years in a position of System Architect.
These were great years. We wrote 4 big games that earn ~1 billion of revenue per year.
We wrote our game engine in C#/.NET, made it work on iOS, Android, Windows 10, MacOS, Linux, XBox One. Wrote and editor for levels for our engine. We fully automated mobile release pipeline, and update could be released to stores just in 1 click, automated UI testing, created great tools for QA to work with builds (logs, replays, CI/CD).
During my 10 years as a developer and and architect, i saw many managerial decisions that led us to hell. Even worse, those decisions were never properly explained to teams.
On my next position i want to try build development team, to help them automate their process, to setup proper cross-team communication, to clearly translate business goals into dev tasks, to have p2p meetings with guys and solve their problems.
Engineering is interesting, but people are fascinating. So i decided to try find my new job in a role of Head of Engineering or similar. Role name depends on company size.
I’m ready to relocate abroad. Preferably to a country where 30+% of population speak English. I worked in UK for 1 year, and it was a great experience. I’d love to try it once again, hopefully with possibility to stay 🙂
Here I attach my CV: Grigory_Perepechko_CV
In the last project i participate in, we have all logic in PCL libraries (78 profile). 1.5 years ago there was only one PCL logger – MetroLog. It was partially from log4net/NLog and contained too much async/await logic (mostly IO related), which is too expensive for mobile devices, especially if app performs very detailed logging as our app does.
So we outlined few goals for a perfect logging library:
1. Very small in terms of lines of code.
2. Minimal footprint on IOS IPA size
3. Very fast with minimal possible amount of memory allocations
4. No dependencies except for .NET
5. Support of WP8, Xamarin, UWP
6. Support categories
My colleague Oleg Ilyin wrote an implementation that satisfied those goals, which i optimized a little bit and uploaded to github.
1. We have a library that has ~200 lines of code according to Visual Studio metrics.
2. .NET dll size is ~20kb, IOS binary footprint is <50kb for ARMv7+ARM64.
3. Logging one message to file produces 2 memory allocations, which is much less that NLog/MetroLog do
Code is on github – https://github.com/Belorus/XLog/wiki
I made few measurements with cool DotNetBenchmark library written by Andrey Akinshin:
1. I’m awaiting async method that throws deep in callstack and after catching i get StackTrace
2. I’m awaiting async method that throws deep in callstack
3. [COMPARISON ONLY] I’m awaiting async method that returns deep in callstack (without exception)
4. I’m calling normal method that throws deep in callstack
5. I’m calling normal method that throws deep in callstack and after catching i get StackTrace
Code is here (don’t forget to add DotNetBenchmark library, i used 0.78 from nuget)
For stack depth = 100 results are following
For stack depth = 10 results are following
For stack depth = 1 results are following
CAUTION: Logarithmic scale!
From measurements we can see:
1. Getting stacktrace can slowdown your exception handling code significantly for deep stacks.
2. awaiting methods is very slow itself and exceptions don’t influence on its performance (if not to get stacktrace)
During my eternal fighting with .NET performance i decided to check what performance impact does finalizer give.
The easiest way is to write isolated test.
In short, finalizer is symmetrical to ctor optional special method that is called when object is ready to be Garbage Collected on a special finalizer thread. It should be used to free unmanaged resource, and it is better not to touch any managed resources from it, because they can be already GCed.
In my test i create 10,000,000 instances of MyClass and either
1. Store them all in list so they all get to gen2
2. or just forget about them to let GC collect then during gen0 collection
My second research dimension covers finalizability.
a. MyClass has empty Dispose
b. MyClass has empty finalizer and have GC.SuppressFinalize in Dispose
c. MyClass has empty finalizer without GC.SupressFinalize being called
______a b c
1. 1400ms 2950ms 4300ms
2. 85ms 1000ms 2850ms
The code is here
I ran it on AMD FX-6200 4.4Ghz without CPU affinity.
This shows that
1. allocating/collecting shortliving objects without finalizer is very cheap.
2. forgetting to call SupressFinalize can significantly reduce your performance (finalizer doesn’t allow collecting shortliving objects immediately (in gen0) but adds them to finalization queue and moves to gen1 where they are collected after finalizer is called)
Hi there 🙂
Today is the Independence day in Belarus (hooray :)) and i have spare time to look at app performance a bit.
I’ve been lookin thru the code and found out that many of method that accept collection work with IEnumerable<T> for better flexibility. Sounds like good following of rule “Relax preconditions, strenghten postconditions”. But quite often i have a materialized collection with data(not yield-based generator) like List<T> or and array.
I found a place where i initially get string but then pass it as IEnumerable<string> and call string.Join over it.
Basically there are 5 overloads of string.Join (the second is actually generic string.Join<T>)
And i used the first one. Huh, quite interesting what is the difference between the one that works with array and the one that works with IE<string>.
First of all quite simple microbench:
(If u’re interested in those red lines under Console.WriteLine method – have a look at awesome performance fighting plugin for R# HeapView)
Simply changing .ToArray() to .ToList() changes the overload. Results are following:
Array – 73ms 81GC gen 0 collections
List – 115ms 202GC gen 0 collections
IEnumerable based implementation of string.Join simply creates StringBuilder and appends strings one by one.
Array based impl runs over provided array and calculates the total length of final string with separator, creates string with preallocated char buffer of appropriate length (using both internal and external FastAllocateString(int length) method) and then does unsafe(in terms of C#) memcpy to that preallocated buffer of every string from the array.
As for me, i’d use make my code a bit less nice in terms of preconditions and use arrays a bit more often. One more cool thing about using concrete collection types (T/List<T> instead of IEnumerable<T>/IList<T>) – they have struct enumerator, and iterating over them is faster (non-interface call) and do no heap allocations (passing struct as interface (IEnumerator) automatically boxes it, which is pretty expensive).
Have a nice day!
Tired of wiring app bar buttons thru codebehind handlers ?
Try Fluent Application Bar – https://fluentappbar.codeplex.com/
I think everyone would agree that showing a cute placeholder during long image loading is a good idea.
There are couple of solutions in the internet. My favourite is this – http://compiledexperience.com/blog/posts/image-placeholder-control-with-arbitrary-content . Unfortunately i encountered couple of issues with it when used it in virtualized lists. Image was never loaded, or even the placeholder disappeared.
The easiest way to reproduce is to scroll really fast and to navigate away from the page and then return back. When we navigate away – the page gets unloaded and imageOpened event doesn’t fire – this breaks control logic.
I modified code slightly so it can be used in virtualized lists.
Some day i was staying in metro and testing the app i’ve been working on. Something went wrong. Issue was that images were not loaded as device was connected to the internet via GPRS.
App should load smaller images.Luckily server supports multi-res image output.
I defined 4 important for us states
There are 3 ways of getting conenction speed on device. And only 1 of them works properly.
1. HttpWebRequest and WebRequestExtensions.GetCurrentNetworkInterface (not reliable)
2. DeviceNetworkInformation.ResolveHostNameAsync (breaks tombstoning)
3. Socket and SocketExtensions.GetCurrentNetworkInterface
The third option works like a charm.
Here you can see how socket to Googles Public DNS server is opened and NetworkInterfaceInfo is extracted. Speed assumptions are based on NetworkInterfaceInfo.Bandwidth
Basing on ConnectionSpeed and on DeviceSpeed
we decide what image to load via nice matrix
All the code is in the Zip file on the dropbox.
Important: Don’t forget to invoke ConnectionSpeedManager.CheckConnection() in Apps OnLaunch and OnActivate methods
Probably every WP7 developer had to deal with this nasty issue.
Steps to reproduce:
During navigation deactivate app via central hardware button (Win). Important: Reproduces only on Device
After activating app back InvalidOperationException with message “Navigation is not allowed when the task is not in the foreground” is thrown and navigation is not processed correctly.
After restoring app from dorment/tombstone it retries navigating if navigation has failed (yeah, quite simple solution).
It is used like that:
NavigationFixService.cs – https://www.dropbox.com/s/oq0mdjg371y7vvj/NavigationFixService.cs?m
Have a look at the code. Try to guess
1. What color will be used to render text “Hello world” initially ?
2. Will it change after button click ?
Initially it will be yellow (yeah, it was easy). But after button click in WPF text color will change, but in SL for Windows Phone it won’t.
Explanation (actually not)
Basically i don’t understand this difference. I feel that this is a bug in Silverlight.
When we set foreground of a
1. ContentControl – the value gets inherited by TextBlockButton (TextBlockButton Foreground value is a new brush now), but notification is not sent to TextBlockButton template children (TextBlock) and TextBlock still uses old brush.
2. TextBlockButton – the notification is sent to its template children and text color changes.
Remove TemplateBinding for Foreground on TextBlock in ControlTemplate