Blog

Seite: 1
vor: 2


Simon Simon
25.07.2016 20:39

PHP Performanceoptimierung von lenex-php


Im Rahmen des Projekts "Lxf2Html" für woum.at erfolgte eine Performanceoptimierung der Bibliothek lenex-php.

Der lxf2html Konverter konvertiert lxf Dateien in html. Die lxf Dateien sind elektronische Ergebnisdateien im europäischen Schwimmsport. Mit dem Konverter ist es möglich, die gesamten Ergebnisse eines Schwimmwettkampfes nach Clubs und Schwimmer bzw Schwimmerin durchzuklicken. Zwischenzeiten und Einzelzeiten der Schwimmer bei Staffeln werden ebenfalls berechnet und dargestellt. Die jeweils erreichten Punkte können für verschiedene Punktesysteme ausgegeben werden : FINA Punkte, Rudolph Punkte, Italienische Masters Punkte und DSV Masters Punkte. Die Ergebnisse können in unterschiedlichen Sprachen (Deutsch, Englisch, Italienisch, Französisch, ..) dargestellt werden. Weitere Details zum Lenex Konverter.

Eine Performanceanalyse mittels XDebug und Darstellung mittels webgrind ergab folgende Ergebnisse:

Das Einlesen und Parsen einer unkomprimierten Lenex-Ergebnisdatei mit 900kb mit der Originalversion der Bibliothek dauerte ca. 7,3 Sekunden (die Ausführungszeiten sind aufgrund des XDebug-Profilers erhöht). Mittels der Performanceanalyse konnte der Flaschenhals schnell ausfindig gemacht werden: Für den Zugriff auf die Properties der Model-Klassen wurde die PropertyAccess Komponente des Symfonfy Frameworks verwendet. Da bei den entsprechenden get und set Methoden keine Typenüberprüfungen oder sonstige Überprüfungen erfolgten, sind diese nicht unbedingt notwendig. Das Umschreiben des Zugriffs auf die Properties der Model-Klassen erbrachte folgendes Ergebnis: das Einlesen und Parsen einer unkomprimierten Lenex-Ergebnisdatei mit 900kb ohne Symfony PropertyAcces  benötigte nur noch zwischen 1,14 und 1,36 Sekunden. Dazu musste die Sichtbarkeit der Objekteigenschaften von protected auf public geändert werden.

Ein Performancetest ergab, dass der "dynamische" Zugriff auf Objekteigenschaften praktisch gleich schnell ist, wie der direkte Zugriff:

Count: Testing of setting 3 times 300000 = 900000 property values
Setting properties using direct accessing took 2.2677540779114s
Setting properties using dynamic accessing took 2.2825977802277s
Setting properties using array simulation took 9.5236191749573s
Setting properties using mapper took 5.1776850223541s
 

Der Performancetest verwendet verschiedene Mapping-Implementierungen (die etwas unkonventionell sind):

  • direct accessing: Jede Eigenschaft wird direkt zugewiesen
  • dynamic accessing: der Eigenschaftsname, in den geschrieben wird, steht in einer Variablen
  • array simulation: das Objekt enthält keine wirklichen Eigenschaften, sondern lediglich eine Eigenschaft. Diese ist vom Typ Array und enthält alle Eigenschaften. Der Zugriff wird mittels der magischen Methode "__get" auf den Array umgeleitet
  • mapper: die Eigenschaften stehen in einem Array und werden an eine Mapping Methode der Klasse übergeben, die die Eigenschaftten mittels der direkten Zuweisen überträgt.

Die Parsing-Funktionen wurden komplett neu mittels Reflection geschrieben, da die dynamische Zuweisung kaum Performanceinbußen bring, aber viel Code einspart. Danach benötigte die Datei nurmehr 0,41 Sekunden für den Einlese- und Parsevorgang. Denn ein weiterer Flaschenhals der Implementierung ist der rekursive Aufruf von Funktionen. Ohnehin benötigt ein Funktionsaufruf in PHP relativ viel Zeit.

Original-Webgrind-Screenshot, Neuentwicklung-Webgrind-Screenshot

Die Struktur der Originalimplenetierung definierte zum Parsen eines Objekts einen Array, der die Mappings enthielt. Zudem werden Objekteigenschaften, die in einem Kind-XML-Element definiert werden in einer dynamischen Funktion (Closure) eingelesen. Einerseits werden diese Mapping-Arrays nicht gecached und andererseits verursacht das Definieren der Closures in dem Array unnötige Verschachtelungen.


Schlüsselwörter: php performance, symfonfy PropertyAccess, property access, reflection
zuletzt geändert: 27. Juli 2016 17:13
Link zu diesem Artikel: (in die Zwischenablage)





Martin Martin
28.03.2016 13:43

The bad side of UWP


The bad side of UWP

I'm a frontend developer using WPF with .net 3.5 since 2009. So I would say I know a thing or two about WPF but lately got a little bit rusty, because the last year most of the projects I was assigned were web related. Therefore, I was really excited about my first UWP project app. My personal goal and interest regarding this UWP project were to find ways to adopt the WPF best practices. The result and experience is described below. Needless to say, UWP got its upsides, but on this article I will focus on the frustrating stuff.

Silverlight developers might not be as bothered as I am by the limitations that UWP entails, due to the fact that they seem to be somewhat used to the restriced XAML subset. I on the other hand am accustomed to being able to make use of the full WPF XAML possibilities.

Styles, x:Type, x:Static

Let’s start and compare WPF and UWP projects. I like the MVVM pattern and when I'm able to put UI logic into XAML code, I do so.

For example, when our task is to display additional controls on a checked checkbox we can handle all of this UI logic in XAML. I did this in WPF XAML with style triggers and in some cases using animations to set values on specific events. In UWP you can't do this anymore. Style triggers are gone.

Luckly, there is a workaround and a complete implemented solution using the "Behavior SDK (XAML)". See the code below. 

Regardless, the Behavior Attached Propertie works only on controls and cannot be used in styles. The next thing I realize was that x:Type and x:Static are also not available in UWP.

I used x:Static in WPF for many cases, but let’s focus on styles. We could have done something like that with WPF styles in our Resource:

With the above code, we "inherit" the base TextBox style and set the Background Property to green. In UWP we can't "inherit" the base TextBox style, because of the two missing Keywords. The only workaround I know for this issue feels a little bit nasty.

We could copy the default control styles from \(Program Files)\Windows Kits\10\DesignTime\CommonConfiguration\Neutral\UAP\10.0.10586.0\Generic and copy it to our ResourceDictionary and assign a Key to every style. So we could use the BasedOn Property.

x:Static is used in WPF to "access" static members from XAML and is, as I mentioned before, gone in UWP.

Localization

The way how localization is done in UWP also changed. At the moment I'm not quite sure if the result is satisfying.  Anyway, in UWP you got resw files. A localization in UWP can looks like the following:

Lets assume the resw file contains the following key(s):

Abort.Content Abort
Abort.ToolTip Aborts the current operation

The last part of the key contains a dot followed by the Name of the property which the value should be assigned to. This means for the above example that the Button's property Content is "Abort" and the ToolTip contains "Aborts the current operations". This gives us the ability to use x:Uid on a control once, but it can localize multiple Depdency Properties. On the other hand, I have to create a new Key "Abort.Text" when I want to use the Value "Abort" for the TextBlock DP Text.

TypeConverters

So far the localization in UWP seems to be better supported than in WPF. But let’s take another look at the restricted XAML capabilities. TypeConverters are a very important. You can use them for types such as: arrays, strings, brushes and double and so forth in XAML code. The existing TypeConverters support only a little subset of those Types. So I thought, no problem, I’ll create my own TypeConverter for the unsupported ones, but no, you can’t even extend or add additional TypeConverters.

I’ll give you an example of how deeply these missing TypeConverters affect existing best practices. There are two proper ways to handle user privileges in a WPF application. One of them is implemented with converters.

Let’s see the simplified example below:

In this example, the ConverterParameter contains a Sorted Dictionary in XAML, which defines the required claim for the current WindowsIdentity to show the MenuItem. The ClaimConverter evaluates if the current Principal contains the necessary claims defined by the ConverterParameter and returns the proper Visibility. Because I can't use the SortedList in XAML the whole concept is useless.

Some workarounds can be found here http://stackoverflow.com/questions/12495937/winrt-replacement-for-system-componentmodel-typeconverter

Custom Controls

The limited TypeConverter ability also concerns the custom control development. Which brings me to the next point: creating custom controls. Routed Events like the ones in WPF are, you guessed it, also gone! As a workaround I created a DP which uses a DelegateCommand which in return can be manually raised. Sure, it's no replacement for the routed events. They’ve got the cool routing strategies like bubbling and tunneling features. Also, we only got a stripped down version of the DependencyProperties compared to WPF ( http://WPF.2000things.com/tag/dependency-properties/)

Validation

When you develop WPF applications the possibility that you get in touch with validation is quite high. The WPF validation is mostly done using Adorners in combination with IDataErrorInfo or BindingValidationError. The Adorners give you the ability to set the state of a control visually. Because in UWP this element doesn't exist anymore, I looked again for an UWP workaround.

Using Prism I quickly found the solution in a pattern and practice example: https://msdn.microsoft.com/en-us/library/windows/apps/xx130660.aspx?f=255&MSPPError=-2147217396. What are they doing? Simplified, the solution is using attached properties where you set the default and a validation style. When the value gets invalid it uses the validation style which you set on the attached property. Most of the time you only want to add a red border to the invalid control and print the error message. When using this approach you have to create additional styles that define the appearance of the control when it is invalid.

Another way to solve this validation issue is to create a usercontrol that "hosts" the control which needs to be validated. The usercontrol shows the red border with the validation message when needed. I think something like that is done here http://blog.jerrynixon.com/2014/07/lets-code-handling-validation-in-your.html. Maybe a combination of the pattern and practice with jerry nixons approach can work as a fine solution.

Last but not least

There are quite more features which I'm missing in UWP like multibindings, no IMultivalueConverter, using the ancestor type in bindings and so on, but the above ones are the most important in my opinion.

What concerns me most in UWP is that the flexibility is gone.

One of coolest things when taking the full advantage of WPF was to create nearly any kind of control really fast.  The missing features definitely dampen my view of UWP as a whole.

There is a discussion https://github.com/dotnet/corefx/issues/5766on github related to the XAML topic. Maybe when the System.XAML Namespace will be opened we can add the missing features by ourselves.

Some of the aforementioned issues are already being discussed on the uservoice platform:

 

What do you think about UWP? Are you currently developing in UWP and are you ok with how it turned out? Did you find workarounds for the XAML limitations by yourself? I would be glad to hear from your UWP experience.


Schlüsselwörter: UWP, XAML, WPF, c#
zuletzt geändert: 02. April 2016 09:18
Link zu diesem Artikel: (in die Zwischenablage)





Martin Martin
27.01.2016 20:57

Code-Snippet: LINQ - outsource where condition


Sometimes you need to look for specific objects in several linq queries. Therefore its very important to query the objects in the exactl same way in every query.

In this case, it makes sense to store the WHERE LINQ statments in a predicate variable. Then you can reuse it in all linq queries.

This sample code is simplefied and for demonstration:

Predicate<DateTime> dateTimePredicate = b => b.Hour == 1;
 
        List<DateTime> dateTimeList = new List<DateTime>()
        {
            DateTime.Now,
            DateTime.UtcNow,
        };
 
dateTimeList.Where(a=>dateTimePredicate.Invoke(a));

Schlüsselwörter: LINQ, Where, Predicate
zuletzt geändert: 27. Jänner 2016 21:18
Link zu diesem Artikel: (in die Zwischenablage)





Martin Martin
23.08.2015 10:16

Add Token Authorization to AngularJS and WebApi


Protection and authorization for a Single Web Application and a RESTFul Service

Introduction

There exists some ways to implement an authentication into RESTFul Service. For this article I will focus on the HTTP Token Header technique, because its really easy to implement with the JsonWebTokenHandler.(RESTful Authentication, 22.08.2015, http://stackoverflow.com/questions/319530/restful-authentication?lq=1  ).

To keep it short we focus on the practical aspect. The demonstration contains a Single Web Application with AngularJS which is hosted on an ASP.NET MVC page. The RESTFul Service will be represented by an ASP.NET WebApi project. I want to mention that most of the code was built from code snippets which I researched from other blogs or stackoverflow to reduce time. So the example project consists of several code snippets and some custom coding.

As you know the RESTFul Service is stateless. We need to achieve that the WebApi can correctly identify our current requests to a user. There the token, or precisely the Json Web Token, comes into play. Because the returned data is formatted as JSON the term Json Web Token is more common in that subject.

When sending a valid login request to the WebApi, it will issue a token for the logged in user. The SWA will catch the returned token from the login. From now the SWA will add the token to each call into the HTTP Header. The WebApi will check if there exists a JWT and extract the containing user information. This process is visualized in the graphic below.

After associating a user to the request we can permit or deny the request.

{"iss":"Identity Provider","name":"John Doe","admin":true}

The Json Web Token is a JSON-based open standard which contains the user payload a signature and the following important header information’s (JSON Web Token, https://en.wikipedia.org/wiki/JSON_Web_Token, 22.08.2015).

·         Issuer (iss) : The Service which created the jwt

·         Subject (sub) : The subject regarding the token

·          Audience (aud) : Which application can use the token

·         Expiration time (exp): When expires the token

·         Not before (nbf): Don’t use the token before

·         Issued at (iat): When was the token created

·         JWT ID (jti) : The ID of the token

(“JSON Web Token (JWT)”, https://self-issued.info/docs/draft-ietf-oauth-json-web-token.html, 22.08.2015 )

Frontend - AngularJS

Our AngularJS web application has got an Authentication service which can initiate the login process. It sends the logon and the password to the webapi and saves the returned token. The token will be set to the default Authorization HTTP Header of the httpService (“Setting angularjs $http headers globally“, http://stackoverflow.com/questions/27134840/setting-angularjs-http-headers-globally, 22.08.2015).

In order to prevent the user from navigating to any other page of our application, we add a callback to the angular module. When navigating between pages the callback checks if the user is logged in our Authentication service.

This is done by registering the “$locationChangeStart” event which will be fired on any page navigation. If the user is not logged in we force a redirect to the login page. A logout can be done by refreshing the whole page, the state of the SWA will then be lost.

After a successful login we forward the user from the login- to the home view. The corresponding homeController makes an authenticated webapi request which will then return the current users privileges.

Backend - WebApi

Let’s switch to the WebApi’s PostUser action method. It is used to login a user and issue a security json web token.

First of all we check if the delivered user credentials are correct. Normally this is done by querying the database or another resource. The user and the roles are implemented with the claims-based identity of the Windows Identify Foundation. So if you never heard of claims you should definitely check Andras Nemes blog series about that topic (“Introduction to Claims based security in .NET4.5 with C# Part 4: authorisation with claims”, http://dotnetcodr.com/2013/02/21/introduction-to-claims-based-security-in-net4-5-with-c-part-4-authorisation-with-claims/, 22.08.2015 ).

For creating JSON Web Tokens Microsoft published the JwtSecurityTokenHandler class which can be found in the NuGet Package System.IdentityModel.Tokens.Jwt.

We create the ClaimsIdentity for the user which we wish to log in by adding his claims. After that we can create the token with tokenHandler.CreateToken(issuer: "http://localhost", audience: "http://localhost", subject: claimsIdentity, expires: expires, signingCredentials: new X509SigningCredentials(cert));

So as you see the issuer and audience value are equal because we create the token and at the same time consume it. With the expire parameter we can determine how long the token is valid and with the signing credentials we sign our token against manipulation. The returned encoded token is a base64 string.

The Json Web Token will be signed when issuing it with a private key. When a token will be “read”, it will be validated against the public key.

In this project I deposit the private and the public key as files, which is not recommended regarding security issues. In a real world example it would be stored in the certificate manager and for a convenient project start up I skipped that part. By the way, I used the following self-signed certificate tool http://blog.pluralsight.com/selfcert-create-a-self-signed-certificate-interactively-gui-or-programmatically-in-net.

We should not only be able to create tokens, but also to read and “extract” the information from it. This can be done with a DelegatingHandler which intercepts every web request of the WebApi.

Vittorio Bertocci wrote an excellent article http://www.cloudidentity.com/blog/2013/01/09/using-the-jwt-handler-for-implementing-poor-man-s-delegation-actas/on that topic a while ago. The JwtSecurityTokenHandler has changed since the article was released.

What does the TokenValidationHandler do in particular?

First of all it intercept the web request before the concerning action method gets executed. It checks if the request contains a HTTP Header with the key Authorization. If not, the request will be forwarded to the action method. If you wish to protect the action method you can add a claimsauthorization attribute (details about that later).

If there exists a JWT token it will be validated against the TokenValidationParameters and the public key. With ValidateToken the user information from the token will be extracted and set the current user of the HttpContext and Thread. If the validation didn’t fail the request will be forwarded to the action method. Otherwise we abort the current request and return an unauthorized status code.

If for specific action methods certain claims are necessary we can use the ClaimsAuthorization attribute. Before the action method gets executed, it checks if the current HttpContext.User got the required claims.

Remarks

The solution is configured in a way that you can easily execute the project. Make sure you installed Visual Studio 2013 with the Web Development Tools and the latest updates. Also The Web Essential Tools should be installed with the latest TypeScript Version. You can Download the project from Github.

Press F5 to start the Web Project and navigate to http://localhost:5118/Default/Index/to start the SWA. Then switch to Visual Studio and right click on the WebApi Project and select Debug àStart new Instance. Create some breakpoints and try to login with the user martin in the web application and step through the program to see what’s happening.

Because the web projects are hosted under different domains (http://localhost:5118vs http://localhost:5117) we run into the CORS issue. To solve that I installed the CORS NuGet Package from Microsoft and enabled it with the EnableCors attribute. You may also want to check http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api.

I hope I could show you that it is really is easy to implement an authentication mechanism in AngularJS and ASP.NET WebApi. If you have any questions or suggestion feel free to comment or write me on twitter.

Other used Links:

http://stackoverflow.com/questions/18032038/securing-the-jwt-with-a-x509certificate2-jwtsecuritytokenhandler create jwt token

http://stackoverflow.com/questions/20198124/read-private-key-from-pfx-file read certificate from file

http://stackoverflow.com/questions/52797/how-do-i-get-the-path-of-the-assembly-the-code-is-in get current assemply path


Schlüsselwörter: RESTFul, WebApi, .NET, C#, Typescript, AngularJS
zuletzt geändert: 24. August 2015 22:14
Link zu diesem Artikel: (in die Zwischenablage)





Martin Martin
10.05.2015 21:27

DLL Hell - Could not load file or assembly System.Web.http 4.0.0.0


Bei einem Erstdeployment kann es zu unliebsamen Überraschungen kommen bei denen nicht sofort die Ursache erkennbar ist. 

Besonders tragisch ist es, wenn die Fehlermeldung am Testsystem nicht am Entwicklungssystem reproduzierbar ist. Nach dem Installieren und Aufrufen der Applikation wird vom IIS die Fehlermeldung "Could not load file or assembly System.Web.http 4.0.0.0" ausgegeben. 

Die StackOverFlow Antworten brachten keine Lösung, weshalb das Problem genauer anlysiert werden musste.

Das Testsystem war eine Windows Server 2003 Installation und siehe da, im GAC war tatsächlich die Datei nicht vorhanden. Der Global Assembly Cache ist dazu da, um Versionskonflikte zu vermeiden. Ein weiteres Feature vom GAC ist, das die Assemblies dort nativ vorliegen. Während der Installation vom .NET Framework werden die Assemblies prozessoroptimiert kompiliert und sind dann in nativem Code verfügbar. Das heißt die Bibliotheken können um einiges schneller gestartet werden, als die "üblichen" welche in der Common Intermediate Language vorliegen und mit dem JIT ausgewertet werden. 

Wie auch immer, nach Recherechen hat sich dann herausgestellt, dass genau diese File und noch ein paar Andere auf Server Installationen nicht ausgeliefert werden (Security Issues).

Also habe ich die Option Copy to Local im Visual Studio auf true gesetzt. Auch das zeigte keinen Effekt. Somit löschte ich die Referenz und kompilierte nochmal das Projekt auf dem Entwicklungssystem. Trotz der Änderung kam am Testsystem nach wie vor die Fehlermeldung. Also die Änderung wieder Rückgäng machen und die Referenz System.Web.http zum Projekt hinzufügen.

Nach dem die Projekt-Referenzen genauer unter die Lupe genommen wurden, fiel eine Third Party Referenz auf, die eine Abhänigkeit auf System.Web.http hatte. Außerdem waren die referenzierten Versionen auf System.Web.http der Lib und der Web Application unterschiedlich. Es wurden deshalb alle Referenzen von System.Web.Http zunächst einmal auf die Version upgedated welche die Third Party Lib verwendete. In der web.config ist auch der Eintrag

  <dependentAssembly>
    <assemblyIdentity name="System.Web.Http" publicKeyToken="31bf3856ad364e35" culture="neutral" />
    <bindingRedirect oldVersion="0.0.0.0-5.3.0.0" newVersion="5.3.0.0" />
 </dependentAssembly> 
 

interessant. Den dieser ist dafür verantwortlich, dass wenn keine geeignete Assembly Version gefunden wird, ein Fallback auf den GAC passiert. Genau das ist auf der Testmaschine passiert. Die Assembly System.Web.http war im bin Folder der Web Application vorhanden, aber aufgrund des web.config Eintrag wurde stattdessen auf den GAC zurückgegriffen. Da auf der Windows Server Installation die File nicht existierte, kam die Fehlermeldung. Auf dem Entwicklungsystem waren beide Assembly Versionen vorhanden, weshalb der Fehler so nicht reproduzierbar war.

Nachdem bei allen Projekten die Referenzen auf die korrekte Assembly Version verwiesen haben kam immer noch die Fehlermeldung System.Web.Http 4.0.0.0 wurde nicht gefunden, obwohl die neue Assembly Version 5.3.0.0 lauten sollte. Nach weiterem suchen, hat sich herausgestellt, dass die Projektdateien im Visual Studio zwei Referenzen auf die gleiche Assembly hatten mit jeweils der unterschiedlichen Assembly Version. In diesem Fall hat die Visual Studio GUI die falsche Information angezeigt. Das Visual Studio Projekt musste also ungeloaded werden und in der xml Ansicht nachbearbeitet um die alten Assembly Verweise zu löschen. Der Fehler könnte von einem auto. TFS merge stammen.

In diesem Fall haben mehrere ungünstige Faktoren zusammengespielt.


Schlüsselwörter: c#, .NET, IIS, deployen
zuletzt geändert: 17. Mai 2015 10:08
Link zu diesem Artikel: (in die Zwischenablage)





Seite: 1
vor: 2