tag:blogger.com,1999:blog-8255408447587672992024-03-13T16:21:34.279+01:00doepDevelopment ideas mostly regarding mC2 (musikCube) and other nerdy stuff.Anonymoushttp://www.blogger.com/profile/17242697277954515696noreply@blogger.comBlogger20125tag:blogger.com,1999:blog-825540844758767299.post-15380650806838664252011-05-09T23:38:00.000+02:002011-05-09T23:38:03.387+02:00Optimized websitesThis article is about how to setup and develop a website in PHP.<br />
At our company we develop a Learning Management System (LMS), and a couple of years ago we decided to rewrite the whole LMS from scratch and at the same time take all our experience and make the best of it.<br />
We took into consideration everything from choice of web-server, scripting language, database backend, clients proxy caching (that we have had some problems with before), etc etc.<br />
This is a guide on our experiences from nothing to version 2.0 of our LMS.<br />
<br />
<span class="Apple-style-span" style="font-size: large;">Web-server:</span><br />
Our servers are running Linux, so the choice of web-server some years ago was always Apache. But since about 75% of all the content that our servers send is static files we decided to give nginx a try. Nginx is a asynchronous web-server that only runs in one process and serves files with very little footprint or load on the system. Nginx can not serve php-files like Apache can using mod_php, but instead you use fastcgi to execute php-files. The downside with Apache is that every request has it's own process, and every process will load mod_php even if only serving a static file, so every request will use up alot of memory with no advantage. Nginx will (when configured right) instead only proxy the fastcgi when it needs to execute php code.<br />
<br />
<span class="Apple-style-span" style="font-size: large;">PHP:</span><br />
So the choice of nginx required us to execute php through fastcgi, and fortunately php now includes php-fpm that is a fastcgi process manager for php.<br />
Setting up php-fpm is basically like setting up how Apache works. You need to set the number of startup/maximum/minimum processes.<br />
At first I was a bit worried that executing php through nginx/fastcgi/php-fpm would affect the performance, but after setting it up and benchmarking some php scripts, we noticed that the performance was about the same compared to Apache/mod_php.<br />
We also made the choice to use xcache that is set up and optimized for 4 cores that we have on the webserver. Optimizing xcache for several cores using the xcache.count parameter affects the locking of shared memory quite a bit.<br />
<br />
<span class="Apple-style-span" style="font-size: large;">Problems with web-server/PHP:</span><br />
When we started to benchmark our LMS we ran into some problems that are important.<br />
<br />
<ol><li>The first problem was that PHP leaks memory, so after running the web-server for a couple of hours we noticed that the php-fpm processes was getting bigger and bigger, so after a while the server started swapping memory that affected the whole system.<br />
The solution was easy: Just set php-fpm parameter "pm.max_requests" to something like 20 that means that the process will only serve 20 requests and then shut down. Php-fpm will handle this nicely and start a new process if the processes are too few.</li>
<li>When benchmarking under high load, we started to get alot of php errors that turned out to be problems with the database. PHP could not connect to the database anymore giving us some undocumented error code in return.<br />
We use PHPs PDO to connect to a MySQL-server running on a different server and the error we got turned out to be a error that there where no available ports anymore.<br />
The solution again was very easy: Just turn on persistent connections to the database. If you do not use persistent connections, the PHP script will connect to the database and make it's requests and then close the connection. But a normal system will still make that TCP port unavailable for another 60 seconds, and since there are only some thousand ports dedicated to this you will eventually run out of ports.<br />
When we turn on persistent connection, the connection will not close to the database unless the process is killed and that will only happen every 20 request with our configuration. </li>
</ol><br />
<br />
<span class="Apple-style-span" style="font-size: large;">Static files:</span><br />
When we developed the new version of our LMS we made some very good decisions based on previous experience.<br />
We see our static files in different ways:<br />
<br />
<ol><li>Shared files: This is files used everywhere and is basically javascript (like jquery, json, uploadify, etc), stylesheets and images.</li>
<li>Uploaded files: In a LMS the administrators upload all the content like documents and SCORM-packages.</li>
</ol><br />
<b>Ground rule: NEVER UPDATE STATIC FILES!!</b><br />
This means that if we make a update on any of the shared files, we make a new revision in a new path. For instance we go from http://example.com/shared/r100/jquery.js to http://example.com/shared/r101/jquery.js if we upgrade jquery.<br />
If the administrators upload any new content, we always update the path to the content like: http://example.com/data/documents/1/mydoc.pdf to http://example.com/data/documents/2/mydoc.pdf<br />
If we follow this rule, we can setup nginx with the setting "expires max" on all our static files. This basically means that if a browser have downloaded the file once, it will not even check to see if the file is updated again and if we update a file, the path change and the browser will see this as a new file to download.<br />
This will also take care of any miss-configured proxy server that doesn't check for updated files as it should. Proxy servers are very good with this aproach, since they can take the load off serving static files.<br />
<br />
<b>Rule: Compress appropriate static files.</b><br />
For our shared file, we have made a script that will go through all the javascript and stylesheets and run minimize on them and then gzip them. So in the "shared" folder there is always both a myscript.js and a myscript.js.gz. Now we can turn on the nginx "gzip_static on" that will check if the browser can handle compressed files. Nginx will then serve the gzipped file instead.<br />
<br />
With all this setup I compared the output before and after. Out front page was initially about 850Kb big and included alot of images, stylesheets and javascript. After all this settings the front page went down to 120Kb, and since the static files weren't served again with the "expires max", clicking on a link is very fast since it's only the page itself that needs to be served.<br />
We also have turned on nginxs "gzip on" on out php files.<br />
<br />
<span class="Apple-style-span" style="font-size: large;">Bottlenecks:</span><br />
Our web application is very fast. We have a very well normalized and indexed database running on one backend server and our webapp is developed using Zend Framework. When we make a load test on the LMS the bottleneck actually isn't the database as you normally predict, but instead it's PHP that is the main bottleneck. On maximum load on the web-server (4 cores) the database (1 core) server only has a load of about 1/4 compared to the web-server. We are looking at different approaches to optimize this like trying to optimize the autoloader or maybe even use PHP hip-hop compiler. The problem is not memory on the web-server; there is plenty of memory left and the maximum number of php-fpm processes is never reached under maximum load.<br />
<br />
<span class="Apple-style-span" style="font-size: large;">Conclusion:</span><br />
After optimizing our application, we score 91/100 on the "page speed" firebug plugin. And we have no problems with high load on our servers at all. But it's always fun to optimize webapplications further since I'm a bit allergic to slow webapps :)<br />
Any suggestions on how to optimize this further is appreciated.<br />
<div><br />
</div>Anonymoushttp://www.blogger.com/profile/17242697277954515696noreply@blogger.com2tag:blogger.com,1999:blog-825540844758767299.post-16715994040651883882011-02-08T01:32:00.000+01:002011-02-08T01:32:42.414+01:00Howto design a webapp C++ MVC API part 2Doing a MVC implementation that is intuitive in C++ isn't very easy. I'm thinking about how to implement the controllers. Should the controller-class be inherited by the implementations or should it provide some kind of callback/signal-system. For some reason I seem to be against inheriting from the controller, but compared to a signal/slot or similar callbacksystem, this is probably the best and most intuitive option.<br />
<br />
So I'm thinking something like this:<br />
-----<br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">// Create a webapp</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">forumApp myforum;</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">http_server.add_webapp("forum",myforum); // add the forumApp to the "/forum/"-path</span><br />
-----<br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">// Looking at the forumApp-class, it inherits the webapp_controller</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">class forumApp : public webapp_controller{</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> // Set up the "sub" controllers in a static method</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> static void add_controllers(dispatcher::ptr dispatcher){</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> // Add the controller "forumAdministration" to the subpath "/forum/admin/"</span><br />
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> dispatcher->add_controller<forumAdministration>("admin"); </span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> // Add the controller "forumThread" to the subpath "/forum/thread/"</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> dispatcher->add_controller<forumThread>("thread");</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> // Also add actions related to this controller </span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> dispatcher->add_action(&forumApp::about,"about");</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> }</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br />
</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> void about(connection &con){</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> con.send_response("this is the best forumapp ever");</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> }</span></div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">}</span><br />
-------<br />
So, this is just initial thoughts. Writing about this helps me figure out how code would look like, and who knows, maybe I can catch someones attention.<br />
<br />
Next up is how views should work and what type if template-system to use or not to use.Anonymoushttp://www.blogger.com/profile/17242697277954515696noreply@blogger.com2tag:blogger.com,1999:blog-825540844758767299.post-40383176648122551262011-02-06T23:25:00.010+01:002011-02-07T01:15:55.675+01:00Howto design a webapp C++ MVC API?So I decided to start on my webspeed-project doing a http/fastcgi server. So far I'm just implementing the http-server itself, but designing it so that a typedef will turn it into a fastcgi server instead.<br />
<div>The implementation is very simple, just create a doeplus::webapp::http_server, set the callback and then send content to the doeplus::webapp::connection provided in the callback.</div><div>It looks like this:</div><hr /><div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">int new_connection(doeplus::webapp::connection::ptr connection){</span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-tab-span" style="white-space: pre;"> </span>std::string content("Send this to the browser 200 times. ");</span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-tab-span" style="white-space: pre;"> </span>for(int i(0);i!=200;++i){</span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-tab-span" style="white-space: pre;"> </span>connection->send_response(content,false);</span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-tab-span" style="white-space: pre;"> </span>}</span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-tab-span" style="white-space: pre;"> </span>connection->send_response(" Finished",true);</span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-tab-span" style="white-space: pre;"> </span>return 0;</span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">}</span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br />
</span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">int main(int argc, char *argv[]) {</span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-tab-span" style="white-space: pre;"> </span>boost::asio::io_service io_service;</span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-tab-span" style="white-space: pre;"> </span>doeplus::webapp::http_server myserver(io_service,"127.0.0.1",9010);</span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-tab-span" style="white-space: pre;"> </span>myserver.connection_callback()<span class="Apple-tab-span" style="white-space: pre;"> </span>= &new_connection;</span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-tab-span" style="white-space: pre;"> </span>io_service.run();</span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-tab-span" style="white-space: pre;"> </span>return 0;</span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">}</span></div></div><hr />Pretty easy right. But it's not ready for production yet because I still have the major task in front of me. I will implement a MVC design for webapps.<br />
<div><br />
</div><div><b>How does a good MVC implementation looks like in C++?</b></div><div>Not an easy question. Lets see what we are trying to accomplish:</div><div><br />
</div><div>Classic webapps maps the address to the filesystem and associate file extension to something being executed. Instead of this approach I'd like to map the path to different controllers. Modern webapps are using addresses like this one: http://example.com/myapp/path/to/what/im/doing/dosomething<br />
Breaking down the path we have one "root" path to the webapp "myapp". Next we have a path to something related to what we are doing, and last we have the path to the action we would like to take.</div><div>So with this design we can break down the path to different kind of controllers. First we have a WebappController "myapp". Next we have several PathControllers "path", "to", "what", "im", "doing". Finally we have a "Action" in the last "doing" controller called "dosomething".</div><div><br />
</div><div>I can see other kind of information that can be hidden in the path itself. Take this example: </div><div>We have a forum-webapp with a administration where the administrators can edit users information. The path to a page like that could look like this:</div><div>http://example.com/forum/admin/users/35/edit</div><div>Using a path like this we can easily go from the "edit" action to the "editpermission" action of the user without providing the users id (35) with a very easy link to "editpermission".</div><div>With this in mind, we probably need to provide a type of controller that can handle more dynamic paths - maybe a RegexpPathController.</div><div><br />
</div><div>So far we have 3 different controller types: </div><div><ul><li>WebappController: This controller need to define the path to the webapp itself and maybe even on what virtual host to use. The path to the webapp itself should also be able to be just root "/".</li>
<li>PathController: This should be a subpath to another controller so that you can add the PathController to your WebappController or to another PathController.</li>
<li>RegexpPathController: Just like the PathController, but can also contain dynamic content.</li>
<li>There are probably other controllers to think of (like a ExtensionController), but this is what I can find out now.</li>
</ul><div>The next thing is how a "action" will work. The first design that comes to mind is that a "action" is a method (function) in the controller, but there are alot more to think about.</div><div><b><br />
</b></div><div><b>What exactly will happen when a user of the webapp direct the browser to http://example.com/forum/admin/users/35/edit ???</b></div><div><br />
</div><div>This is the big question that I've been asking myself. What is the best design for this?</div></div><div>Lets assume that we somehow has build <b>one</b> hierarchy of the controllers and the actions when the webapp was started. </div><div>We could just find out in the controller-hierarchy what action to execute and provide necessary information to the action and execute it. Although this will assume that each action is threadsafe since several simultaneous calls can be made to the same action. </div><div>Another option is that we can find out the controller-hierarchy and create a copy of the controller-object to that path. This approach may be better since the controllers now can be used for user-specific information like a User-object and the controllers can contain helper-methods for authentications and stuff like that.</div><div>Maybe I should implement different kind of controllers depending on if I want a unique controller-object for each call or a "static" object for the whole server?</div><div><br />
</div><div>I'm not done yet, and I have several designquestions to make decisions about.</div><div>More to come... soon... </div>Anonymoushttp://www.blogger.com/profile/17242697277954515696noreply@blogger.com0tag:blogger.com,1999:blog-825540844758767299.post-30348024349532854822010-10-11T23:47:00.003+02:002010-10-12T00:24:37.794+02:00What to do?I have the tendency to start projects and never complete them. I'm not sure why I'm doing this, but I guess it's because I tend to get bored after a while.<div>At the moment I have several projects in mind, but I'm not sure what to choose.</div><div><br /></div><div>My current/upcoming projects:</div><div><ul><li>musikCube 2: We started this project some years ago and I've done the mayor part of the codebase, but it got stalled when there was only I left in the project and we had also decided to switch to QT and that was a real energy drainer. I'd like to get this project going again, but there is so much effort to be put down before there will be any kind of release.</li><li>webspeed project: I've been researching how to get the maximum speed out of the web and found out that I'd like to do a C++ fastcgi framework. The project is all in my mind right now and I really think it could become a brilliant project.</li><li>Radix trie: You may have seen my latest blog posts about "associative array" benchmarks. I've started on a radix trie that is almost finished, but at the moment I actually do not have the use for it myself and therefore I do not see the point in finishing it.</li><li>Work projects: I have 2 projects for work that I'd like to do. But work projects should be done during working hours. </li></ul><div><br /></div></div><div>All of the projects are really interesting, but why should I complete them?</div><div>A project should have any or several of the following motivation factors:</div><div><ul><li><b>Money</b>. The work projects are partially motivated by money, but I do not earn more money if I develop them outside working hours.</li><li><b>Curiosity</b>. Like my radix trie project. Can I do this better/faster than everyone else?</li><li><b>Need</b>. A project that fulfills a need. musikCube 2 was this kind of project in the beginning. But nowadays I just use spotify instead.</li><li><b>Kudos</b>. Sometimes a project is driven by the fact that other users/developers express their gratitude for the project. The best gratitude is when a project is being used alot by others.</li></ul><div>For a project to really take of, it probably requires more than one of the motivation factors.</div></div><div>Right now, I'm not sure if any of my projects fall into more than one factor, so I guess that's why I'm not developing anything instead.</div>Anonymoushttp://www.blogger.com/profile/17242697277954515696noreply@blogger.com2tag:blogger.com,1999:blog-825540844758767299.post-9283318823355971962010-08-29T15:39:00.012+02:002010-08-29T16:56:37.760+02:00Benchmarking "associative array"Some time ago I needed a fast way to look up objects in what people would call an associative array. In C++ this most of the time means a std::map<std::string,myobject> or something similar.<div>A std::map is a great generic container that associate any kind of object with any kind of other object, and it's usually very fast as well. This blog post will be about benchmarking different kinds of ways to associate strings with objects.</div><div><br /></div><div>Lets look at what the different alternatives we have:</div><div><ul><li>std::map<std::string,myobject>: The most generic way that almost always is available on all platforms. Often using binary trees.</std::string,myobject></li><li>boost::unordered_map<std::string,myobject>: Also a generic container using hash index instead of binary trees.</std::string,myobject></li><li>stringmap<myobject>: An attempt by myself to make a specialized container with strings as the key and a trie index.</myobject></li></ul>There are many other containers out there and I will follow up on this post when I have the time comparing other trie/radix implementations. Right now I'm mostly interested in how fast the std::map and boost::unordered_map are.</div><div><br /></div><div>So to try them out we need to make different kind of tests. We are interested in the performance when doing a "find" in the container, and when doing "inserts". We should also do different tests for different kind of strings.</div><div><br /></div><div>Lets cut to the chase and do some benchmarking:</div><div><br /></div><div><span class="Apple-style-span" style="font-size: x-large;">Round 1: "find" totaly random data.</span></div><div><span class="Apple-style-span">In this test each string is totally randomized with a size between 1 and 255. Each char is a char between 1 and 255. Basically a worst case scenario for doing hash index.</span></div><div><span class="Apple-style-span"><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://onnerby.se/~daniel/blog/bench_rand_find.png"><img style="cursor:pointer; cursor:hand;width: 876px; height: 513px;" src="http://onnerby.se/~daniel/blog/bench_rand_find.png" border="0" alt="" /></a><br />It turns out that boost::unordered_map is pretty fast. But my own implementation that specialize in strings is almost twice as fast.</span></div><div><span class="Apple-style-span"><br /></span></div><div><span class="Apple-style-span" style="font-size: x-large;">Round 2: "find" some more normal data.</span></div><div><span class="Apple-style-span">Total random data is not very common, so I thought that I should do a test of something a little more common data. I made a "find /usr/" on my linux-box and used that as the keys.</span></div><div><span class="Apple-style-span"><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://onnerby.se/~daniel/blog/bench_norm_find.png"><img style="cursor:pointer; cursor:hand;width: 876px; height: 513px;" src="http://onnerby.se/~daniel/blog/bench_norm_find.png" border="0" alt="" /></a><br /></span></div><div>boost::unordered is still pretty damn fast. And it does not seem to degrade much when the container size gets larger.</div><div><br /></div><div>For me, this tests would be enough since I'm mostly interested in how the "find" performs. But I have also made a benchmark with the same data on how "inserts" performs.</div><div><br /></div><div><span class="Apple-style-span" style="font-size: x-large;">Round 3: "insert" random data:</span></div><div>Same data as the round 1 data.</div><div><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://onnerby.se/~daniel/blog/bench_rand_insert.png"><img style="cursor:pointer; cursor:hand;width: 876px; height: 513px;" src="http://onnerby.se/~daniel/blog/bench_rand_insert.png" border="0" alt="" /></a><br /></div><div>Not much to say. They all seem to perform nearly equal when inserting random data.</div><div><br /></div><div><span class="Apple-style-span" style="font-size: x-large;">Round 4: "insert" normal data:</span></div><div>Same data as the round 2.</div><div><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://onnerby.se/~daniel/blog/bench_norm_insert.png"><img style="cursor:pointer; cursor:hand;width: 876px; height: 513px;" src="http://onnerby.se/~daniel/blog/bench_norm_insert.png" border="0" alt="" /></a><br /></div><div>Now, this is interesting. boost::unordered performs very well in this test. You also notice the typical characteristics for a hash index.</div><div><br /></div><div><span class="Apple-style-span" style="font-size: x-large;">Conclusion:</span></div><div>Well. Comparing std::map and boost::unordered_map was interesting. If you are using std::map today, replace it with boost::unordered_map unless you are using map-specific methods like equal_range. I also concluded that there is room for some specialized string-specific containers. </div><div><br /></div><div>I have found some specialized trie/radix index containers and will follow up on them later on.</div><div>If they aren't drop in replacements for a std::map, I will probably continue on my own "stringmap" container and make it fully compatible with std::map.</div><div><br /></div><div>Note: I should also do a test on memory usage.</div></std::string,myobject>Anonymoushttp://www.blogger.com/profile/17242697277954515696noreply@blogger.com4tag:blogger.com,1999:blog-825540844758767299.post-15340336467052871002010-06-28T21:15:00.020+02:002010-06-28T22:54:10.142+02:00Search for webapp speed part 2: Designing my own<div>Some thoughts about how I would make a webapp-engine if it should gain some real speed (just for fun):</div><div><br /></div><div><b><span class="Apple-style-span" style="font-size:medium;">Language:</span></b></div><div>There are several good languages out there for writing webapps. PHP, Java, C#, Perl, Python, Ruby, node.js (javascript), etc, etc.</div><div>It all comes down to what language you prefer, and I would prefer C++.</div><div>C++ have the speed and the flexibility to do everything, but the downside of being too complex for just doing webapps.</div><div></div><blockquote><div><i>But C++ is my prefered language.</i></div></blockquote><div><br /></div><div><b>Model for speed:</b></div><div>So the big question is how a webengine should be modeled to avoid all the big bottlenecks. Lets look at the different parts of a webapp-server</div><div><br /></div><div><b>Webserver:</b></div><div>First of all we need a webserver.</div><div>We could use an existing webserver like nginx, and it would probably be the best choice, but (just for the fun of it) lets see how a webserver would work if I made it myself.</div><div><br /></div><div><b>Multiprocessing/Multithreaded/async webserver?</b></div><div>This is a good question. A multiprocessing webserver has the advantage of being safe. If a process dies/leaks/hangs the kernel handles the cleanup. But a multiprocessing webserver will take a lot of memory since each process has its own stack and overhead. The downside of a multiprocessing webserver is also that it's hard to communicate between processes.</div><div>A multithreaded webserver would probably be a good idea since threads doesn't take as much memory as a process, and threads share memory between each other. The downside would be that if a thread hangs, the whole process hangs.</div><div>We also have the option to do a async webserver (like node.js). Meaning that everything done in the webserver is done in a "non blocking" way using a library like boost::asio. The advantage of using a non blocking webserver is that you do not need to worry about any deadlocks, but it can be hard to build plugins that are non blocking. I find the async way very interesting and I've tried to find out how node.js does plugins like gzip nonblocking without luck. I will investigate this further :)</div><div></div><span><span><br /></span></span><blockquote><span><span><i>For speed and memory usage, I would go with either multithreaded or a async webserver.</i></span></span><div></div></blockquote><div><br /></div><div><b>Communication between app-engine and webserver:</b></div><div>We probably want a little bit of fail safety between our webserver and app-engine, so running the app and the webserver in different processes is probably a good idea. We could then write the webserver so it would start the app-process if it's not already running.</div><div>But running the app and the webserver in different processes will also cause our first performance problem. How do we communicate between the app-process and the webserver?</div><div>IPC (Inter-process communication) is a big topic on the internet, and I have to say that I do not know a lot about this. But as I see it, we have the following options:</div><div><ul><li>Sockets: TCP/IP connections between the processes, just like the connection between the webserver and the client. This does not seem like an ideal option since it takes some time to open a new socket. But it's supported by all operatingsystems.</li><li>Pipe: (POSIX systems) You know.. like the pipes that you use on Linux like this "cat README.txt | grep stuff".</li><li>Named pipes: (POSIX systems) More advanced pipes, but does not seem like a good solution.</li><li>Semaphore: A kind of locking mechanism between processes.</li><li>Shared memory: A technique to share memory between processes. Does not seem to have a way to send notifications between processes though.</li></ul></div><div><br /></div><div>Sockets seems like the best solution, but to minimize latency, we should keep connections open between the app and the webserver, and reuse the connections.</div><div><br /></div><div>The goal of the webserver should be to handle all static files and then be used as a kind of a proxy for the webapp and forward the connection to the app-process. Although it is probably a good idea to be able to send back some special headers from the app to the webserver like example "Webserver: use_compression=1" to tell the webserver to compress the response before sending it back to the client. This way we but some of the load over to the webserver, and let the app do it's own thing.</div><div><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1H5u9nCLzFwe3uezq-AfzDNXuxDdY5-YbCeBGgHNQHJV9v0Gws4QNP39sa3KC_CLk7PVjwn97eb8vd7LR5iXIaSIX7Yxa0nCyZb_HJM4S_tf4dG5-roklYDVz9-21Oac6f4p3IuxzjMgc/s1600/appmodel.png"><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1H5u9nCLzFwe3uezq-AfzDNXuxDdY5-YbCeBGgHNQHJV9v0Gws4QNP39sa3KC_CLk7PVjwn97eb8vd7LR5iXIaSIX7Yxa0nCyZb_HJM4S_tf4dG5-roklYDVz9-21Oac6f4p3IuxzjMgc/s400/appmodel.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5487909655906486786" style="cursor: pointer; width: 400px; height: 229px; " /></a></div><div><br /></div><div><br /></div><div><b>The apps:</b></div><div>So how do we design the app itself. The app itself should be a executable that when started will listen for socket connections. The webserver will be responsible for starting the app-executable if it's not already running.</div><div>So we need to write several classes and C++ templates to help making a good webapp (I will use the namespace "webplus" in this example for the classes/templates)</div><div><div><br /></div></div><div><ul><li>webplus::app should be the main class for the whole app, responable for listening to the correct socket (that probably comes from a config-file or send as parameters from the webserver when the app-executable is started)</li><li>webplus::request and webplus::response when a connection is made, the webplus::app should create a webplus::request and a webplus::response object that helps parsing headers, paths, and all request related information. The objects should then be send to the app-writers own code where the app decides itself if it should be written multithreaded or as a nonblocking app.</li><li>webplus::cachemap<class> Helper map templates that could be used for objects often used. For instance if you have a User class and you would like to keep the 100 most frequently used User-objects in memory:<br /><span class="Apple-style-span" style="font-family:'courier new';"><span class="Apple-style-span" style="font-size: small;">typedef webplus::cachemap<int,user> UserCacheMap;<br />UserCacheMap userCache(100); // maximum 100 objects in the map<br />User doep('doep','Daniel'); // create a user object<br />userCache[1] = doep; // copy the object to the cache<br /></span></span>It would probably be better to use a boost::shared_ptr if the objects gets bigger and I haven't fully thought this through. But you get the point ;)</li></ul><div><br /></div></div><div><b>Summary:</b></div><div>I'm not saying I'm about to write a new webapp-engine, I just started thinking about how I probably would have done if I where about to write one and I find it interesting to know how other people do things like this.</div><div>Although I have to admit that I am a little bit tempted to do this now, and a appengine like this would be ideal to use instead of the current musikServer.</div>Anonymoushttp://www.blogger.com/profile/17242697277954515696noreply@blogger.com1tag:blogger.com,1999:blog-825540844758767299.post-63030507647371314652010-05-11T00:25:00.004+02:002010-05-11T00:30:02.382+02:00Search for webapp speed<div>If I want real speed for a web application. What webserver/language should I use?</div><div>This is a question I've been asking myself lately, and I found that there is no real good solution currently available.</div><div>Sure, PHP/ASP/JSP/Whatever with MySQL/SQLite/OtherDB would probably work in most cases, but I would like to have some real powerful kick ass speed.</div><div>What I would like to have is C++ used like a scripting language, and I've been thinking that this can't be that impossible. Can it?</div><div><br /></div><div>What I would like to have:</div><div><ul><li>A webserver that compiles the C++-files when accessed just like a scripting language. It should check for file-changes and compile when appropriate.</li><li>The abillity to create in memory "application"-objects that also can run things in threads. What I mean is that if I for instance create the "application" "http://myserver/forum", there could be some "void main()" in the "forum"-folder that is executed when the webserver starts. This "void main()" could then create threads or do whatever it would like in the background. If C++-files would change related to the "application", then it should run the applications appropriate destructors, recompile, and start the "application" again.</li><li>Preferably it should be build using MVC.</li><li>Everything should be build using a object oriented interface. Communication between "pages" and the "application" and the webserver should all be done using pure virtual interfaces plugins <a href="http://code.google.com/p/musikcube/wiki/PluginAPI">just like we do in mC2</a> . This would make everything alot more clean.</li></ul></div><div><br /></div><div>If something like this existed you would be able to build some really powerful webapps. Caching the most important objects in the "application"-part, and accessing the rest from the database.</div><div>Sure, the developer would still be responsible for not overloading memory in the "application"-part, but C++-developers are used to this. It would probably help with some kind of help-library that implements caching-vectors that removes objects that are rarely used in the "application"</div><div><br /></div><div>so, am I the only one that's been thinking like this or is my googling just bad?</div><div><br /></div>Anonymoushttp://www.blogger.com/profile/17242697277954515696noreply@blogger.com3tag:blogger.com,1999:blog-825540844758767299.post-35410738352756411612009-10-23T10:55:00.003+02:002009-10-23T11:02:02.153+02:00Pointless application for andoidI've been very busy at work lately. But yesterday I had a couple of hours left so I started to try out how to make some graphics/games stuff for android.<div>What I came up with was a very pointless application that draws some pixels with gravity that reacts to the accelerometer.</div><div>But I've learned alot :)</div><div>Download at: <a href="http://onnerby.se/~daniel/bengt/bengt.apk">bengt.apk</a></div>Anonymoushttp://www.blogger.com/profile/17242697277954515696noreply@blogger.com1tag:blogger.com,1999:blog-825540844758767299.post-9324421598276697722009-09-01T08:32:00.003+02:002009-09-01T08:39:27.524+02:00musikCube on androidSo, I finally finished the first version of the musikCube android client.<div>It's working pretty good, and I have even implemented the "workout mode" that I have been writing about for a while.</div><div>I have submitted the application to <a href="http://code.google.com/android/adc/">ADC2</a> and will add it to the market as soon as I know it's ok to do so according to the ADC2 rules.</div><div>To run the android client you need to have a musikServer up and running and you also need to know how to find it (IP-number, ports etc).</div><div>Download from this barcode:</div><div><img src="http://onnerby.se/~daniel/mc2barcode.png" style="cursor:pointer; cursor:hand;width: 200px; height: 200px;" border="0" alt="" /></div><div><br /></div>Anonymoushttp://www.blogger.com/profile/17242697277954515696noreply@blogger.com4tag:blogger.com,1999:blog-825540844758767299.post-48470602936755671202009-06-10T22:34:00.002+02:002009-06-10T22:47:35.393+02:00IDE followupSo after my recent cursing over some <span class="blsp-spelling-error" id="SPELLING_ERROR_0">IDEs</span> I have finally bought myself a <span class="blsp-spelling-error" id="SPELLING_ERROR_1">HTC</span> Magic android phone. So the next logical step was to try out the android <span class="blsp-spelling-error" id="SPELLING_ERROR_2">SDK</span> to see if that works.<div><span class="blsp-spelling-error" id="SPELLING_ERROR_3">Btw</span>, I have to say that I just love the android system. It's by far the most logical and intuitive interface I have come across. And I was really surpriced to see a full implementation of ActiveSync on android.</div><div><br /></div><div>Now, the android <span class="blsp-spelling-error" id="SPELLING_ERROR_4">SDK</span> is how a <span class="blsp-spelling-error" id="SPELLING_ERROR_5">SDK</span> should be. You first need to install eclipse and then install the android <span class="blsp-spelling-error" id="SPELLING_ERROR_6">SDK</span>. Finding out how to set up the <span class="blsp-spelling-error" id="SPELLING_ERROR_7">SDK</span> to work in eclipse was VERY easy. Just follow a step by step tutorial that took about 5 minutes and everything just works.</div><div><b>"Thank you android team, this is why you will succeed!"</b></div><div>Android team: Can you please instruct <span class="blsp-spelling-error" id="SPELLING_ERROR_8">Nokia</span> how to make <span class="blsp-spelling-error" id="SPELLING_ERROR_9">SDKs</span> and <span class="blsp-spelling-error" id="SPELLING_ERROR_10">IDEs</span> (they could really use the help)?</div>Anonymoushttp://www.blogger.com/profile/17242697277954515696noreply@blogger.com2tag:blogger.com,1999:blog-825540844758767299.post-56360813329692611742009-05-14T23:18:00.005+02:002009-05-15T00:32:58.756+02:00Wanted: Decent IDE<div>My latest effort on trying to make a flash lite client to musikServer did not turn out the way I wanted to. It turned out that flash lites playback of mp3s on the phone had a really crappy sound and as soon as it was out of focus (like when keylock kicks in or screensaver activates) it stopped playing. So I temporarily abandoned the project until flash lite has matured a bit.</div><div><br /></div><div>What I really would like to talk about was the problems with making a flash lite swf into a SIS file and the lack of good development tools.</div><div>In order to make a SIS file out of the flash SWF, I had to install a app called Adobe Mobile Packager. OK, I installed it.</div><div>Not working...</div><div>It turned out that it required CAB SDK, Perl and S60 SDK. So I installed them all.</div><div>Still not working...</div><div>Turns out that S60 SDK required java, so I installed that.</div><div>Still not working...</div><div>Turns out I have the wrong Perl version, so I installed the right version.</div><div>Still not working...</div><div>Tried 2 more different versions of S60 SDK until I found out the right version that worked.</div><div>Seems to work, but the phone complains about certificate so I package the exact same thing again, and now it works.</div><div><br /></div><div>After abandoning the whole project with flash lite, I decided to install Carbide C++ that is a IDE for developing C++ apps for symbian. Sure thing, Carbide downloaded and installed. Oh yeah, I also wanted to use some STL and boost since we use that in musikCube, so I had to install an extra SDK for that. So I started up carbide and created a standard "hello world" project from a tutorial. Without any changes I tried to build.</div><div>Lots of errors...</div><div>After 15 minutes of research it turned out that I again had the wrong Perl version, so I had to reinstall that again. New try to compile.</div><div>Some errors...</div><div>Hmm.. Some more research and it turns out that I have to have my project on the same drive I installed the S60 SDK on... Strange.. but anyhow, I moved it.</div><div>Still errors...</div><div>Tried to recreate some other of the project templates (basically different kind of "hello world" projects) and found one that compiled fine. So I started the project in the emulator.</div><div>Emulator hangs...</div><div><br /></div><div>At this point I am <span class="Apple-style-span" style="font-weight: bold;">VERY </span>frustrated. Why can't anyone make a decent IDE that just works out of the box. Problems like this is the reason why developers give up trying to develop C++. Coding C++ isn't very hard, but setting up a IDE and getting things up and running is a pain and this is the reason why people turn to scripting languages.</div>Anonymoushttp://www.blogger.com/profile/17242697277954515696noreply@blogger.com2tag:blogger.com,1999:blog-825540844758767299.post-13166500505291277742009-04-28T22:40:00.003+02:002009-04-28T22:55:53.919+02:00Thoughts for phone client.Thinking some more about the phone client I'm working on.<div>I've had an idea for quite some time to make a player on the phone that would play music in the same BPM as you are running in (or maybe a bit faster).</div><div>I noticed that in flash lite - at leased on my nokia - I am able to read the accellerometer. This means that I would be able to determin the BPM you are running/walking in and choose track accordingly and with the BPM-analyzer plugin on the musikServer, this is perfect :) </div>Anonymoushttp://www.blogger.com/profile/17242697277954515696noreply@blogger.com2tag:blogger.com,1999:blog-825540844758767299.post-73540329964100804562009-04-28T22:20:00.004+02:002009-04-28T22:37:54.905+02:00musikPhone?<div><div>So, what's going on with mC2?</div><div>I haven't had much time developing because of my current work has taken up all of my free time. But the last couple of days I've been playing around with flash lite and I've managed to connect to our musikServer using only flash lite on my Nokia N95. </div><div>Flash lite actually got all the functionallity to use the musikServer: It's got XMLSockets for doing all the querying, and the abillity to stream mp3s (although other formats will not play). </div><div>I also noticed that they are having a challenge both at http://www.callingallinnovators.com/flash.aspx and http://www.flashlitedeveloperchallenge.com/ that would be fun to participate in, and although I know it does not stand a chance to win because it requires a musikServer, it may generate some promotion.</div><div><br /></div><div>I guess I should be converting mC2 to using QT instead of doing this, but it's not as fun :)</div><div><br /></div></div>Anonymoushttp://www.blogger.com/profile/17242697277954515696noreply@blogger.com0tag:blogger.com,1999:blog-825540844758767299.post-88672882502864573822009-02-03T08:50:00.002+01:002009-02-03T08:53:03.069+01:00mC2dm3 released.<div>mC2 developer milestone 3 has just been released. <br /></div><div>We decided to make a release of the current state of the trunk since we have decided to make a very big change in mC2. We will in the future be using QT as the main GUI API.</div><div><br /></div><div>mC2dm3 changelog:</div><div><ul><li>Audioengine: Gapless playback<br /></li><li>Audioengine: Instant change when modifying volume or clicking "Pause".<br /></li><li>Decoders: mpg123 engine updated, seeking working alot better.<br /></li><li>One "Now playing" that can handle tracks from any library or http streams.<br /></li><li>HTTP streamed tracks choose decoder depending on mimetype.<br /></li><li>Precaching of http streams.<br /></li><li>mC2 will open the lastest opened library when restarting.<br /></li><li>Experimental plugin: BPM analyzer. A plugin that will analyze the BPM of your tracks.<br /></li><li>Experimental plugin: DSP Echo. A plugin that will put a small echo on all audio. Please note that there is no way to turn the plugin off unless removing the .dll file.<br /></li></ul></div><div><br /></div>Anonymoushttp://www.blogger.com/profile/17242697277954515696noreply@blogger.com4tag:blogger.com,1999:blog-825540844758767299.post-48644773448831218392008-12-06T22:52:00.002+01:002008-12-06T23:09:21.082+01:00mC2 progress<p class="MsoNormal" style="margin-bottom:0cm;margin-bottom:.0001pt;line-height: normal"></p><p class="MsoNormal" style="margin-bottom: 0.0001pt; ">So, 3 weeks and 500 downloads from mC2dm2 release. What's up next?</p><p class="MsoNormal" style="margin-bottom: 0.0001pt; ">We have started on the mC2dm3 release and we are starting to take a look on how to make mC2 a little more attractive.</p><p class="MsoNormal" style="margin-bottom: 0.0001pt; ">This is what we are planning to implement in the near future:</p><p class="MsoNormal" style="margin-bottom: 0.0001pt; "></p><ul><li>URI tracks: This is just the technical term we use for being able to open tracks not just from the library, but by just double clicking or drag'n'drop files on mC2. As you might have noticed mC2dm2 have a "now playing" for each library and is unable to combine tracks from multiple sources. mC2dm3 will have only one "now playing" in its own special tab, and you will be able to add files that aren’t in any library.</li><li>Album art: We need to start making an attractive appearance of mC2 and showing album covers is one way to do that.</li><li>Better preference dialog: We have a lot of preferences that we are able to set, but so far there haven’t been any dialog to change the settings in.</li></ul><p></p><p class="MsoNormal" style="margin-bottom: 0.0001pt; ">Well, this is just some of the features we are currently working on, but there are several features to come. For instance we have several developers showing interest in porting the musikServer to linux.</p><p class="MsoNormal" style="margin-bottom: 0.0001pt; ">Btw. We have just received our first donation. Kudos to DocTriv!</p><p></p>Anonymoushttp://www.blogger.com/profile/17242697277954515696noreply@blogger.com1tag:blogger.com,1999:blog-825540844758767299.post-31280605306453573302008-11-15T22:16:00.001+01:002008-11-15T22:19:45.700+01:00mC2dm2 is outIf you haven't <a href="http://www.musikcube.com/punbb/viewtopic.php?pid=13893">noticed</a>, we released a new developer milestone of <a href="http://code.google.com/p/musikcube/">mC2</a> the other day with the long awaited client/server implementation.Anonymoushttp://www.blogger.com/profile/17242697277954515696noreply@blogger.com0tag:blogger.com,1999:blog-825540844758767299.post-52403701216711469762008-11-12T07:56:00.003+01:002008-11-12T08:01:58.185+01:00LicensingThere is always a discussion on what license to use for open source development. Some years back I always used GPL when doing some development, but the last couple of years I have started to use licenses like BSD-style license.<br /><br /><span style="font-weight: bold;">So why this change?</span><br />Well. I'm developing alot of stuff at work, and when I get home and all kids are sleeping I continue to develop mC2 stuff. I often found myself writing the exact same stuff over and over again. For instance I wrote a db wrapper for mC2, and I reuse that at work for some internal application stuff, and I would not be able to do that if we had set a GPL license on mC2. Sure, the company I work for gain from this, but stuff I come up with at work I often set a BSD license on (with my company's approval) so I can reuse it for mC2 (often with some renaming of namespaces first though).<br />If I should rewrite everything all the time I would probably not have any energy left to develop mC2.<br /><br />I also see some great potential in BSD when it comes to popularity. If we can get companies to write plugin or make forks of mC2, they would probably just be helping us develop mC2, applying patches and fixing bugs. I mean, if a company has one of the greatest DSP techniques, would you choose to have a non open source plugin for it or non at all. If mC2 where GPLed, there probably would only be the choice of "non at all".<br /><br /><span style="font-weight: bold;">So what is the downside of using a BSD-style license?</span><br />One thing is that there are plenty of very good applications/libraries out there that I like to use in mC2, but it's not possible because of the GPL license. For instance I'd like to integrate the amaroks moodbar in mC2, but it has a GPL license.<br />Fortunately most libraries are still using LGPL and makes it possible for us to use them.<br />I know that there is a greyzone between BSD and GPL when using them as plugins, but we do not want to go there.<br /><br />This does not mean that I do not like GPL. GPL is a great license, just not for me as a developer :)Anonymoushttp://www.blogger.com/profile/17242697277954515696noreply@blogger.com0tag:blogger.com,1999:blog-825540844758767299.post-61927180108567484022008-11-01T21:06:00.003+01:002008-11-01T21:17:46.618+01:00Analyzing soundI've been working some with the audioengine we use in mC2. The engine was originally a rip of the tuniac eninge, but has been modified by bjorn to fit our needs in mC2 (really great work bjorn). The last month I've been implementing the filestreams in the decoders and started to look at how we should implement DSP and mixing plugins.<br />I found a library that looks very interresting called <a href="http://www.surina.net/soundtouch/">SoundTouch</a> that I can see some great features in.<br />First of all we could use it for "Track analyzer" plugin. A "Track analyzer" plugin is a plugin that make some kind of anayze of the sound and saves that info to the tracks metadata. SoundTouch could be used for analyzing BPM in all your tracks.<br />I also has been thinking of some more advanced plugins like DSP/Mixing plugins like beatmix plugins with timeshifting beats for a perfect mixing between tracks. SoundTouch is perfect for that kind of plugins.Anonymoushttp://www.blogger.com/profile/17242697277954515696noreply@blogger.com0tag:blogger.com,1999:blog-825540844758767299.post-10869705485700699582008-11-01T13:02:00.004+01:002008-11-01T13:19:50.703+01:00An extensible way to make filestreams.A couple of weeks ago we where talking on the irc about how we should implement streaming from http or other protocols. I've seen other implementations where it's been implemented on the decoder side so that basically the mp3 decoder will be able to receive a http address or a link to a file.<br />We didn't think this was flexible enough and decided to make our own filestream class that could be extended to use any type of protocol.<br />The implementation turned out to be very simple, the only hard work we needed to do was to send a <a href="http://code.google.com/p/musikcube/source/browse/trunk/src/core/filestreams/IFileStream.h">IFileStream </a>object to the decoders and use that instead of sending the path to the file. Luckily most decoders has thought about this and have ways to hook all calls to the streams.<br /><br />So now mC2 is able to stream anything as long as it has a decoder for it, and implementing new type of protocols is a breeze.<br /><br />More information can be found at the <a href="http://code.google.com/p/musikcube/wiki/FileStreams">mC2 wiki</a>.Anonymoushttp://www.blogger.com/profile/17242697277954515696noreply@blogger.com0tag:blogger.com,1999:blog-825540844758767299.post-58986146491583158032008-10-31T11:12:00.003+01:002008-10-31T11:17:09.548+01:00What this blog is all aboutSo, why should I start a blog?<br />Well, I'm a developer doing lots of C++ stuff and I develop <a href="http://code.google.com/p/musikcube/">mC2 </a>that is a rewrite of <a href="http://www.musikcube.com/">musikCube</a>.<br />This blog will probably be about all the ideas and coding done when developing mC2. So expect lots of code examples and other nerdy stuff :)Anonymoushttp://www.blogger.com/profile/17242697277954515696noreply@blogger.com2