JSON sucks

  • Ersteller Ersteller omaliesschen
  • Erstellt am Erstellt am
Ist das alles was du zu melden hast? Spitze Zungen vermelden Du solltest mich meiden.


und bevorzugst freche Antworten

Solche hier?

Der Threadtitel ließ es schon vermuten, hier sitzt das Problem eher vor dem Bildschirm.

gerne auf deinem Murks

dass du nicht wirklich verstanden hast



Verstehe ich, es ist nur dumm, wenn sich der Problemsolver beim lösen eines Problems _selbst_ Probleme in den Weg legt, die es nicht geben müsste.

Welches den? Eine suboptimale Vorgehensweise ist noch lange kein Problem.
 
Zuletzt bearbeitet:
omaliesschen schrieb:
Spitze Zungen vermelden Du solltest mich meiden.

Ok, mache ich ab jetzt sofort.

Achja, du hast es nicht verstanden und es ist Murks, was ist daran frech? Ok, das war dumm von mir, ich sollte an meiner Ausdrucksweise arbeiten. Neuer Versuch: Deine Lösung ist doch sehr suboptimal, ich würde vorschlagen, dass du dich nochmal etwas genauer mit der Thematik auseinander setzt.

Tschüssi
 
Wenn Du an dem Murks welchen Du vermutlich als homogenen Sprachfluss empfindest arbeitest erkläre ich mich bereit dazu die Vorgehensweise bei der Erstellung eines JSON Strings zu überdenken dessen Resultat den Regeln entspricht ist.
 
oma, du kannst dich beschweren soviel du willst: JSON mit String-Operationen in Schleifen zusammenzuschustern ist einfach nicht sinnvoll.
Viel sinnige wäre es, wenn du deine Arrays/Objekte direkt bauen würdest und die fertige Datenstruktur in JSON umzuwandeln. Dann hättest du auch das Problem nicht.
 
Code:
$json = array('lg' => array('tail'));
foreach ($sth as $r) { $json['lg']['tail'][] = $r; }
$json = json_encode($json);

@dcobra
Das Du gestern im Unterricht aufgepasst hast ändert an deinem Hitzeempfinden nur sehr wenig.
 
Zuletzt bearbeitet:
Bescheuerte Frage:
Was hindert dich, statt dieser foreach-Schleife einfach direkt das ganze Array anzuhängen? Du ratterst über das array drüber, statt dir direkt einfach alle Elemente einzufügen?

$json['loaded_msg']['mesg_detail'] = $sth;

Wo genau liegt da das Problem, dass du das nicht machen kannst?
Irgendwo sieht dein foreach da recht fehlplatziert aus ...
 
var_dump($sth) ->

Code:
object(PDOStatement)

Zumal innerhalb der Schleife das gesammelte Array mittels einer anderen Funktion aufgearbeitet wird.
 
Zuletzt bearbeitet:
Keine weiteren Einwände?

Kann ich mich auf das escapen ohne eigene Funktion verlassen?
 
ja, denn das ist die Aufgabe von json_encode().


omaliesschen schrieb:
Code:
    $json = array('loaded_msg' => array('msg_detail'));
    foreach ($sth as $r) { $json['loaded_msg']['msg_detail'][] = $r; }
    $json = json_encode($json);

Der Loop ist unverzichtbar.
Schonmal ein Array-Cast auf $sth probiert? Also $data = (array) $sth, eventuell funktioniert es - sind teilweise so undokumentierte Eigenschaften, dass die Klassen doch eine Art toArray() implementiert haben.


Nachtrag:
Äh, warum eigentlich kein $sth->fetchAll() ? Das scheint ja ein PDOStatement zu sein, das wäre doch das naheliegendste
 
Zuletzt bearbeitet:
Was für Vorteile bringt es das Ergebnis von fetchAll() einer Funktion zu übergeben in der ein Loop gestartet wird um einzelne Teile zu bearbeitet, gegenüber einer foreach Schleife in der die einzelnen Arrays der Funktion übergeben werden?
Ergänzung ()

Viel interessanter finde ich es die Datenmenge mittels setFetchMode(PDO::FETCH_ASSOC); zu reduzieren.
Ergänzung ()

Auch auf die Gefahr hin mich dem allgemeinen Spot auszusetzen, hier ist das aktuelle Skript. Recht überschaubar und mir selbst wären noch Optimierungsmöglichkeiten geläufig.

Was sagt die Fachwelt zu den zusammengeschusterten Zeilen?

PS: Das ist natürlich nur der aktuelle Stand und es fehlt noch bisschen was.

Code:
<?php
session_start();

try{

	if (!isset($_SESSION['UID'])) { exit(); }
	else{ $user = $_SESSION['UID']; }

	$conv_session = 1; // tmp 
	$json         = array('loaded_msg' => array('msg_detail'));
	$previous     = (isset($_GET['previous']) && $_GET['previous'] != '') ? (int)$_GET['previous'] : 0;

	require('/var/inc/dbconnect.php.inc');
	require('/var/inc/functions.php.inc');


	function encode($in){

		$depth = count($in);

		for ( $i = 0; $i < $depth; ++$i ) {
			$in[$i]['msg_time'] = get_time_ago($in[$i]['msg_time']);
			$in[$i]['msg_text'] = nl2br(san($in[$i]['msg_text']));
			$in[$i]['a_name']   = san($in[$i]['a_name']);
		}

		return $in;

	}


	function sendData($json){
		header("Expires: Tue, 11 Sep 2001 00:00:00 GMT" ); 
		header("Last-Modified: " . gmdate( "D, d M Y H:i:s" ) . "GMT" ); 
		header("Cache-Control: no-cache, must-revalidate" ); 
		header("Pragma: no-cache" );
		header("Content-Type: text/json; charset=utf-8");
		echo $json;
	}


	if(isset($_POST['msg_text']) && $_POST['msg_text'] != '') {
		$sth = $dbh->prepare('INSERT INTO msg_live_chat(conv_session, user_id, msg_text, msg_time) VALUES (?,?,?,?)');
		$sth->execute(array($conv_session,$user,trim($_POST['msg_text']),time()));
	} 


	$sth = $dbh->prepare('SELECT m.msg_id, m.msg_text, m.msg_time, a.id, a.a_name
		FROM msg_live_chat m 
		LEFT OUTER JOIN authors a
		ON a.id = m.user_id 
		WHERE m.conv_session = ? 
		AND m.msg_id > ?');


	$sth->setFetchMode(PDO::FETCH_ASSOC);
	$sth->execute(array($conv_session,$previous));
	$r = $sth->fetchAll();
	$r = !$r ? '' : encode($r);

	$json['loaded_msg']['msg_detail'] = $r;
	$json = json_encode($json);
	sendData($json);


}

catch (PDOException $p) {
	$json = '';
	$json['loaded_msg']['msg_detail'][] = array(
	'msg_id'   => 0, 
	'msg_text' => 'Sorry. An error occured', 
	'msg_time' => get_time_ago((int)time()), 
	'id'       => 0, 
	'a_name'   => 'System'
	);
	echo json_encode($json);
}

?>

Wo kann man optimieren? Wo finden sich BadPractices und was ist einfach nur Pfusch?
 
Zuletzt bearbeitet:
N paar Sachen würd ich ändern...

Bei encode($in) würde ich nicht mit count() und for() arbeiten, sondern mit foreach mit ner Referenz.

Die Datenbank würde ich wahrscheinlich noch stärker abstrahieren. Entweder würde ich mir eine bestehende DB-Klasse schnappen, oder aber selbst eine schreiben. Ich mag Objektorientierung...

Grundsätzlich würde ich hier nicht auf ein RDBMS setzen. Aus eigener Erfahrung kann ich dir sagen: Chats sind nicht wirklich nett zu klassischen RDBMS. Ein Key-Value-Store wäre günstiger, den kannst du im Idealfall sogar direkt mit JSON-Strings füttern.

Bei nl2br() in Verbindung mit unformatiertem Text bin ich immer etwas skeptisch. Es hat seinen Nutzen, aber eben auch seine Tücken. Für einen einfachen Chat reicht es, für komplexere Funktionen ist z.B. ein BB-Code - Parser recht nützlich.... und wenns nur für Smileys/Emoticons ist. Hier würde ich wohl gleich Nägel mit Köpfen machen.
 
Danke.

der Chat ist nur temporär. Die Endlösung sieht eine NodeJS/Redis/Websocket Lösung vor mit der ich mich erst noch vertraut machen muss. Bis dahin hätte ich allerdings gerne eine funktionierende PM Funktion in der Form wie es später dann über NodeJS laufen wird. Wenn Du mich fragst ist der AJAX/MySQL Weg als Endlösung völlig inakzeptabel.

Code:
	function encode($in){

		foreach ( $in as &$value ) {
			$value['msg_time'] = get_time_ago($value['msg_time']);
			$value['msg_text'] = nl2br(san($value['msg_text']));
			$value['a_name']   = san($value['a_name']);
		}

		return $in;

	}
 
Und? Klappts mit dem Foreach? Sieht zumindest deutlich aufgeräumter aus.

Und gegen AJAX spricht nichts, nicht zuletzt weil es überall funktioniert und sehr einfach zu implementieren ist, z.B. via Mootools/jQuery. Man kann damit auch wunderbar Daten von einem SQL-Server pollen. Geht auch wunderbar... Dein Kernproblem ist die Art der Daten. Deine Daten erlauben keinen Query Cache und zerballern permanent den Index. DESHALB geht ein RDBMS nicht.
Websockets klingen toll, aber mal ehrlich: Willst du 1/4 deiner potentiellen Besucher ausschließen? Unklug. Auf Websockets kannst du in 5-6 Jahren evtl. setzen.
http://caniuse.com/#search=websocket
Spätestens der lange rote Balken bei "Android Browser" würde dafür sorgen, dass ich diese Technologie nicht einmal mit dem Arsch angucke.... und hey... 20% der User verwenden IE8/9, die können auch keine Websockets...
 
Daaron schrieb:
Dein Kernproblem ist die Art der Daten. Deine Daten erlauben keinen Query Cache und zerballern permanent den Index. DESHALB geht ein RDBMS nicht.

Der Query Cache wird sinnlos, richtig. Aber die Aussage zu dem Index komplett falsch. Der wird kein Stück zerballert, noch irgendetwas, B-Bäume und die am meisten eingesetzten B+/B*-Bäumen sind auf viele Änderungen ausgelegt, die wurden vor vielen Jahren von sehr schlauen Menschen für so etwas erschaffen.
Und das der Query Cache nutzlos ist, stellt auch kein Problem dar (den Mist sollte man eh deaktivieren), ein InnoDB mit einem großen Bufferpool und die ganzen relevanten Daten liegen gecacht als Seiten im Arbeitsspeicher, dann braucht es kein Query Cache mehr.
 
Tja, mach doch mal den Härtetest: Installier dir ein Magento mit 3k Produkten, die jeweils 100 Varianten haben. Schalte dann mal den Query-Cache ab... Das willst du nicht erleben. Du kannst nicht alles in den Buffer Pool werfen, außer du hast eine einzelne Maschine mit wenigstens so 16GB RAM nur für diese eine Datenbank.
 
Was sind denn heute auch noch 16GB Ram? oO
Datenbanken sind eben Speichermonster, und wenn Magento wirklich so ne große DB hat nimmt man eben mind. 16GB, wo ist das Problem?
 
16 GB / (3k*100) = 53 kB pro Variation oder 5 MB pro Produkt mit all seinen Variationen.
Da würd ich mal sagen, dann ist Magneto übelst ineffizient.

BTW:
Lass die Cache bei deinem Magneto an (auch wenn's da kein Problem wäre, einfach das HTML zu cachen), aber für ein Chatsystem bremst das einfach und erzeugt einen Flaschenhals auf Multithreading-Systemen.
 
Hancock schrieb:
Lass die Cache bei deinem Magneto an (auch wenn's da kein Problem wäre, einfach das HTML zu cachen), aber für ein Chatsystem bremst das einfach und erzeugt einen Flaschenhals auf Multithreading-Systemen.
Wie ich schon sagte, für ein Chat-System nimmt man gar nicht erst MySQL, sondern eben eine NoSQL-Lösung. Genau für solche Anwendungszwecke gibt es den Kram ja, genau da blüht er auf. Außerdem: Wie stellst du den Query Cache NUR für die 1-2 Tabellen ab, die für den Chat zuständig sind, lässt ihn aber überall da an, wo er einfach effektiver ist? Ganz oder gar nicht.... udn gar nicht halte ich aus persönlicher Erfahrung für keine gute Idee.

Und es ist etwas problematisch, Magento selbst komplett zu cachen. Das klappt nur, wenn du zusätzlich noch einen weiteren Server als Fullpage-Cache vorschaltest. Und selbst dann hast du spätestens im Admin Panel ein paar kräftige Probleme. Das Panel spinnt ja schon etwas, wenn man nur einen OpCode-Cache verwendet. Bei Fullpage hast du oft Sorgen, dass die dargestellten Daten nicht mit dem realen Zustand überein stimmen. Mage ist eben etwas... speziell.... aber eben auch zu mächtig, um es nicht zu nutzen.
 
Meine Einschätzung ist das ein MySQL basiertes Chatsystem über einen eigenen Server laufen sollte.
 
Zurück
Oben