CSS > SCSS > CSS

Neue Webseiten werden heutzutage oft via SASS erstellt, aber was macht man mit alten Projekten? Kann man auch hier SASS einsetzten? – Ja! Das schöne an “SCSS”-Dateien ist das diese 100% mit CSS kompatibel sind, so dass man die entsprechende Dateiendung umbenennen kann und neue / kleine Anpassungen in der SASS-Syntax schreiben kann. Wer jedoch eine ganze CSS-Datei auf den SCSS-Style anpassen möchte kann z.B. den “sass-convert”-Befehl auf der Kommandozeile verwenden.


See the Pen tqJvn by Lars Moelleken (@voku) on CodePen.
1

CSS > SCSS

Mit dem folgendem Befehl kann man die CSS-Datei in eine SCSS-Datei umwandeln lassen.

sass-convert --from css --to scss test.css test.scss


See the Pen Arxuv by Lars Moelleken (@voku) on CodePen.
1

Es folgt eine kleine manuelle Optimierung, dabei gilt: Umso besser die ursprüngliche CSS-Datei aufgebaut war, desto besser kann diese konvertiert werden.


See the Pen eFdlJ by Lars Moelleken (@voku) on CodePen.
1

SCSS > CSS

Nun erstellen wir aus der neuen SCSS-Datei wieder eine CSS-Datei + Sourcemap

scss  --sourcemap --line-comments --style expanded test.scss test_new.css


See the Pen pErjB by Lars Moelleken (@voku) on CodePen.
1

PS: mithilfe der Source Map kann Chrome automatisch die entsprechenden Code-Stellen in der entsprechenden SCSS-Datei  anzeigen :)

 

Links:
http://sassmeister.com/
http://css-tricks.com/sass-style-guide/

Quellen:
http://sass-lang.com/documentation/file.SASS_REFERENCE.html#output_style

Einführung: PHP-Variablen und der Garbage Collector

In diesem Blog-Post möchte ich erklären, was technisch hinter einer Variable in PHP steckt und wann PHP den Speicher dieser Variablen wieder freigibt.

Der PHP Quellcode?

Im Alltag schaut man doch ehr selten (nie) in den eigentlichen Quellcode von PHP. Dies sollten wir an dieser Stelle nachholen. -> https://github.com/php/php-src/tree/PHP-5.5

Info: Auf der folgenden Seite kann man den PHP Quelltext einfach nach bestimmten z.B.: Funktionen durchsuchen: http://lxr.php.net

Ich habe mich hier für den Quelltext von PHP 5.5 entschieden, da diese Version auf meinen lokalen PC läuft und ich die folgenden Tests mit dieser Version durchführen werde.

PHP Quellcode – Struktur: Hier gibt es zwei Hautbestandteile von PHP, mit welchen wir uns weiter beschädigen werden. Aufgeteilt sind diese in den folgende zwei Verzeichnissen.

– Zend: (www.php.net/manual/en/langref.php) Die Zend Engine, stellt die Laufzeitumgebung für PHP zur Verfügung. In diesem Verzeichnis werden somit alle “language level”-Funktionen von PHP bereitgestellt wie z.B. Variablen, Syntax-Analyse, Code-Ausführung und Fehlerbehandlung.

– ext: (www.php.net/manual/en/funcref.php) Extensions, stellt alle einzel Funktionen von PHP bereit. (z.B. strpos, substr, PDO, SplFixedArray etc.)

Intern stellt PHP jeder Variable als sogenannte “ZVALs” da. Dies ist unter anderen nötig, da der PHP-Kern in C geschrieben ist, C jedoch keine dynamische Typisierung wie in PHP zulässt. Somit bedient man sich einer Art Wrapper, welcher verschiedene Werte beinhalten kann.

struct _zval_struct {
  /* Variable information */
  zvalue_value value;             /* value */
  zend_uint refcount__gc;
  zend_uchar type;                /* active type */
  zend_uchar is_ref__gc;
};

Was steck in einer zval-Struktur?

value: http://lxr.php.net/xref/PHP_5_5/Zend/zend.h#321

typedef union _zvalue_value {
    long lval;                   /* long value */
    double dval;                /* double value */
    struct {
        char *val;
        int len;
    } str;
    HashTable *ht;              /* hash table value */
    zend_object_value obj;
} zvalue_value;

Wir sehen, dass der “value” in einer PHP-Variable (zval) mehrere Variablentpyen (Zustände) beinhaltet. Daher kann eine PHP-Variable sowohl einen int-Wert, als auch ein Array beinhalten.

z.B.:
$foo = (int) 3;
$foo = array(3);

C

PHP

long

int, boolean, resource

double

float

str

string

hashtable

array

zend_object_value

object

type: http://lxr.php.net/xref/PHP_5_5/Zend/zend.h#578

/* data types */
/* All data types <= IS_BOOL have their constructor/destructors skipped */
#define IS_NULL     0
#define IS_LONG     1
#define IS_DOUBLE   2
#define IS_BOOL     3
#define IS_ARRAY    4
#define IS_OBJECT   5
#define IS_STRING   6
#define IS_RESOURCE 7
#define IS_CONSTANT 8
#define IS_CONSTANT_ARRAY   9
#define IS_CALLABLE 10

/* Ugly hack to support constants as static array indices */
#define IS_CONSTANT_TYPE_MASK       0x00f
#define IS_CONSTANT_UNQUALIFIED     0x010
#define IS_CONSTANT_INDEX           0x080
#define IS_LEXICAL_VAR              0x020
#define IS_LEXICAL_REF              0x040
#define IS_CONSTANT_IN_NAMESPACE    0x100

Da wir sovor gesehen haben, dass das “value”-Feld verschiedene Typen von Variablen beinhalten kann, wird hier festgelegt um welchen Type es sich hier handelt. z.B.: zval.type = IS_LONG

is_ref: 0 || 1 http://www.phpinsider.com/download/PHP5RefsExplained.pdf
Dieses Feld wird auf “1” gesetzt falls es sich bei der Variable um eine Referenz (z.B.: &$foo) handelt.

refcount: http://www.php.net/manual/en/features.gc.refcounting-basics.php
Dieses Feld ist ein Zähler für die Anzahl von PHP-Variablen, welche zu dem internen zval referenzieren, so kann der PHP Garbage Collector entscheiden, wann die entsprechende Variable nicht mehr benötigt wird.

z.B.:
$a= new A;    // 1 Referenz
$b = $a;         // 2 Referenzen
unset( $a );   // 1 Referenz
unset( $b);    // 0 Referenzen

Größe von “zval”?

Auf folgender Webseite wurden bereits mit PHP 5.3 getestet, wie viel Speicher für 100000 Integer-Werten in einem Array benötigt werden. -> http://nikic.github.io/2011/12/12/How-big-are-PHP-arrays-really-Hint-BIG.html

                             |  64 bit   | 32 bit

zval                         |  24 bytes | 16 bytes
+ cyclic GC info             |   8 bytes |  4 bytes
+ allocation header          |  16 bytes |  8 bytes
===================================================
zval (value) total           |  48 bytes | 28 bytes
===================================================
bucket                       |  72 bytes | 36 bytes
+ allocation header          |  16 bytes |  8 bytes
+ pointer                    |   8 bytes |  4 bytes
===================================================
bucket (array element) total |  96 bytes | 48 bytes
===================================================
total total                  | 144 bytes | 76 bytes

144 bytes * 100000 = 13.73 MB

Test mit PHP 5.5 (32-Bit)

$int = 0;
Speichergröße: 176 bytes

(refcount=1, is_ref=0),int 0

$null = null;
Speichergröße: 184 bytes

(refcount=1, is_ref=0),null

Da es für “null” keinen Eintrag im zvalue_value gibt, wird dieser Wert seperat gespeichert und benötigt somit inital mehr Speicher als 0.

$string = ”;
Speichergröße: 200 bytes

(refcount=1, is_ref=0),string '' (length=0)

$string = ‘1234567’;
Speichergröße: 200 bytes

(refcount=1, is_ref=0),string '1234567' (length=7)

$string = ‘12345678’;
Speichergröße: 208 bytes

(refcount=1, is_ref=0),string '1234567' (length=8)

$string = ‘0123456789’;
Speichergröße: 208 bytes

(refcount=1, is_ref=0),string '1234567' (length=10)

Wir sehen, dass PHP jeweills 1 byte (8 bit) benötigt, um ein Zeichen für einen String zu Speichern und diese zu jeweills 8 bytes zusammenfasst. So bleiden im letzten Beispiel 192 (208 – 16) bytes übrig, welche PHP benötigt um die entsprechende Variable anzulegen.

$array = range(1, 100000);
Speichergröße: 8524576 bytes => 8.12966919 megabytes

(refcount=1, is_ref=0), array (size=100000)
  0 => (refcount=1, is_ref=0),int 1
  1 => (refcount=1, is_ref=0),int 2
  2 => (refcount=1, is_ref=0),int 3
  3 => (refcount=1, is_ref=0),int 4
  [...]

 

PHPs Garbage Collector

Quellcode für den Test: test4.php

start:                                88 bytes 
array:                     8524592 bytes 
function1-begin:     8524608 bytes 
function1-end:      17049016 bytes 
array-test4:             8524536 bytes 
function2-begin:      8524552 bytes 
function2-end:         8524616 bytes 
array-test4_ref:       8524552 bytes 
end:                         8524552 bytes 

Wir sehen, dass PHP bei der ersten Funktion mit Parameterübergabe (ohne Referenz) das entsprechende Array kopiert, da es sich hier um eine neue Variable handelt, welche in der Funktion verarbeite wird und zurückgegeben wird. Zusätzlich können wir hier beobachten wann PHP die Variable kopiert und zwar erst wenn diese Verändert wird (copy-on-write).

 

Zusammenfassung:

Ich glaube es ist Zeit für eine erste Zusammenfassung von dem was wir bisher aus den PHP Quelltext und den ersten kleinen Tests sehen konnten.

1.) PHP behandelt Variablen intern als Struktur von Variablen (zval_struct -> zval).

2.) Diese Struktur beinhaltet nicht nur den aktuellem Wert und den Type, sondern auch die Anzahl wie oft diese Variable verwendet wird und ob es sich dabei um eine Referenz (&) handelt. 

3.) PHPs Garbage Collector kann somit nicht mehr benötigte Variablen selbständig aus dem Speicher löschen.

 

Quellen:
http://www.php.net/manual/en/internals2.variables.intro.php
http://www.php.net/manual/en/features.gc.refcounting-basics.php
http://www.php.net/manual/en/function.debug-zval-dump.php

http://code.stephenmorley.org/php/references-tutorial/
http://www.developerknowhow.com/inside-the-php-engine-integers-and-their-zval/
http://webandphp.com/how-php-manages-variables
http://wiki.selfhtml.org/wiki/Artikel:PHP/
http://www.sitepoint.com/better-understanding-phps-garbage-collection/

grep, ack, find, locate, sed, diff, wc …

An dieser Stelle wollte ich einmal notieren wie ich in der täglichen Arbeit mit z.B. “grep” oder “find” etc. umgehe, um möglichst schnell in Verzeichnissen und Dateien zu suchen oder Text zu ersetzten.

Ich werde hier nicht alle Möglichkeiten der entsprechenden Befehle nennen können, daher beschränke ich mich auf das, was ich wirklich verwende. Falls du dich weiter in der Thematik einlesen möchtest, empfehle ich gerne den “man”-Befehl oder wie andere es ausdrücken RTFM!

Falls dir die Begriffe tail, cat, less nicht viel sagen, dann klick hier!!!

 

grep: 

global regular expression print -> durchsucht Dateien und Verzeichnisse via RegEx bzw. nach Strings

Kurzform Langform Beschreibung
-H
--with-filename
gibt den Dateinamen vor jedem Treffer aus.
-i
--ignore-case
unterscheide nicht zwischen Groß- und Kleinschreibung.
-n
--line-number
gibt die Zeilennummer vor jedem Treffer aus.
-R
-r
--recursive
liest alle Dateien unter jedem Verzeichnis rekursiv.
-v
--invert-match
Invertiert die Suche und liefert alle Zeilen die nicht auf das gesuchte Muster passen.

z.B.:

grep -rHn test ~/php/

-> sucht im Verzeichnis “php”, welches sich wiederum im Home-Verzeichnis [~] befindet nach dem String “test”

PS: hier der selbe Befehl, jedoch eingeschränkt auf php-Dateien

grep -Hn test ~/php/**/*.php

Info: wenn man “git” im Einsatz hat, sollte man “git grep” verwenden ;)

 

ack:

Ack hat die selbe Aufgabe wie “grep” ist jedoch auf Entwickler zugeschnitten, so sucht “ack” im Standardmäßig rekursiv, ignoriert Binärdaten und Verzeichnisse von Versionkontrollsystemen (.svn, .git, etc.)

PS: unter Debian / Ubuntu findet man das entsprechende Paket unter “ack-grep”

 

find:

ist bei der Suche nach Dateien behilflich (“Alles ist eine Datei”)

Suchkriterien für find
Kriterium Beschreibung
-name Datei
Es wird nach Dateien mit dem Namen “Datei” gesucht. Sollen bei der Suche Platzhalter Verwendung finden, so muss der ganze Ausdruck in Anführungszeichen gestellt werden, zum Beispiel

-name "*.txt"
-iname Datei
Es wird nach Dateien mit dem Namen “Datei” – ohne Beachtung der Groß und Kleinschreibung – gesucht.
-type f
Es wird nur nach regulären Dateien gesucht.
-type d
Es wird nur nach Verzeichnissen gesucht.
find -size +10M -20M -exec ls -lah {} \;

-> sucht alle Dateien welche eine Dateigröße zwischen 10 – 20 MB haben und zeigt diese an

WARNING: der “exec”-Parameter kann auch für jeden anderen Befehl auf die Ergebnismenge von “find” ausführen, dabei sollte man jedoch bei dem “rm”-Befehl besonders vorsichtig sein. Und ggf. kann man sich safe-rm anschauen. ;)

PS: hier sind noch ein paar Beispiel

 

locate:

“sudo updatedb” nicht vergessen und schon kann man sehr schnell nach Dateien suchen, da die Dateien nicht im Filesystem, sondern in einer Datenbank (updatedb) gesucht werden.

z.B.:

locate Download | grep home

 

sed:

Es handelt sich hier um einen “nicht-interaktiver Texteditor” was eigentlich nur bedeutet, dass man damit String verarbeite kann. Zum Bespiel kann man ein bestimmtes Wort in einer Datei durch ein anderes ersetzten.

https://github.com/voku/dotfiles/blob/master/.functions

# WARNING -> replace: changes multiple files at once
replace()
{
  if [ $3 ]; then
    find $1 -type f -exec sed -i 's/$2/$3/g' {} \;
  else
    echo "Missing argument"
  fi
}
replace *.php alt neu

-> dieser Befehl such im aktuellen (+ Unterverzeichnisse) nach Dateien, welche auf “.php” enden und ersetzt darin “alt” gegen “neu”

PS: hier findet man ein paar nützliche Beispiele

Dabei ist besonders praktisch, dass man diese Funktionalität auch im “vim” verwenden kann indem man z.B. folgendes eingibt …

 :%s/alt/neu/g

 

diff:

Wie der Name schon vermuten lässt, kann man hiermit Dateien vergleichen. z.B.:

diff -u --ignore-all-space -r old/ new/

-> vergleicht alle Dateien rekursiv (-r) vom Verzeichnis “old/” und “new/” und ignoriert dabei Änderungen vom Leerräumen z.B. Leerzeichen oder Zeilenumbrüche (\r <-> \r\n)

Info: wenn man “git” im Einsatz hat, sollte man “git diff” verwenden ;)

 

wc:

word count kann Wörtern, Zeichen und Bytes (man ahnt es bereits) zählen. z.B.:

cat /proc/cpuinfo | grep processor | wc -l

-> zählt die Anzahl der CPU-Kerne

 

Quellen:
http://beyondgrep.com/ – ack
http://wiki.ubuntuusers.de/grep
http://wiki.ubuntuusers.de/find
http://wiki.ubuntuusers.de/locate
http://wiki.ubuntuusers.de/wc
http://suckup.de/linux/find-linux/
http://suckup.de/linux/streameditor-sed/

Kurztipp: RegEx für die Paketsuche

Habe soeben einen älteren Blog-Post aktualisiert und einen kleinen Tipp hinzugefügt, welchen ich hier an zwei Beispielen zeigen möchte: suckup.de/linux/ubuntu/aptitude-dpkg/

sudo aptitude search "^php5-[a-cA-C]+"

-> sucht alle Pakete welche mit “php5-” anfangen und darauf “a”, “b oder “c” in beliebiger Häufigkeit folgen

sudo aptitude search "(^bash|^git).*completion"

-> sucht Pakete welche entweder mit “bash” oder mit “git” anfangen gefolgt von beliebigen (auch beliebige Anzahl) von Zeichen, gefolgt von dem String “completion”

Die RegEx-Funktionalität funktioniert sowohl bei “apt-cache”, “apt-get” als auch bei “aptitude” und auch bei anderen Befehlen wie z.B.: “remove”, “install”, “search”, “purge” etc. Bei meinen Tests hat dies jedoch mit “aptitude” am besten funktioniert, da hier nur nach den Paketnamen gesucht wird, falls man jedoch nicht genau weiß wonach man eigentlich sucht, dann sollte man es wohl mit “apt-cache” versuchen.

PS: wer sich RegEx noch nicht angeschaut hat, der sollte auch mal die Links in den Quellen anklicken, da man dies z.B. in so gut wie jeder Programmiersprache, in der Shell oder ansatzweise selbst bei der Google-Suche nutzen kann. Wer mehr über Tricks in der Google-Suche erfahren möchte, klickt hier! ;)

Quellen:
https://www.debian.org/doc/manuals/debian-reference/ch02.de.html#_browsing_with_the_regex_matching
http://regex101.com/
http://de.wikipedia.org/wiki/Regul%C3%A4rer_Ausdruck