Switched to english.
I'm more and more into frontend developing in the last years.
Recently I needed the best way to clone an object. Here my result:
http://jsben.ch/#/t917Z
Montag, 17. Oktober 2016
Mittwoch, 16. Dezember 2015
Elemente finden, die einen horizontalen Scrollbalken verursachen
Developer Tools => Console öffnen.
Folgendes Skript pasten:
var docWidth = document.documentElement.offsetWidth;
[].forEach.call(
document.querySelectorAll('*'),
function(el) {
if (el.offsetWidth > docWidth) {
console.log(el);
}
}
);
Jetzt erscheinen die Elemente die untersucht werden müssen.
Dienstag, 19. Mai 2015
Mehrere OnPageStarted und OnPageFinshed Aufrufe bei Android Webview Apps behandeln.
Folgendes Problem bei einer WebView - Hybrid - Android - App: Wenn man eine URL lädt, setzt man meistens einen Loading-Dialog ein, damit der Nutzer weiß, dass er kurz warten muss.
In meinem Fall ist das ein Splash-Screen bestehend aus einem zweiten WebView. Das ist aber irrelevant.
Das Problem ist, dass es oft dazu kommt, dass mehrere "OnPageStarted" und "OnPageFinished" nacheinander oder parallel gestartet werden. Zum Beispiel bei Weiterleitungen, Iframes, Ajax-Calls usw. Zum Beispiel bei einem Facebook-API-Login sieht das dannziemlich doof aus.
Meine Lösung: Im OnPageFinished - Handler habe ich einen 500ms delay eingebaut. Nach den 500ms wird nachgesehen, ob ein "neuerer" "OnPageStart" vorhanden ist, Wenn ja, dann beende den Loading-Screen nicht, sondern warte bis der nächste "OnPageFinshed" kommt.
myWebView.setWebViewClient(new WebViewClient() {
boolean loadingFinished = true;
boolean redirect = false;
long last_page_start;
long now;
// Load the url
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (!loadingFinished) {
redirect = true;
}
loadingFinished = false;
view.loadUrl(url);
return false;
}
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
Log.i("p","pagestart");
loadingFinished = false;
last_page_start = System.nanoTime();
show_splash();
}
// When finish loading page
public void onPageFinished(WebView view, String url) {
Log.i("p","pagefinish");
if(!redirect){
loadingFinished = true;
}
//call remove_splash in 500 miSec
if(loadingFinished && !redirect){
now = System.nanoTime();
new android.os.Handler().postDelayed(
new Runnable() {
public void run() {
remove_splash();
}
},
500);
} else{
redirect = false;
}
}
private void show_splash() {
if(myWebView.getVisibility() == View.VISIBLE) {
myWebView.setVisibility(View.GONE);
myWebView_splash.setVisibility(View.VISIBLE);
}
}
//if a new "page start" was fired dont remove splash screen
private void remove_splash() {
if (last_page_start < now) {
myWebView.setVisibility(View.VISIBLE);
myWebView_splash.setVisibility(View.GONE);
}
}
});
In meinem Fall ist das ein Splash-Screen bestehend aus einem zweiten WebView. Das ist aber irrelevant.
Das Problem ist, dass es oft dazu kommt, dass mehrere "OnPageStarted" und "OnPageFinished" nacheinander oder parallel gestartet werden. Zum Beispiel bei Weiterleitungen, Iframes, Ajax-Calls usw. Zum Beispiel bei einem Facebook-API-Login sieht das dannziemlich doof aus.
Meine Lösung: Im OnPageFinished - Handler habe ich einen 500ms delay eingebaut. Nach den 500ms wird nachgesehen, ob ein "neuerer" "OnPageStart" vorhanden ist, Wenn ja, dann beende den Loading-Screen nicht, sondern warte bis der nächste "OnPageFinshed" kommt.
myWebView.setWebViewClient(new WebViewClient() {
boolean loadingFinished = true;
boolean redirect = false;
long last_page_start;
long now;
// Load the url
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (!loadingFinished) {
redirect = true;
}
loadingFinished = false;
view.loadUrl(url);
return false;
}
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
Log.i("p","pagestart");
loadingFinished = false;
last_page_start = System.nanoTime();
show_splash();
}
// When finish loading page
public void onPageFinished(WebView view, String url) {
Log.i("p","pagefinish");
if(!redirect){
loadingFinished = true;
}
//call remove_splash in 500 miSec
if(loadingFinished && !redirect){
now = System.nanoTime();
new android.os.Handler().postDelayed(
new Runnable() {
public void run() {
remove_splash();
}
},
500);
} else{
redirect = false;
}
}
private void show_splash() {
if(myWebView.getVisibility() == View.VISIBLE) {
myWebView.setVisibility(View.GONE);
myWebView_splash.setVisibility(View.VISIBLE);
}
}
//if a new "page start" was fired dont remove splash screen
private void remove_splash() {
if (last_page_start < now) {
myWebView.setVisibility(View.VISIBLE);
myWebView_splash.setVisibility(View.GONE);
}
}
});
Mittwoch, 5. November 2014
#1690 - BIGINT UNSIGNED value is out of range
#1690 - BIGINT UNSIGNED value is out of range
Kann bei einer MySQL - Abfrage erscheinen, wenn man innerhalb der Abfrage mit UNSIGNED Integer - Spalten rechnet und das Ergebnis ein negativer Wert ist.
Also beispielsweise die Tabellenspalte "time" ist eine unsigned Integer Spalte. Unsigned bedeutet übrigens, dass der Wert nicht negativ werden kann, aber dafür erhöht sich der gültige Wertebereich im postiven Bereich um 100%.
Nehmen wir an die Spalte "time" hat einen UNIX TIMESTAMP wert in der Vergangenheit und wir haben folgende Abfrage:
SELECT * FROM tabelle WHERE time - UNIX_TIMESTAMP() < 5
Hier würde entweder die Fehlermeldung von oben erscheinen oder ein sehr hoher Wert errechnet werden.
Die Lösung:
1. entweder die Spalte "time" zum normalen Integer umwandeln (ALTER TABLE `tabelle` CHANGE `time` `time` INT(10) NOT NULL DEFAULT '0';)
2. Oder MySQL im 'no_unsigned_subtraction' - Modus starten.
Dazu einfach in der my.cnf "sql_mode = 'no_unsigned_subtraction'" eintragen, bzw. "no_unsigned_subtraction" in der entsprechenden Zeile ergänzen.
Kann bei einer MySQL - Abfrage erscheinen, wenn man innerhalb der Abfrage mit UNSIGNED Integer - Spalten rechnet und das Ergebnis ein negativer Wert ist.
Also beispielsweise die Tabellenspalte "time" ist eine unsigned Integer Spalte. Unsigned bedeutet übrigens, dass der Wert nicht negativ werden kann, aber dafür erhöht sich der gültige Wertebereich im postiven Bereich um 100%.
Nehmen wir an die Spalte "time" hat einen UNIX TIMESTAMP wert in der Vergangenheit und wir haben folgende Abfrage:
SELECT * FROM tabelle WHERE time - UNIX_TIMESTAMP() < 5
Hier würde entweder die Fehlermeldung von oben erscheinen oder ein sehr hoher Wert errechnet werden.
Die Lösung:
1. entweder die Spalte "time" zum normalen Integer umwandeln (ALTER TABLE `tabelle` CHANGE `time` `time` INT(10) NOT NULL DEFAULT '0';)
2. Oder MySQL im 'no_unsigned_subtraction' - Modus starten.
Dazu einfach in der my.cnf "sql_mode = 'no_unsigned_subtraction'" eintragen, bzw. "no_unsigned_subtraction" in der entsprechenden Zeile ergänzen.
Mittwoch, 29. Oktober 2014
strict_trans_tables deaktivieren. Möglicher fix.
Ich musste wegen eines Projekts die irgendwann neu eingeführte Direktive "strict_trans_tables" in mysql deaktivieren, da sie dazu führte, dass einige MySQL-Queries nicht ausgeführt wurden.
Normalerweise geht man in die /etc/my.cnf , sucht nach "sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES" und kommentiert diese Zeile aus.
Hat aber nicht gereicht. Nach etwas Recherche suchte ich my.cnf die im /usr Verzeichnis sein sollte. Und tatsächlich, sie existierte. Dort gab es auch nur die Zeile "sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES", welche auskommentiert werden musste.
Normalerweise geht man in die /etc/my.cnf , sucht nach "sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES" und kommentiert diese Zeile aus.
Hat aber nicht gereicht. Nach etwas Recherche suchte ich my.cnf die im /usr Verzeichnis sein sollte. Und tatsächlich, sie existierte. Dort gab es auch nur die Zeile "sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES", welche auskommentiert werden musste.
MySQL Datenbank von einem Server zum anderen kopieren mittels ssh und mysqldump
Um eine Datenbank per SSH zu einem anderen Server zu kopieren kann man folgenden Befehl verwenden:
Ja: nach -u und -p kommt KEIN Leerzeichen. Hier ein Beispiel, wenn
User gleich root
Passwort gleich 123sonnenschein
Datenbank gleich MyDB
Ziel-Host: 192.168.2.1
Es sollte beachtet werden, dass auf dem Zielhost entsprechende Rechte des Users vorhanden sind. Also, dass er auch außerhalb von localhost auf den Server verbinden kann.
Zudem sollte die Datenbank (in diesem Fall MyDB) bereits angelegt worden sein.
Das Beispiel geht davon aus, dass User und Passwort auf beiden Servern gleich ist (was keine gute Idee ist).
mysqldump -uuser -ppassword db1 | mysql -h desthost -uuser -ppassword destdb
Ja: nach -u und -p kommt KEIN Leerzeichen. Hier ein Beispiel, wenn
User gleich root
Passwort gleich 123sonnenschein
Datenbank gleich MyDB
Ziel-Host: 192.168.2.1
mysqldump -uroot -p123sonnenschein MyDB | mysql -h 192.168.2.1 -uroot -p123sonnenschein MyDB
Es sollte beachtet werden, dass auf dem Zielhost entsprechende Rechte des Users vorhanden sind. Also, dass er auch außerhalb von localhost auf den Server verbinden kann.
Zudem sollte die Datenbank (in diesem Fall MyDB) bereits angelegt worden sein.
Das Beispiel geht davon aus, dass User und Passwort auf beiden Servern gleich ist (was keine gute Idee ist).
Dienstag, 7. Oktober 2014
[linux] SSH-Befehl im Hintergrund ausführen bzw. nicht beenden, wenn die Verbindung abbricht.
Manchmal möchte man im Remote - SSH einen Befehl eingeben, dessen Ausführung ziemlich lange dauern kann. zum Beispiel das Packen vieler Dateien oder weiß der Fuchs was.
Diese Aktion wird Standardmäßig abgebrochen, wenn die SSH Verbindung beendet wird. Das kann zum Beispiel durch den 24h - Reconnect des Providers sein oder irgendeinen anderen Grund haben. In jedem Fall ist das dann sehr ärgerlich.
Man kann das Ganze aber auch im Hintergrund ausführen - mit "screen".
Um genau das Problem zu lösen benutzt man folgenden Befehl:
"myscreen" ist dabei einfach eine Bezeichnung für den geöffneten neuen Screen.
Beendet man nun die Verbindung zum Server, werden die Befehle weiterhin ausgeführt.
Diese Aktion wird Standardmäßig abgebrochen, wenn die SSH Verbindung beendet wird. Das kann zum Beispiel durch den 24h - Reconnect des Providers sein oder irgendeinen anderen Grund haben. In jedem Fall ist das dann sehr ärgerlich.
Man kann das Ganze aber auch im Hintergrund ausführen - mit "screen".
Um genau das Problem zu lösen benutzt man folgenden Befehl:
screen -dmSL myscreen
"myscreen" ist dabei einfach eine Bezeichnung für den geöffneten neuen Screen.
Beendet man nun die Verbindung zum Server, werden die Befehle weiterhin ausgeführt.
[linux] rsync Performance verbessern. Mehr CPU Kerne.
Ich stand vor dem Problem viele kleine (3 Millionen) Bilddateien von einem Server zum anderen kopieren zu müssen, da der Bildauslagerungsserver gewechselt werden sollte.
Was ich noch nicht probiert habe, ist tar mit einer Erweiterung zu versehen, die mehrere Threads zum Schreiben verwenden kann.
Das gibts hier: http://www.maier-komor.de/mtwrite.html
Syntax für Nutzung mit mtwrite:
Ich habe mich dann aber erstmal für die Nutzung von rsync entschieden. Vorteile: Ich muss den laufenden Betrieb (Bildupload) nicht stoppen; Abgebrochene Aktionen können wieder aufgenommen werden; Ich habe nur eine Aktion auszuführen, denn die Daten werden direkt via ssh übertragen.
Leider dauert dieser Vorgang wegen der vielen kleinen Dateien auch ziemlich lange. Nach 24 Stunden waren knapp 70GB übertragen.
Nun gibt es noch einige Dinge die ich demnächst ausprobieren möchte. Und damit ich Sie nicht vergesse gibt es diesen Post :)
Zum Beispiel lässt sich der CPU - Kern den rsync verwendet auf den Maximalwert hochtakten.
Das kann man so machen:
Mehr dazu auf http://lwn.net/Articles/400489/
Noch etwas mehr verspreche ich mir jedoch von mehreren parallel laufenden rsync- Prozessen.
Mit Hilfe eines Scripts werden die Dateien auf die Prozesse verteilt.
Das Script gibts dort: https://wiki.ncsa.illinois.edu/display/~wglick/Parallel+Rsync
Falls der Link irgendwann mal down sein sollte, hier zum Kopieren:
Nachteil hierbei: Bei diesem Script werden alle Dateien des Hauptverzeichnisses mit nur einem Prozess übertragen. In den Kommentaren gab es eine alternative Lösung:
Für beide Fälle gilt: Soll per ssh übertragen werden - also von Server zu Server - müssen die rsync Befehle abgeändert werden:
Und noch ein wichtiger Parameter: Soll das Verzeichnis lediglich geupdated werden und nicht alle Dateien überschrieben werden, unbedingt die Option "-u"verwenden.
Quellen:
http://www.maier-komor.de/mtwrite.html
http://lwn.net/Articles/400489/
https://wiki.ncsa.illinois.edu/display/~wglick/Parallel+Rsync
http://wiki.ubuntuusers.de/rsync
Das Packen und Archivieren mit tar und gzip war leider unbefriedigend langsam.
Auch die Alternative mit pigz (gzip mit Mehrkern-Unterstützung) brachte keine großartige Besserung.
Syntax für pigz:
tar -cv –use-compress-program=pigz -f meinarchiv.tar /srv/www/img
Was ich noch nicht probiert habe, ist tar mit einer Erweiterung zu versehen, die mehrere Threads zum Schreiben verwenden kann.
Das gibts hier: http://www.maier-komor.de/mtwrite.html
Syntax für Nutzung mit mtwrite:
mttar xf mytarfile.tar
Ich habe mich dann aber erstmal für die Nutzung von rsync entschieden. Vorteile: Ich muss den laufenden Betrieb (Bildupload) nicht stoppen; Abgebrochene Aktionen können wieder aufgenommen werden; Ich habe nur eine Aktion auszuführen, denn die Daten werden direkt via ssh übertragen.
Leider dauert dieser Vorgang wegen der vielen kleinen Dateien auch ziemlich lange. Nach 24 Stunden waren knapp 70GB übertragen.
Nun gibt es noch einige Dinge die ich demnächst ausprobieren möchte. Und damit ich Sie nicht vergesse gibt es diesen Post :)
Zum Beispiel lässt sich der CPU - Kern den rsync verwendet auf den Maximalwert hochtakten.
Das kann man so machen:
for i in 0 ; doecho performance > /sys/devices/system/cpu/cpu$i/cpufreq/scaling_governordone
Mehr dazu auf http://lwn.net/Articles/400489/
Noch etwas mehr verspreche ich mir jedoch von mehreren parallel laufenden rsync- Prozessen.
Mit Hilfe eines Scripts werden die Dateien auf die Prozesse verteilt.
Das Script gibts dort: https://wiki.ncsa.illinois.edu/display/~wglick/Parallel+Rsync
Falls der Link irgendwann mal down sein sollte, hier zum Kopieren:
/bin/bash# SETUP OPTIONSexport SRCDIR="/folder/path"export DESTDIR="/folder2/path"export THREADS="8"# RSYNC TOP LEVEL FILES AND DIRECTORY STRUCTURErsync -lptgoDzd $SRCDIR/ /$DESTDIR/# FIND ALL FILES AND PASS THEM TO MULTIPLE RSYNC PROCESSEScd $SRCDIR; find . -type f | xargs -n1 -P$THREADS -I% rsync -az % /$DESTDIR/%# IF YOU WANT TO LIMIT THE IO PRIORITY,# PREPEND THE FOLLOWING TO THE rsync & cd/find COMMANDS ABOVE:# ionice -c2
Nachteil hierbei: Bei diesem Script werden alle Dateien des Hauptverzeichnisses mit nur einem Prozess übertragen. In den Kommentaren gab es eine alternative Lösung:
#!/bin/bash# SETUP OPTIONSexport SRCDIR="/Storage/data1"export DESTDIR="/Storage/data2"export THREADS="32"# FIND ALL FILES AND PASS THEM TO MULTIPLE RSYNC PROCESSEScd $SRCDIRif [[ $? -eq 0 ]]; thenfind . -type d | xargs -I% mkdir -p /$DESTDIR/%find . -type f | xargs -n1 -P$THREADS -I% rsync -a % /$DESTDIR/%fi
Für beide Fälle gilt: Soll per ssh übertragen werden - also von Server zu Server - müssen die rsync Befehle abgeändert werden:
rsync -lptgoDzd -e 'ssh -c arcfour' $SRCDIR/ remotehost:/$DESTDIR/cd $SRCDIR; find . -type f | xargs -n1 -P$THREADS -I% rsync -az -e 'ssh -c arcfour' % remotehost:/$DESTDIR/%
Und noch ein wichtiger Parameter: Soll das Verzeichnis lediglich geupdated werden und nicht alle Dateien überschrieben werden, unbedingt die Option "-u"verwenden.
Quellen:
http://www.maier-komor.de/mtwrite.html
http://lwn.net/Articles/400489/
https://wiki.ncsa.illinois.edu/display/~wglick/Parallel+Rsync
http://wiki.ubuntuusers.de/rsync
Montag, 19. Mai 2014
Android. App in den Hintergrund, anstatt zu beenden.
statt
folgenden Code verwenden:
finish();
folgenden Code verwenden:
Intent startMain = new Intent(Intent.ACTION_MAIN);
startMain.addCategory(Intent.CATEGORY_HOME);
startMain.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(startMain);
Samstag, 17. Mai 2014
Android Webview App. Beim Aufrufen der App bei Klick auf Push Notification wird eine neue Activity erstellt. Fix.
Szenario:
Man hat eine App bzw. in meinem Fall eine Webview App. Per Push erhält man eine Nachricht, dass eine neue Nachricht eingegangen ist. Man klickt nun auf die Push-Notification und anstatt die eventuell vorhandene Activity zu öffnen, wird eine neue Activity gestartet. Das wollte ich gern vermeiden.
Nach echt langer Recherche bin ich dann auf diesen Link gestoßen: http://www.helloandroid.com/tutorials/communicating-between-running-activities
Relevanter Inhalt:
In der Main-Activity:
In der Notifiaction Sende Klasse:
Man hat eine App bzw. in meinem Fall eine Webview App. Per Push erhält man eine Nachricht, dass eine neue Nachricht eingegangen ist. Man klickt nun auf die Push-Notification und anstatt die eventuell vorhandene Activity zu öffnen, wird eine neue Activity gestartet. Das wollte ich gern vermeiden.
Nach echt langer Recherche bin ich dann auf diesen Link gestoßen: http://www.helloandroid.com/tutorials/communicating-between-running-activities
Relevanter Inhalt:
In der Main-Activity:
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);//must store the new intent unless getIntent() will return the old one
intent = getIntent();
WebView myWebView = (WebView) findViewById(R.id.webview);
myWebView.loadUrl(url);
}
In der Notifiaction Sende Klasse:
Intent intent = new Intent(this, MainActivity.class);
intent.putExtra("tag", tag);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
Donnerstag, 24. April 2014
Höhe und Breite eines HTML Elements mit CSS proportional halten - bei dynamischer Breite/Höhe..
Quelle: http://www.mademyday.de/css-height-equals-width-with-pure-css.html
Mit diesem CSS Trick, bekommt man ein div Element, welches immer die selbe Höhe hat, wie es breit ist.
HTML:
CSS:
In meinem Fall war es nötig einen runden Kreis hinzubekommen bei dynamischer Breite.
(div wird zum kreis mit border-radius:1000px)
Mit diesem CSS Trick, bekommt man ein div Element, welches immer die selbe Höhe hat, wie es breit ist.
HTML:
<div class="box">
<div class="content">
Aspect ratio of 1:1</div>
</div>
CSS:
.box{
position: relative;
width: 50%;
}
.box:before{
content: "";
display: block;
padding-top: 100%;
}
In meinem Fall war es nötig einen runden Kreis hinzubekommen bei dynamischer Breite.
(div wird zum kreis mit border-radius:1000px)
Mittwoch, 23. April 2014
HTML Select funktioniert nicht unter Android 2.3. Fix.
Link zum Original-Fix: http://wil.to/android-positioning/
Inhalt, falls der Link irgendwann nicht mehr geht:
"On Android 2.3, a fixed element that contains an absolute positioned element, which itself contains an absolute positioned element, will cause select menus on the page to stop responding altogether.
By removing that nested absolute element (represented by the red square above) the select menu will work normally. Alternately, by removing the fixed positioning of the parent element—either by not disabling user-scalable in one’s viewport tag or by removing the fixed positioning.
Edit: It seems this bug pertains not specifically to nested absolute elements, but to empty absolute elements—including whitespace. By adding a non-breaking space to the nested element, the problem is solved."
Also zum leeren Element einfach ein
Inhalt, falls der Link irgendwann nicht mehr geht:
"On Android 2.3, a fixed element that contains an absolute positioned element, which itself contains an absolute positioned element, will cause select menus on the page to stop responding altogether.
By removing that nested absolute element (represented by the red square above) the select menu will work normally. Alternately, by removing the fixed positioning of the parent element—either by not disabling user-scalable in one’s viewport tag or by removing the fixed positioning.
Edit: It seems this bug pertains not specifically to nested absolute elements, but to empty absolute elements—including whitespace. By adding a non-breaking space to the nested element, the problem is solved."
Also zum leeren Element einfach ein
<span style='display:none'> </span>
Mittwoch, 11. April 2012
Javascript dynamisch via Javascript nachladen
Hier http://murksfurtz.blogspot.de/2008/12/mit-ajax-nachgeladene-javascript.html habe ich gezeigt, wie man per Ajax nachgeladenen Javascript-Code ausführbar machen kann.
Eine wahrscheinlich bessere Variante ist es, das Javascript einfach dynamisch in der Hauptdatei via Javascript nachzuladen, denn es sind dann keine Anpassungen an der Syntax des Scripts notwendig und es entfällt auch die Evaluierung, welche je nach Rechenkraft schon etwas Zeit in Anspruch nehmen kann.
Ein Beispiel:
So kann man also Javascript-Funktionen nachladen, die man für neue nachgeladene Ajax-Inhalte benötigt. Zum Beispiel ein Script eines ColorPickers, den man für eine Design-Funkion benötigt.
Eine wahrscheinlich bessere Variante ist es, das Javascript einfach dynamisch in der Hauptdatei via Javascript nachzuladen, denn es sind dann keine Anpassungen an der Syntax des Scripts notwendig und es entfällt auch die Evaluierung, welche je nach Rechenkraft schon etwas Zeit in Anspruch nehmen kann.
Ein Beispiel:
<script type="text/javascript">
function loadScript(scriptname) {
var snode = document.createElement('script');
snode.setAttribute('type','text/javascript');
snode.setAttribute('src',scriptname);
document.getElementsByTagName('head')[0].appendChild(snode);
}
loadScript('../js/benoetigtes_script.js');
</script>
So kann man also Javascript-Funktionen nachladen, die man für neue nachgeladene Ajax-Inhalte benötigt. Zum Beispiel ein Script eines ColorPickers, den man für eine Design-Funkion benötigt.
Montag, 8. August 2011
IE 9, Ajax, Error c00c023f
Bei Ajax-Anwendungen, kann es in unregelmäßigen Abständen zu komischen Fehlermeldungen kommen. Error c00c023f. Ziemlich doof, da dann wichtige Funktionen einfach abgebrochen werden.
Der Grund ist wohl ein Bug im IE9 bei der Behandlung von XMLHttpRequest(). Der IE9 nutzt nämlich erstmalig XMLHttpRequest(), statt seiner ActiveX-Objekte.
Die meisten Ajax Skripte haben - damit es auf allen Browsern läuft - immer beide Möglichkeiten unterstützt und meistens XMLHttpRequest() zu erst abgefragt.
Um den Fehler im IE9 also zu vermeiden reicht es, die if und else Zweige zu vertauschen und erst nach dem ActiveX Objekt zu fragen. Denn der IE9 kann diese natürlich auch noch benutzen.
Wie folgt sieht das dann aus:
if (window.ActiveXObject) { // IE
try {
http_request = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
http_request = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {}
}
}
else if (window.XMLHttpRequest) { // Mozilla, Safari,...
http_request = new XMLHttpRequest();
if (http_request.overrideMimeType) {
http_request.overrideMimeType('text/html; charset=iso-8859-1');
// zu dieser Zeile siehe weiter unten
}
}
Der Grund ist wohl ein Bug im IE9 bei der Behandlung von XMLHttpRequest(). Der IE9 nutzt nämlich erstmalig XMLHttpRequest(), statt seiner ActiveX-Objekte.
Die meisten Ajax Skripte haben - damit es auf allen Browsern läuft - immer beide Möglichkeiten unterstützt und meistens XMLHttpRequest() zu erst abgefragt.
Um den Fehler im IE9 also zu vermeiden reicht es, die if und else Zweige zu vertauschen und erst nach dem ActiveX Objekt zu fragen. Denn der IE9 kann diese natürlich auch noch benutzen.
Wie folgt sieht das dann aus:
if (window.ActiveXObject) { // IE
try {
http_request = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
http_request = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {}
}
}
else if (window.XMLHttpRequest) { // Mozilla, Safari,...
http_request = new XMLHttpRequest();
if (http_request.overrideMimeType) {
http_request.overrideMimeType('text/html; charset=iso-8859-1');
// zu dieser Zeile siehe weiter unten
}
}
Montag, 4. Oktober 2010
Geheimtipp I/O NOOP Scheduler bei Hardware RAID Systemen
Unsere Datenbankserver waren trotz 4 SAS HDDs mit 15K UPM und Hardware RAID 10 immer der Flaschenhals. Beim Server an sich gabs auch nie Probleme mit der CPU Leistung.
Ich möchte in dem Artikel garnicht groß drum rum reden und viel erklären, da mir dazu auch die nötige Sachkenntnis fehlt. Außerdem hab ich keine Benchmarks gemacht. In unserem Fall konnte man die Veränderung direkt an der Projektgeschwindigkeit spüren. Das reichte uns :)
Mein Tipp: Bei Hardware RAID Systemen lohnt es sich mit I/O Schedulern herumzuexperimentieren.
Nachdem wir statt CFQ (OpenSuse 11.0 Standard) NOOP eingesetzt haben, lief alles bedeutend schneller.
Ein Scheduler ist dafür verantwortlich, wie die Festplatte(n) Lese- und Schreibvorgänge koordiniert. CFQ gehört dabei zu einer Variante die versucht die Anfragen möglichst sinnig zu sortieren, damit die Schreib- und Leseköpfe nicht unnötig viel umherspringen, sondern nahgelegene Operationen nacheinander abgearbeitet werden und eine "weit entferntere" Operation danach folgt.
NOOP hingegen lässt diese Optimierung gänzlich sein und arbeitet die Anfragen sequentiell ab. Dadurch wird natürlich Zeit gespart, da das ganze Berechnen und Koordinieren und evntl. Warten weggelassen wird, kann aber dazu führen, dass die Schreib- und Leseköpfe viele große Sprünge machen.
Bei Flash-Drives wird daher grundsätzlich NOOP empfohlen, da es dort keine Lese- und Schreibköpfe gibt und es dem Laufwerk egal ist wo der nächste Datenzugriff stattfindet.
So wie ich das jetzt, nach dem Lesen einiger Artikel, verstanden habe, verhält es sich ähnlich bei Hardware - Raid Systemen. Die Raid Controller nämlich, optimieren selbst schon ihre Operationen und ein weiterer Optimierer der keinen Einblick in diese Optimierungen hat, wäre verschwenderisch und im schlimmsten Fall kontraproduktiv.
Den I/O Scheduler kann man im laufendem Betrieb ändern und so problemlos testen. In einem Forum schrieb jemand, er hätte dabei mal einen Server-Freeze gehabt. Das kann ich von meiner Seite her nicht bestätigen. Es lief immer alles glatt.
So kann man gucken welcher I/O Scheduler derzeit aktiv ist:
In diesem Fall wäre anticipatory aktiv.
Ändern kann man ihn wie folgt:
Man hat nun "noop" aktiviert.
Diese Änderung ist nach einem Neustart verloren. Man kann das auch permanent ändern, aber ich finde das grad nicht. Wird nachgereicht.
Links zum Thema:
http://www.linuxhowtos.org/System/iosched.htm
http://www.linuxtechnicalreview.de/content/download/420/3357/file/I-O-Scheduler-und-RAID-Performance.pdf
Ich möchte in dem Artikel garnicht groß drum rum reden und viel erklären, da mir dazu auch die nötige Sachkenntnis fehlt. Außerdem hab ich keine Benchmarks gemacht. In unserem Fall konnte man die Veränderung direkt an der Projektgeschwindigkeit spüren. Das reichte uns :)
Mein Tipp: Bei Hardware RAID Systemen lohnt es sich mit I/O Schedulern herumzuexperimentieren.
Nachdem wir statt CFQ (OpenSuse 11.0 Standard) NOOP eingesetzt haben, lief alles bedeutend schneller.
Ein Scheduler ist dafür verantwortlich, wie die Festplatte(n) Lese- und Schreibvorgänge koordiniert. CFQ gehört dabei zu einer Variante die versucht die Anfragen möglichst sinnig zu sortieren, damit die Schreib- und Leseköpfe nicht unnötig viel umherspringen, sondern nahgelegene Operationen nacheinander abgearbeitet werden und eine "weit entferntere" Operation danach folgt.
NOOP hingegen lässt diese Optimierung gänzlich sein und arbeitet die Anfragen sequentiell ab. Dadurch wird natürlich Zeit gespart, da das ganze Berechnen und Koordinieren und evntl. Warten weggelassen wird, kann aber dazu führen, dass die Schreib- und Leseköpfe viele große Sprünge machen.
Bei Flash-Drives wird daher grundsätzlich NOOP empfohlen, da es dort keine Lese- und Schreibköpfe gibt und es dem Laufwerk egal ist wo der nächste Datenzugriff stattfindet.
So wie ich das jetzt, nach dem Lesen einiger Artikel, verstanden habe, verhält es sich ähnlich bei Hardware - Raid Systemen. Die Raid Controller nämlich, optimieren selbst schon ihre Operationen und ein weiterer Optimierer der keinen Einblick in diese Optimierungen hat, wäre verschwenderisch und im schlimmsten Fall kontraproduktiv.
Den I/O Scheduler kann man im laufendem Betrieb ändern und so problemlos testen. In einem Forum schrieb jemand, er hätte dabei mal einen Server-Freeze gehabt. Das kann ich von meiner Seite her nicht bestätigen. Es lief immer alles glatt.
So kann man gucken welcher I/O Scheduler derzeit aktiv ist:
cat /sys/block/sda/queue/scheduler
noop [anticipatory] deadline cfq
In diesem Fall wäre anticipatory aktiv.
Ändern kann man ihn wie folgt:
echo noop > /sys/block/sda/queue/scheduler
Man hat nun "noop" aktiviert.
Diese Änderung ist nach einem Neustart verloren. Man kann das auch permanent ändern, aber ich finde das grad nicht. Wird nachgereicht.
Links zum Thema:
http://www.linuxhowtos.org/System/iosched.htm
http://www.linuxtechnicalreview.de/content/download/420/3357/file/I-O-Scheduler-und-RAID-Performance.pdf
Donnerstag, 14. Januar 2010
MySQL vs. Memcached vs. Memcached + XCache ... Benchmark
Aus aktuellen Anlass hat mich Folgendes interessiert:
Auf einem Userprofil sollen 50 Freunde ausgegeben werden. Jeder User der online ist, soll dabei farblich anders dargestellt werden als die, die offline sind.
Die MySQL Query dazu sieht in etwa so aus: SELECT a.user_id, a.hat_freund, b.username, c.user_id AS online FROM friends AS a JOIN userdaten AS b ON a.hat_freund = b.user_id LEFT JOIN last_action AS c ON a.hat_freund = c.user_id AND c.last_action > UNIX_TIMESTAMP() - 1200 WHERE a.user_id = 111 ORDER BY a.seit DESC ...als "online" gelten also User, die in den letzten 20 Minuten eine Aktion durchgeführt haben.
So eine Query kommt zur Zeit zum Einsatz. Wir sind aber bemüht dem Datenbankserver so viel Last wie möglich zu entziehen und Cachingmethoden einzusetzen.
Verglichen wurde nun:
1. Der Istzustand, die reine MySql-Abfrage und die anschliessende Ausgabe der Daten.
2. Die reine MySql-Abfrage, mit anschliessender Serialisierung und Speicherung als Array in Memcached, sowie die Ausgabe der Daten aus der Datenbank. (Bzw. die soeben serialisierten Daten)
3. Das reine Auslesen des Resultsets aus Memcached und die Ausgabe.
4. Das reine Auslesen des Resultsets aus Memcached und die Ausgabe, mit dem Unterschied, dass in der Ausgabeschleife für jeden einzelnen User per XCache der aktuelle Onlinestatus abgefragt wird.
5. Das reine Auslesen des Resultsets aus Memcached und die Ausgabe, mit dem Unterschied, dass in der Ausgabeschleife für jeden einzelnen User per Memcached der aktuelle Onlinestatus abgefragt wird.
(Memcached läuft lokal. Datenbankserver im gleichen Rack.)
Die Ergebnisse:
1. normal aus datenbank ( 0.0036)
2. aus datenbank, werte in array speichern, in den cache packen und dann ausgeben ( 0.0043)
3. daten aus memcached auslesen und ausgeben ( 0.0010)
4. daten aus memcached auslesen und ausgeben. in der schleife jeden onlinestatus via xcache prüfen ( 0.0012)
5. daten aus memcached auslesen und ausgeben. in der schleife jeden onlinestatus via memcached prüfen ( 0.0046)
Auswertung:
Methode 3 ist hier eindeutig die Schnellste. Mit dieser Variante liesse sich allerdings nicht Anzeigen, wer von den ausgegebenen Usern gerade online ist bzw. wären diese Daten schnell veraltet, so dass der Cache höchstens ein paar Minuten Gültigkeit haben sollte.
Methode 4 sieht da schon vielversprechender aus. Speichert man die Useraktivitäten jeweils auch in einer XCache Variablen, so dauert es bei diesen 50 Durchgängen lediglich 0,0002 Sekunden um alle zu überprüfen. Dadurch kann der Teil, der mit Memcached gecached wird solange gültig sein, bis der User einen neuen Freund hinzugefügt oder gelöscht hat.
Methode 5 ist die Langsamste von allen. Auf diese Methode müsste man zurückgreifen, wenn man mehr als einen Webserver verwendet und XCache als Cachingsystem unbrauchbar wird*. Wenn man aber bedenkt, dass die Hauptaufgabe nicht ist, bedeutend schneller zu sein als MySQL, sondern nur, den Datenbankserver zu entlasten, so ist die Geschwindigkeit immernoch mehr als ausreichend.
Fazit:
Solange man noch nicht darüber nachdenkt, mehr als einen Webserver zu verwenden, sollte Methode 4 verwendet werden, bzw. Methode 3, wenn die Onlinezustände der User nicht angezeigt werden sollen.
Methode 4 geht bei 50 Durchläufen noch in Ordnung. Man sollte es mit den Schleifen jedoch nicht übertreiben. Die benötigte Zeit steigt entsprechend der Anzahl der Durchläufe!
Auf einem Userprofil sollen 50 Freunde ausgegeben werden. Jeder User der online ist, soll dabei farblich anders dargestellt werden als die, die offline sind.
Die MySQL Query dazu sieht in etwa so aus: SELECT a.user_id, a.hat_freund, b.username, c.user_id AS online FROM friends AS a JOIN userdaten AS b ON a.hat_freund = b.user_id LEFT JOIN last_action AS c ON a.hat_freund = c.user_id AND c.last_action > UNIX_TIMESTAMP() - 1200 WHERE a.user_id = 111 ORDER BY a.seit DESC ...als "online" gelten also User, die in den letzten 20 Minuten eine Aktion durchgeführt haben.
So eine Query kommt zur Zeit zum Einsatz. Wir sind aber bemüht dem Datenbankserver so viel Last wie möglich zu entziehen und Cachingmethoden einzusetzen.
Verglichen wurde nun:
1. Der Istzustand, die reine MySql-Abfrage und die anschliessende Ausgabe der Daten.
2. Die reine MySql-Abfrage, mit anschliessender Serialisierung und Speicherung als Array in Memcached, sowie die Ausgabe der Daten aus der Datenbank. (Bzw. die soeben serialisierten Daten)
3. Das reine Auslesen des Resultsets aus Memcached und die Ausgabe.
4. Das reine Auslesen des Resultsets aus Memcached und die Ausgabe, mit dem Unterschied, dass in der Ausgabeschleife für jeden einzelnen User per XCache der aktuelle Onlinestatus abgefragt wird.
5. Das reine Auslesen des Resultsets aus Memcached und die Ausgabe, mit dem Unterschied, dass in der Ausgabeschleife für jeden einzelnen User per Memcached der aktuelle Onlinestatus abgefragt wird.
(Memcached läuft lokal. Datenbankserver im gleichen Rack.)
Die Ergebnisse:
1. normal aus datenbank ( 0.0036)
2. aus datenbank, werte in array speichern, in den cache packen und dann ausgeben ( 0.0043)
3. daten aus memcached auslesen und ausgeben ( 0.0010)
4. daten aus memcached auslesen und ausgeben. in der schleife jeden onlinestatus via xcache prüfen ( 0.0012)
5. daten aus memcached auslesen und ausgeben. in der schleife jeden onlinestatus via memcached prüfen ( 0.0046)
Auswertung:
Methode 3 ist hier eindeutig die Schnellste. Mit dieser Variante liesse sich allerdings nicht Anzeigen, wer von den ausgegebenen Usern gerade online ist bzw. wären diese Daten schnell veraltet, so dass der Cache höchstens ein paar Minuten Gültigkeit haben sollte.
Methode 4 sieht da schon vielversprechender aus. Speichert man die Useraktivitäten jeweils auch in einer XCache Variablen, so dauert es bei diesen 50 Durchgängen lediglich 0,0002 Sekunden um alle zu überprüfen. Dadurch kann der Teil, der mit Memcached gecached wird solange gültig sein, bis der User einen neuen Freund hinzugefügt oder gelöscht hat.
Methode 5 ist die Langsamste von allen. Auf diese Methode müsste man zurückgreifen, wenn man mehr als einen Webserver verwendet und XCache als Cachingsystem unbrauchbar wird*. Wenn man aber bedenkt, dass die Hauptaufgabe nicht ist, bedeutend schneller zu sein als MySQL, sondern nur, den Datenbankserver zu entlasten, so ist die Geschwindigkeit immernoch mehr als ausreichend.
Fazit:
Solange man noch nicht darüber nachdenkt, mehr als einen Webserver zu verwenden, sollte Methode 4 verwendet werden, bzw. Methode 3, wenn die Onlinezustände der User nicht angezeigt werden sollen.
Methode 4 geht bei 50 Durchläufen noch in Ordnung. Man sollte es mit den Schleifen jedoch nicht übertreiben. Die benötigte Zeit steigt entsprechend der Anzahl der Durchläufe!
Mittwoch, 13. Januar 2010
Xcache vs. Memcached
Xcache 1.3.0 vs. Memcached 1.4.4
php 5.2.12 ... xcache statisch eingebunden.
memcache modul ebenfalls statisch eingebunden in der version 2.2.5
webserver: nginx-0.7.64
system: 2 x intel quadcore. 8GB ram. open suse 10.
getestet wurde die geschwindigkeit des setzens und des einlesens von werten in den jeweiligen cache.
testreihe 1 mit memcached über unix-socket:
1.test:
timer: 100000 mal xcache variable gesetzt ( 0.4659)
timer: 100000 mal memcached variable gesetzt ( 2.5669)
timer: 100000 mal xcache variable eingelesen ( 0.1838)
timer: 100000 mal memcache variable eingelesen ( 2.4150)
2.test:
timer: 100000 mal xcache variable gesetzt ( 0.4774)
timer: 100000 mal memcached variable gesetzt ( 2.5527)
timer: 100000 mal xcache variable eingelesen ( 0.1897)
timer: 100000 mal memcache variable eingelesen ( 2.3908)
3.test:
timer: 100000 mal xcache variable gesetzt ( 0.4690)
timer: 100000 mal memcached variable gesetzt ( 2.8108)
timer: 100000 mal xcache variable eingelesen ( 0.1873)
timer: 100000 mal memcache variable eingelesen ( 2.6441)
testreihe 2 mit memcached über TCP:
(hier wurde ein anderer server benutzt, mit 16GB ram und etwas schnelleren prozessoren. alles andere ist identisch)
1.test:
timer: 100000 mal xcache variable gesetzt ( 0.2311)
timer: 100000 mal memcached variable gesetzt ( 2.5986)
timer: 100000 mal xcache variable eingelesen ( 0.1547)
timer: 100000 mal memcache variable eingelesen ( 2.3529)
2.test:
timer: 100000 mal xcache variable gesetzt ( 0.2354)
timer: 100000 mal memcached variable gesetzt ( 2.6385)
timer: 100000 mal xcache variable eingelesen ( 0.1561)
timer: 100000 mal memcache variable eingelesen ( 2.3573)
3.test:
timer: 100000 mal xcache variable gesetzt ( 0.2376)
timer: 100000 mal memcached variable gesetzt ( 2.6054)
timer: 100000 mal xcache variable eingelesen ( 0.1541)
timer: 100000 mal memcache variable eingelesen ( 2.3435)
auswertung:
das reine setzen und einlesen von einfachen variablen ist mit xcache deutlich schneller. das ist nicht verwunderlich, denn xcache bietet weniger funktionen und ist direkt in php eingebunden, wohingegen memcached als eigenständiger daemon läuft und seperat angesprochen werden muss.
wenn man einfache html-stücke oder variablen cachen möchte und man keinen extra-server zum cachen benutzt, dann sollte xcache die erste wahl sein.
memcached hingegen bietet die möglichkeit ganze objekte zu cachen. also beispielsweise mehrdimensionale arrays, womit man ergebnisse von datenbankabfragen cachen kann.
memcached bietet außerdem die möglichkeit große objekte bzw. strings zu komprimieren.
der entscheidende vorteil jedoch liegt in der fähigkeit memcacheds, sich auf verschiedene server verteilen zu lassen. dies ist insbesondere für größere projekte von vorteil.
fazit: es schadet nichts beide varianten parallel zu nutzen. xcache ist als opcode cacher ohnehin ein must-have. der variablen-cache ist da schon mit bei, also kann man ihn auch ruhig nutzen.
memcached sollte man nutzen, wenn es darum geht, wirklich große mysql resultsets zu cachen.
xcache: http://xcache.lighttpd.net/
memcached: http://www.memcached.org/
memcache (pecl): http://pecl.php.net/package/memcache
nginx: http://www.nginx.net
test-script:
php 5.2.12 ... xcache statisch eingebunden.
memcache modul ebenfalls statisch eingebunden in der version 2.2.5
webserver: nginx-0.7.64
system: 2 x intel quadcore. 8GB ram. open suse 10.
getestet wurde die geschwindigkeit des setzens und des einlesens von werten in den jeweiligen cache.
testreihe 1 mit memcached über unix-socket:
1.test:
timer: 100000 mal xcache variable gesetzt ( 0.4659)
timer: 100000 mal memcached variable gesetzt ( 2.5669)
timer: 100000 mal xcache variable eingelesen ( 0.1838)
timer: 100000 mal memcache variable eingelesen ( 2.4150)
2.test:
timer: 100000 mal xcache variable gesetzt ( 0.4774)
timer: 100000 mal memcached variable gesetzt ( 2.5527)
timer: 100000 mal xcache variable eingelesen ( 0.1897)
timer: 100000 mal memcache variable eingelesen ( 2.3908)
3.test:
timer: 100000 mal xcache variable gesetzt ( 0.4690)
timer: 100000 mal memcached variable gesetzt ( 2.8108)
timer: 100000 mal xcache variable eingelesen ( 0.1873)
timer: 100000 mal memcache variable eingelesen ( 2.6441)
testreihe 2 mit memcached über TCP:
(hier wurde ein anderer server benutzt, mit 16GB ram und etwas schnelleren prozessoren. alles andere ist identisch)
1.test:
timer: 100000 mal xcache variable gesetzt ( 0.2311)
timer: 100000 mal memcached variable gesetzt ( 2.5986)
timer: 100000 mal xcache variable eingelesen ( 0.1547)
timer: 100000 mal memcache variable eingelesen ( 2.3529)
2.test:
timer: 100000 mal xcache variable gesetzt ( 0.2354)
timer: 100000 mal memcached variable gesetzt ( 2.6385)
timer: 100000 mal xcache variable eingelesen ( 0.1561)
timer: 100000 mal memcache variable eingelesen ( 2.3573)
3.test:
timer: 100000 mal xcache variable gesetzt ( 0.2376)
timer: 100000 mal memcached variable gesetzt ( 2.6054)
timer: 100000 mal xcache variable eingelesen ( 0.1541)
timer: 100000 mal memcache variable eingelesen ( 2.3435)
auswertung:
das reine setzen und einlesen von einfachen variablen ist mit xcache deutlich schneller. das ist nicht verwunderlich, denn xcache bietet weniger funktionen und ist direkt in php eingebunden, wohingegen memcached als eigenständiger daemon läuft und seperat angesprochen werden muss.
wenn man einfache html-stücke oder variablen cachen möchte und man keinen extra-server zum cachen benutzt, dann sollte xcache die erste wahl sein.
memcached hingegen bietet die möglichkeit ganze objekte zu cachen. also beispielsweise mehrdimensionale arrays, womit man ergebnisse von datenbankabfragen cachen kann.
memcached bietet außerdem die möglichkeit große objekte bzw. strings zu komprimieren.
der entscheidende vorteil jedoch liegt in der fähigkeit memcacheds, sich auf verschiedene server verteilen zu lassen. dies ist insbesondere für größere projekte von vorteil.
fazit: es schadet nichts beide varianten parallel zu nutzen. xcache ist als opcode cacher ohnehin ein must-have. der variablen-cache ist da schon mit bei, also kann man ihn auch ruhig nutzen.
memcached sollte man nutzen, wenn es darum geht, wirklich große mysql resultsets zu cachen.
xcache: http://xcache.lighttpd.net/
memcached: http://www.memcached.org/
memcache (pecl): http://pecl.php.net/package/memcache
nginx: http://www.nginx.net
test-script:
ini_set('error_reporting', E_ALL);
ini_set('display_errors', 'On');
ini_set('display_startup_errors', 'On');
function start_timer($event) {
printf("timer: %s
\n", $event);
list($low, $high) = split(" ", microtime());
$t = $high + $low;
flush();
return $t;
}
function next_timer($start, $event) {
list($low, $high) = split(" ", microtime());
$t = $high + $low;
$used = $t - $start;
printf("timer: %s (%8.4f)
\n", $event, $used);
flush();
return $t;
}
$t = start_timer("");
$x = 0;
while($x < 100000) {
xcache_set('111',"aaahhh ein string!!!",300);
$x = $x+1;
}
$t = next_timer($t, "100000 mal xcache variable gesetzt");
$memcache_obj = memcache_connect('unix:///tmp/memcached.socket', 0);
//$memcache_obj = memcache_connect('127.0.0.1', 11211);
$x = 0;
while($x < 100000) {
//$memcache_obj->set('111',"aaahhh ein string!!!",0,300);
memcache_set($memcache_obj, '111', "aaahhh ein string!!!", 0, 300);
$x = $x+1;
}
$t = next_timer($t, "100000 mal memcached variable gesetzt");
$x = 0;
while($x < 100000) {
$daten = xcache_get('111');
$x = $x+1;
}
$t = next_timer($t, "100000 mal xcache variable eingelesen");
$x = 0;
while($x < 100000) {
$daten = memcache_get($memcache_obj, '111');
$x = $x+1;
}
$t = next_timer($t, "100000 mal memcache variable eingelesen");
?>
Sonntag, 10. Januar 2010
Via PHP Unix-Socket auf Memcached zugreifen. Problembehebung.
Für mich so als Notiz.
// über IP
//$memcache_obj = memcache_connect('127.0.0.1', 11211);
// über socket
$memcache_obj = memcache_connect('unix:///tmp/memcached.socket', 0);
Geht nicht auf Anhieb, da memcached unter dem User "nobody" läuft und keine Berechtigung für /tmp/memcached.socket hat.
Nach dem Starten von Memcached ändert man mit Chmod die Zugriffsrechte der memcached.socket auf 777 und dann gehts.
Sonst gibts Fehlermeldung "Permission denied".
UPDATE:
memcached mit dem flag -a 777 starten, dann hat sich das Problem auch erledigt.
also quasi ./memcached -s /tmp/memc.socket -a 0777
// über IP
//$memcache_obj = memcache_connect('127.0.0.1', 11211);
// über socket
$memcache_obj = memcache_connect('unix:///tmp/memcached.socket', 0);
Geht nicht auf Anhieb, da memcached unter dem User "nobody" läuft und keine Berechtigung für /tmp/memcached.socket hat.
Nach dem Starten von Memcached ändert man mit Chmod die Zugriffsrechte der memcached.socket auf 777 und dann gehts.
Sonst gibts Fehlermeldung "Permission denied".
UPDATE:
memcached mit dem flag -a 777 starten, dann hat sich das Problem auch erledigt.
also quasi ./memcached -s /tmp/memc.socket -a 0777
Donnerstag, 17. Dezember 2009
Via phpmyadmin nachträglich einen Auto-Increment primary key hinzufügen
Wer kennt es nicht.
Man muss mit einigen Werten testen und muss eine Tabelle um einen neuen Primary Key bereichern. Wenn man das über phpmyadmin mit der normalen Spalten-Hinzufüge-Funktion macht, klappt dies nicht auf anhieb.
Hier die Lösung: Zuerst die Spalte (bsp. "id") anlegen, ohne gleichzeitig Auto-Increment zu aktivieren oder die Spalte als Index zu definieren. Als wäre es eine ganz normale Spalte.
Danach diese Spalte als INDEX festlegen (noch NICHT Primary Key). Nun die Spalte bearbeiten und "Auto increment" aktivieren.
Jetzt kann man bei Bedarf den Index als Primary Key deklarieren.
Fertig.
Man muss mit einigen Werten testen und muss eine Tabelle um einen neuen Primary Key bereichern. Wenn man das über phpmyadmin mit der normalen Spalten-Hinzufüge-Funktion macht, klappt dies nicht auf anhieb.
Hier die Lösung: Zuerst die Spalte (bsp. "id") anlegen, ohne gleichzeitig Auto-Increment zu aktivieren oder die Spalte als Index zu definieren. Als wäre es eine ganz normale Spalte.
Danach diese Spalte als INDEX festlegen (noch NICHT Primary Key). Nun die Spalte bearbeiten und "Auto increment" aktivieren.
Jetzt kann man bei Bedarf den Index als Primary Key deklarieren.
Fertig.
Donnerstag, 25. Dezember 2008
Mit AJAX nachgeladene Javascript-Funktionen ausführbar machen
Problem:
ersetzt man einen Teil einer Seite dynamisch per Ajax und enthält dieser Inhalt Javascript-Funktionen, so können diese leider nicht ausgeführt werden.
Dafür gibts aber eine Lösung:
Folgende Funktion muss in den Teil der Seite eingebaut werden, der nicht ersetzt wird:
ersetzt man einen Teil einer Seite dynamisch per Ajax und enthält dieser Inhalt Javascript-Funktionen, so können diese leider nicht ausgeführt werden.
Dafür gibts aber eine Lösung:
Folgende Funktion muss in den Teil der Seite eingebaut werden, der nicht ersetzt wird:
function evalScript(scripts)
{ try
{ if(scripts != '')
{ var script = "";
scripts = scripts.replace(/