Friday, April 17, 2015

Multi-threaded grep in bash

I've recently moved from web site testing to business data analysis.
One of my taks involved searchig for number of visits in apache access.log. Gzipped. For period of a year. On a popular MLM (multi-level marketing) website.

It took 10h to complete a search for a single pattern. I said we can do better and went for writting multi-threaded grep. I used bash because it was simples thing to compated with expected improvement. I was also immediately notified that hard drives won't handle much (searches are run on machine for logs backup) so there is no point in squizing power of CPUs, because I/O wait will kill any effort.

How do you do multi-threading in bash?

You have a loop over thousands of log files in which you run zgrep command. Just send it into background, right?
No - that will create so much processes that task switching will kill any improvements.
You can't really run more than 4 searches per CPU. That is still a lot if you have 8 CPUS :)

I've created a variable that incremented++ every time a new file was processed.
After reaching a limit of 4xCPU count, the script would wait for all of zgreps to finish.
Then we start from beginning - another 32 processes.

This is suboptimal and does not even touch things like thread pool.

But it still improved search time 6 times.
With that solution I've hit hard drives limit (I/O wait was cause of load) and no further optimization was possible.

Further steps

I'm thinking about indexing logs with number of visits per month per URL.
Out of curiosity I'm tempted to write a thread pool based solution in python.

When searching for several patterns, I would immediately benefit from finding a common part and searching for that part - so that the heaviest part of looking at every line of access.log is not repeated.

Sunday, October 12, 2014

Saving screenshot after each step in py.test framework that runs Selenium

Testing websites with Selenium is fun. Py.Test framework is really cool.
Joining those two and running tests inside of PyCharm IDE makes you wanna cry with joy. That is if you previously worked with iMacros :)

But sometimes testing takes hours, is run inside of crontab and you only need to check the results. The TimeoutException or NoSuchElementException tell you nothing if you haven't looked what the browser state was. The screenshot would really be helpful.

Acutally screenshot made after each test, regardless of the result would be helpful too - for example to detect layout errors or errors not covered by asserts.
I found a way to do this in pretty simple way. We will need a fixture that

  • is used automaticaly with every test step
  • calls the selenium driver to make a screenshot

I found no way yet to learn test outcome and make use of it when doing screenshot (like naming file with ``FAIL`` prefix or so on).

The key feature here is that our screenshot-making fixture uses the selenium driver fixture. And it is the same fixture that is provided to test functions.

Say we have selenium driver fixture that is module-wise parametrized with list of countries. That is a new browser session is delivered to module functions in a loop of countries. Eeach test module gets a browser and is run in a loop of countries given in params=:

__author__ = 'sigviper'

import os
import pytest
import datetime

@pytest.fixture(scope="module", params=["pl", "de"])
def driver(request):
    """Selenium driver that creates a loop by countries"""
    class FirefoxImprovedBySigviper(object):
        def screenshot(self, request_for_test_function, session_test_timestamp):
            country = request.param     # module-wise request (each param creates new)
            out_dir = "/tmp/shutter-{timestamp}/{country}/".format(timestamp=session_test_timestamp, country=country)
            try:
                os.makedirs(out_dir)
            except OSError:
                pass

            fname = "{out_dir}/{country}_{module}_{function}_{timestamp}.log".format(
                country=country,
                out_dir=out_dir,
                module=request_for_test_function.module.__name__,
                function=request_for_test_function.function.__name__,
                timestamp=get_timestamp()
            )
            f = open(fname, "ab")
            f.write(repr(self) + "\n")
            f.close()

    return FirefoxImprovedBySigviper()


@pytest.fixture(scope="function", autouse=True)
def shutter(request, driver, session_test_timestamp):
    """Screenshot-making fixture"""
    def fin():
        driver.screenshot(request, session_test_timestamp)

    request.addfinalizer(fin)

def get_timestamp():
    """Provide formatted current timestamp"""
    return datetime.datetime.now().strftime("%Y-%m-%d_%H:%M:%S")

@pytest.fixture(scope="session", autouse=True)
def session_test_timestamp(request):
    """Provide timestamp of test start time - fixed for a session"""
    return get_timestamp()

Now the driver must implement screenshot logic. Please take a carefull look on usage of request and request_for_test_function variables - they are not the same. The request is a attribute of driver fixture that is injected into FirefoxImprovedBySigviper class. The request_for_test_function parameter is given to screenshot function by shutter fixture that is ran before each test function call. The scope in test session of those variables is different. The module-wise request knows nothing about current function. On the other hand, request_for_test_function function-wise knows nothing about current param for the loop in driver. Consequently we need to use both.

Order of execution:

create session-wide timestamp and provide to all modules and functions
for each module create a Selenium driver:
    for each parameter in driver run all test functions in a module:
       save screenshot after each function call

Let's say we have two test modules: TestCatching and TestCopycatch each with three similarly named functions: *_ok, *_failed and *_raises
The test session in PyCharm looks like this:

The disk output with screenshot (here .log files, because I needed simple and quick sandbox for testing) looks like this:

viper@OptiPlex780:/tmp$ ls -lrctR shutter-2014-10-12_16\:16\:07/
shutter-2014-10-12_16:16:07/:
razem 8
drwxrwxr-x 2 viper viper 4096 paź 12 16:16 pl
drwxrwxr-x 2 viper viper 4096 paź 12 16:16 de

shutter-2014-10-12_16:16:07/pl:
razem 24
-rw-rw-r-- 1 viper viper 57 paź 12 16:16 pl_test_catching_test_1ok_2014-10-12_16:16:08.log
-rw-rw-r-- 1 viper viper 57 paź 12 16:16 pl_test_catching_test_2assert_failed_2014-10-12_16:16:09.log
-rw-rw-r-- 1 viper viper 57 paź 12 16:16 pl_test_catching_test_3raises_2014-10-12_16:16:10.log
-rw-rw-r-- 1 viper viper 57 paź 12 16:16 pl_test_copycatch_test_1copy_ok_2014-10-12_16:16:16.log
-rw-rw-r-- 1 viper viper 57 paź 12 16:16 pl_test_copycatch_test_2copy_assert_failed_2014-10-12_16:16:18.log
-rw-rw-r-- 1 viper viper 57 paź 12 16:16 pl_test_copycatch_test_3copy_raises_2014-10-12_16:16:19.log

shutter-2014-10-12_16:16:07/de:
razem 24
-rw-rw-r-- 1 viper viper 57 paź 12 16:16 de_test_catching_test_1ok_2014-10-12_16:16:11.log
-rw-rw-r-- 1 viper viper 57 paź 12 16:16 de_test_catching_test_2assert_failed_2014-10-12_16:16:12.log
-rw-rw-r-- 1 viper viper 57 paź 12 16:16 de_test_catching_test_3raises_2014-10-12_16:16:13.log
-rw-rw-r-- 1 viper viper 57 paź 12 16:16 de_test_copycatch_test_1copy_ok_2014-10-12_16:16:22.log
-rw-rw-r-- 1 viper viper 57 paź 12 16:16 de_test_copycatch_test_2copy_assert_failed_2014-10-12_16:16:24.log
-rw-rw-r-- 1 viper viper 57 paź 12 16:16 de_test_copycatch_test_3copy_raises_2014-10-12_16:16:25.log

All screenshots saved. Easy to find and sort. Names match country and test name. In case of error, timestamp is saved (sometimes helps developers narrow down periods in logs).

I like it. I'll just copy&paste it into my working code monday morning! :)

Thursday, July 31, 2014

Quality of software vs. quality of trucks

When company is to choose between two trucks (cheaper and more expensive) to buy, the schema is pretty straightforward. One is cheaper, of lower quality - the other offers quality and reliability. Some companies will choose the cheaper, most will probably go with reliability.

This is easy decision, basic competence of any company owner or manager - ask them about such a choice and not even a second and they start talking.

This is not the case with software

Most people ordering software cannot even understand what a quality and reliability of software is. With trucks you have publicly available reliability reports.
Trucks quality evaluation is a common knowledge. Evaluating reliability of software is area clouded with misconceptions and poor measure ideas.

Site availability in % per month is one of greatest tools to evaluate quality. But it does not say whether a user could even log in into system for the whole time.

You then go to measuring process availability in % per month which this is difficult and needs special agreements between companies.

The deeper you go into trying to understand quality and reliability the bigger obstacles you face.

This is why we stick with known errors or problems

Simple accounting tells us some fixes are too expensive to be made. Too expensive means: it's cheaper to constantly fix bugs due to that problem than fix the problem.

Simple accounting cannot account for software reliability, final user experience and so on.

Possible measures

By investing into Real User Monitoring we could really reach some level of confidence in software quality. Ammount of error statuses per hour gives you pretty good picture about whether processes work or not.

Other ideas:

  1. RUM: ammount of errorpages per hour for logged-in users
  2. window.onerror -> log problem via ajax for reporting and analysis
  3. ammount of errors in system logs (assuming java here, you need to count stacktraces)

Processes for quality

No logging or reporting will improve software if you do nothing with gained knowledge. Logs need to be inspected and bugs need to be reported.
Then those bugs need to be fixed and your client will have to agree to pay for this.

Information about found and fixed bugs need to be avaliable and transparent for both developing company and it's clients.

Third-party testing raids and code inspections should be as common and obvious as asking other doctor for opinion or visiting independent mechanic workshop.
Are we ready for this?


Paying more for better, more reliable software is a difficult choice. Let's not blame managers for their inability to understand our point of view.

Yes, quality is expensive as commonly said. Let's forge this slogan into real procedures and measures.

Maybe one day simple accounting will tell manager: you should pay more, you'll earn more with better software.

Tuesday, February 11, 2014

Retest and close what you reported

Tester's work is to find bugs, right?
Not exactly in my opinion: our job is to get rid of bugs and promote software quality.

Our job is to make sure bugs were fixed properly, with no new bugs introduced.
We also should make sure the fix is not lost, but:
  • deployed to production environments
  • pushed to the right branch

Resolution:Fixed

I've been often mislead by resolution:Resolved and "Fix version" field in JIRA. The bug might have status "fixed", and:

  • .. is not fixed at all or not good enough. Retest and Reopen!
  • .. is fixed, but not deployed (not commited/pushed ets). Retest and Reopen!
  • .. is fixed by changing system or deleting functionality. Retest and consult system architects.
  • .. is really fixed. Retest and Close!

Please keep in mind that the issue is fixed, when it's fixed on production and development of further system versions include that fix. What good is a fix if end users never see it, or next system version does not include the fix (i.e. reintroduces the bug)?

How do we get rid of bugs then?

  1. We retest the fix on the test/staging environment and Close the issue in bugtracking.
  2. We make sure that proper repository branches include our fix. It might not if:
    1. Client requests that only selected fixes from branch deployed to test are to be deployed on production.
    2. The fix is commited on a branch that is never merged with branch that the next system version is made of.
  3. We periodicaly retest important fixes to make sure no regression occurred
  4. We need to understand the cause of the error and expand test cases based on that knowledge - talk to programmers, and demand analysis/cause description in issue comments. The "done" comment is not good enough.

Periodic retesting?

With 10 bugs every month, we have a whooping 120 test cases for each year of project. That's quite a heap of things to retest, right?

To manage such a pile of imporant knowledge, we should document test cases that need to be done regularly.
Some of them should enter our automatic regression testing scenarios.

Automation of the regression testing should be based on analysys of causes of errors in the system. For example if search engine has trouble when filtering is employed - we should add such a tests and run it often.

If we don't do this - nobody will

Because only we know in details what was broken - only we are able to make sure it's fixed.
No programmer, chief programmer, project manager or developer is able to take up the task of getting rid of detailed system problems.

Monday, September 16, 2013

One node error is hard to detect by external monitoring

I logged in into pingdom.com account to checkout if scheduled maintenance was performed without problems. It was, but I noticed several 404 errors.

I have dumped eror statuses into .csv for last week, and after short analysis found out that there is great number of 404 errors since the maintenance period. Clearly something was wrong.

$ head /tmp/down_prod_analysys.csv 
Status;Date and Time;Error
unconfirmed_down;2013-09-16 09:05:29;HTTP Error 404
unconfirmed_down;2013-09-16 09:02:29;HTTP Error 404
unconfirmed_down;2013-09-16 08:56:29;HTTP Error 404
unconfirmed_down;2013-09-16 08:55:29;HTTP Error 404
down;2013-09-16 08:52:41;HTTP Error 404

Analysis

$ for i in `seq -w 8 16`; do 
       ## useful tip: -w outputs numbers padded with zeros for equal width (depends on seq end)
       echo -n "$i September: "; 
       ## -n: do not print \n
       grep "09-$i" /tmp/down_prod_analysys.csv | wc -l;
       ## wc -l: count how many lines
  done

08 September: 0
09 September: 4
10 September: 1
11 September: 5
12 September: 5
13 September: 2
14 September: 0
15 September: 237
16 September: 126 

Some requests to homepage were returning 404 and some not.
What is wrong is that pingdom.com set the status to unconfirmed - clearly there is some kind of problem.

Unconfirmed

Pingdom retests immediately from different node to confirm a error. Most of there retries returned OK results. How is that possible? I made a quick local check myself to reproduce:

$ for i in `seq 1 20`; do
     wget -S 'http://our_home.page' -a log.txt; 
     ## -S shows request headers, my favorite function in wget
     ## -a appends to logfile so that all output is stored
  done
$ grep ERROR log.txt 
2013-09-16 09:44:22 ERROR 404: Not Found.
2013-09-16 09:44:23 ERROR 404: Not Found.
2013-09-16 09:44:25 ERROR 404: Not Found.
2013-09-16 09:44:27 ERROR 404: Not Found.
$ 

20% of requests got 404 error. Maybe one application node or one of http servers has a problem?

Turns out it is indeed so, one of application servers is misconfigured and always returns 404.

Lessons learned

  • Unconfirmed error does not mean service works in round-robin load balancing architectures.
  • Take time to go through your logs.
  • If in doubt, investigate.

Monday, September 9, 2013

Weird IllegalArgumentException in HashMap constructor

Exception in thread "main" java.lang.IllegalArgumentException: Illegal load factor: 0.0
        at java.util.HashMap.(HashMap.java(Compiled Code))
        at java.util.HashMap.(HashMap.java(Inlined Compiled Code))
        at pl.my_emploee_data.(Minute.java(Compiled Code))
....

This is a bug I was assigned to fix. First tried to look at the Minute.java code and found this in the constructor:

this.servers = new HashMap(Limits.SERVERS);

What could be wrong with suggesting initial hash map size, right?

the JVM

My initial thought was: maybe it's not SUN (Oracle) Java and some incompatibilities occur. Maybe the HashMap constructor parameter was misunderstood? Found IBM Java 1.4.
This is known to be incompatible, but it's not the OpenJVM that simply does not work with most of our code.

the Fix

Just removed the initial size parameters, since default (16) size isn't that much different.

I was tempted to say 'premature optimization is the root of all errors', but actually this isn't the case.
Something must have broken the working code. Probably some fix pack, patch or change in the system.
Somehow the default 0.75 load factor must have been overriden to 0.0.

There are some hints in http://www-01.ibm.com/support/docview.wss?uid=swg21610313 about -Djdk.map.althashing.threshold
Since the code works now and issue seems to be maintanence-like, I only notified hosting staff about the problem to think about.

If however someone has some idea where we might have made such a mistake, please let me know.
(grep jdk.map.althashing.threshold yelds nothing)


UPDATE: It seems that using default constructor (without size) was not a very good idea. Application went out of memory and I had to go back to the initial size. Simply specified the load factor, overriding the problematic parameter:

this.servers = new HashMap(Limits.SERVERS, 0.75f);

Lessons learned:

  • running code on different JVM than usual or used for testing, makes error more probable
  • fix the code with minimum impact
  • admit to yourself that things are not always that simple

Friday, July 12, 2013

Do not assume existence of any data when creating a uptime monitoring sensor.

AlertFox

I've been evaluating AlertFox monitoring service lately, which I like alot.
It has awesome features, killing instantly services like pingdom.com.
I'm able to do anything on my site that a real user can - javascript pitfalls are not a problem.

I also get a screenshot of a problematic situation, which is priceless in case of a 500 error (it contains the error_id that leads programmers to stacktrace. Pretty useful, right?).

To monitor if the website was working properly I created a script that:
  • enters website and uses search bar 
  • evaluates if the product was found

It worked like charm till yesterday 10:00 AM. Got a alert e-mail saying that the site was down 50% of a time. So I went to customer service with that info, to notify them of the problem. 
It turned out to be a false alarm sadly. The product was no longer available, it was deleted.

Lessons learned

  • Do not assume as constant the existence of data or (editable) labels when creating a uptime monitoring sensor
  • Rely instead only on code features, and even then - watch out for system updates
  • Simpler is again better

Friday, March 22, 2013

The universe works agains us - entrophy!

I've been reading Stephen Hawking's The Theory of Everything this morning. He explains the entropy of black holes.

Between the lines, I was able to understand that entropy, understood as, chaos or lack of order, rises constantly. It rises because time elapses...

I got enlighted: the project or code, left alone, will get worse in time, when we do nothing.
A simple act of abstaining from action, lack of management, lack of trying to bring order, makes things worse.
This of course is just a analogy, not a law. But let's examine it..


Lack of action = lack of order

Example 1
The team works hard on developing the system. In the meantime, the test acceptance phrase takes place, and 50 bugs are reported.
The team continues the work on developing, neglecting the bugs - "we'll do it later".

That simple decission makes things worse. How? 
* broken windows (Pragmatic programmer)
* programmer is no longer responsible for delivering working code, since some things do not work already
* overall quality drops rapidly because of attitude
Lack of constant quality requirements (lack of order) makes things worse.

Example 2
The team works serveral months on a project now, and 150 bug/improvement issues are due. The project is near the deadline. The huge amount of work is discouraging - no light in a tunnel, no hope to do a good job.
For political reasons, dropping some functionality in a trade-off for quality is not going to happen. That would be a great, wise decision, but such wisdom would require a single, strong leader. This isn't happening in big bank corporations (our client is one).

I proposed some rearrangement of tasks for developers in yesterday's article; here is the summary:
A developer is required to finish the overall process/part of the system - develop all changes, fixes and improvements. He/she then signalises: "that part of the system is done".
The amount of work does not change, but the "getting work done" attitude gets a huge positive kick. The hope is restored.
Moreover, even when not everything could be done before deadline, at least most parts of the system will work perfectly.

Another example, how simple act of ordering of tacks, brings quality to the project.

And how abstaining from action, brings more trouble.

Entropy is your enemy.

 Do something, manage some change, bring order, rethink tasks... or face failure.

Thursday, March 21, 2013

Improving productivity when project gets messed up

My team is in the middle of serveral-months long development process of website for bank client. We had several stages in project, currently we are on last one.

System is soon to be opened for the world, yet quality still is poor.
There is no one part of the system we could say "it works".
As a tester, I feel it's my duty to improve overall quality.

Overloaded team

The team seems to overloaded with jira tasks. There are three kinds of them:
* totally new features (agreed upon with our client, and paid for)
* bug fixes
* improvements to existing features

Current development mode could be summarised by: "develop new features, and we'll get back to bugs later".

My first approach (after high eyebrow rise and some breathing exersises to calm myself) was: "Let's not break the system - please let's have overall quality as a first goal". This was rejected by the team.
Mainly because the project would be a political failure, should we fail to deliver 100% of requested functionality. I asked several times whether 100% functionality must work, and it seemed that "it should" :-)

Getting parts of the system done

Today I proposed another approach. When developer changes part of the system (a screen, or a process), he/she should:
* read the specification (official document detailing the way system works, the design) and make sure that particular system feature works exactly as describet
* look at jira issues, find and resolve all of task that are related to given feature/screen/process

After that, no improvements or changes are allowed. That particular feature is finished. Sure, there might be bugs, but no changes are allowed.

This way, we could get small, but importand quality improvements with each new system version (every 2 days). This way, the system would finally work properly someday.

This is only a change of view

Developers still have the same amount of work to be done. But my approach fixed the "context switch" problem and, even more importantly, leaves a feeling of job being done. Some parts of the system may now be ticked as done.
The team gets visibly closer and closer to the final goal.

My hope is that this method gets accepted...

Thursday, October 25, 2012

The hidden cost of bad implementation

We have two systems integrated: one processes the internet form and outputs a XML (the forms system), the other receives and stores the output and processes further user input (the frontend system).

For economical reasons the output is stored as text (CLOB) in database, violating the principles of rational relational database usage.

The alternatives were:

  1. a dedicated table (entity) that would need to be changed everytime the other system changed 
  2. table with attributes: form_id | field_name | field_value 
  3. dynamic class with .toXML_CLOB() and .readFromXML_CLOB() methods to parse the XML

The first idea was rejected because it was unpractical - changes to XML output would break the integration. The changes to forms system are unpredictable and the solution was rightly rejected.

The second idea was used in some systems previously in our company and served us well.  I've maintained such systems for 4 years. I liked possibility of mass update of fields in case of :
  • application needing different format of value
  • app ceasing to accept some values/value ranges

The third idea is riddiculous in static java world.

The rationale

The reason simple text storage was choosen was that very little bugs or updates were expected. This turned out to be true, because of enormous experience of team making this decission. Bear in mind hovewer, that it might have turned otherwise.
The type of decission is beeing called 'engeeneering 95% decission', which means that is is solves 95% of requirements/problems.

The misscalculation

But was it truely the effective decission or unwise bow to the budget? Please notice, that the implementation cost of field_name | field_value table is not very much higher than CLOB. I'd say 2 or 3 times more work (max 40 hours more). And we're talking about two year project in team of 15 people. And we're talking about integration.

Integration is something that can't be easly changed once it starts being used.


The hidden cost

What was not taken under consideration are the lost opportunities of good software. The value and stability of well written app is stressed across many books and lectures in the field. Yet it gets forgotten so often.

Let's explore the opportunities of good, simple implementation field_name | field_value. Those are things easly done with this implementation and very hard to be done upon XML CLOB:

  • mass update of date format
  • when a field may no longer be empty, a mass update of default value is easly done
  • analysys of values in specified field is easly deliverable
  • one may search for a form with specified e-mail
  • easy duplicate values (e-mails to be precise) detection and rising alerts
  • additional business-critical validation of user-entered values is possible. Some data is unavailable for forms system but is available in frontend system. Some critical assumptions could be tested (and re-tested) after form has been submitted.
  • any request to alter or analyse forms data would be reasonably priced. Reasonable pricing of simple operations is good. Prohibitive prices for simple things are very, very bad for business relations.
  • alternate ways to deliver the forms data to the system would be easly possible - the frontend system would have a possibility to become some kind of center of processing data. Good for business, right?

Summary

  1. Good implementation delivers higher value to customer who paid for the system.
  2. Good implementation allows better business-to-business relations
  3. Good implementation allows system to grow and become a importand bond between business partners

The hidden cost are those lost opportunities.


Tuesday, September 11, 2012

Fix on four branches

Commit this to following four branches

Yesterday one of developers in my project got a message to commit her changes to four branches in central repository. I said "you must be kidding me" and immediately went to investigate.

We develop new features on separate branches and cherry pick them to release candidate branch that is put to testing and possibly deployed on production. There is also a "master" branch for non-client requested changes and a branch for immediate fixes on production.

As the fix was needed by two different changes (branches), two commits seemed reasonable. What about the master and "fixex" branch?

It turned out that the developer in charge of changes process requested immediate merge to those two branches in fear of someone taking over him (less experienced programmer) might have trouble applying the patch without errors upon master and/or fixex branch also needining this fix.

So some part of new feature was developed on branch, needed the fix, but the fix was also to be applied to other branches is case the changes were to be added to those branches.

This is bad. This is anticipating a problem that did has not yet happened. This potentially breaks the stable branches (not requested, surprise change). This a real problem of trust and leadership.

Don't do it, please. Trust your co-workers to do the good job. Anticipate problems by documending prodedure and quirks. Advice and help verbally. But do not spoil the code.

Wednesday, May 30, 2012

Simple statistics alghoritm that beats A/B methodology hands down

http://stevehanov.ca/blog/index.php?id=132

The alghoritm shows [Buy me!] button in 3 different colors. If user clicks it, "click through ration" for color is risen. It user does not, it's lowered. After 100 clicks (and thousands of visits) one gets very good estimate of both click througrh ratio and which button works best.

Simple.

Friday, May 25, 2012

Friday, February 3, 2012

Memory efficiency in java

I've encountered great resource about memory efficiency of huge java applications: http://domino.research.ibm.com/comm/research_people.nsf/pages/sevitsky.pubs.html/$FILE/oopsla08%20memory-efficient%20java%20slides.pdf

Main points of the presentation are:

  • Representation overhead is sometimes huge
  • Representation overhead not always diminshes with data size (!)
  • Caches should have bounded size
  • Many tiny strings consts you more than you think

Upon reading this paper you will

  • Understand why your simple, low scale java app takes 2GB RAM
  • How to use memory more efficiently
  • Why and how to use good old mmap in java
  • .. have a few good ideas for refactoring

This has been a very good and interesting paper for me, despite the fact I don't like java much. There is hacking spirit and great amout of war-field experience in it. Go read it if you are java pro.

Thursday, November 17, 2011

Flex codebase is now worthless

https://www.pcworld.com/businesscenter/article/244060/adobe_donates_flex_to_apache.html

Commercial giant Adobe believes his Flex codebase is now worthless and donates it to Apache foundation. I discovered the same early this year when I was developing on Flex Hero (4.5) platform.

No documentation, copy-and-paste development and paid development tools were epic fails. Glad to see the free market working towards extinction of technically inferior solutions.

Thursday, October 13, 2011

Facebook's first shot at search

Facebook platform features some mobile functionalities.

Among others, there is search:
https://developers.facebook.com/docs/guides/mobile

This is first serious shot of Facebook at search functionality in terms of challenging Google.
I hope someone makes cool use of that and earns a lot of money :)

Wednesday, October 12, 2011

Clojure will not work

Clojure will not work. Here is why it will not work.

Based on:

Programming Language Checklist

by Colin McMillen, Jason Reed, and Elly Jones.

Slightly modified for clearer rant

You appear to be advocating a new:
[x] functional  [ ] imperative  [x] object-oriented  [ ] procedural [ ] stack-based
[ ] "multi-paradigm"  [x] lazy  [ ] eager  [ ] statically-typed  [x] dynamically-typed
[x] pure  [ ] impure  [ ] non-hygienic  [ ] visual  [ ] beginner-friendly
[ ] non-programmer-friendly  [x] completely incomprehensible
programming language.  Your language will not work.  Here is why it will not work.

You appear to believe that:
[ ] Syntax is what makes programming difficult
[x] Garbage collection is free                [ ] Computers have infinite memory
[ ] Nobody really needs:
    [ ] concurrency  [ ] a REPL  [x] debugger support  [ ] IDE support  [ ] I/O
    [ ] to interact with code not written in your language
[ ] The entire world speaks 7-bit ASCII
[x] Scaling up to large software projects will be easy
[x] Convincing programmers to adopt a new language will be easy
[x] Convincing programmers to adopt a language-specific IDE will be easy
[ ] Programmers love writing lots of boilerplate
[ ] Specifying behaviors as "undefined" means that programmers won't rely on them
[ ] "Spooky action at a distance" makes programming more fun

Unfortunately, your language has (checked only *unfortunate features*, Clojure has tail recursion):
[ ] semicolons  [ ] significant whitespace  [x] macros
[x] implicit type conversion  [ ] explicit casting  [ ] type inference
[ ] goto  [x] exceptions  [ ] coroutines
[x] reflection  [ ] subtyping  [ ] operator overloading
[ ] algebraic datatypes  [ ] recursive types  [ ] polymorphic types
[ ] covariant array typing  [ ] dependent types
[x] infix operators  
[ ] call-by-value  [ ] call-by-name  [ ] call-by-reference  [ ] call-cc

Unfortunately, your language lacks:
[ ] comprehensible syntax  [ ] macros
[ ] implicit type conversion   [ ] type inference
[ ] goto  [ ] exceptions  [ ] closures  [ ] tail recursion  [ ] coroutines
[ ] reflection  [ ] subtyping  [x] multiple inheritance  [ ] operator overloading
[ ] algebraic datatypes  [ ] recursive types  [ ] polymorphic types
[ ] covariant array typing  [ ] monads  [ ] dependent types
[ ] infix operators  [x] nested comments  [x] multi-line strings  [ ] regexes
[ ] call-by-value  [ ] call-by-name  [ ] call-by-reference  [ ] call-cc

The following philosophical objections apply:
[ ] Programmers should not need to understand category theory to write "Hello, World!"
[ ] Programmers should not develop RSI from writing "Hello, World!"
[ ] The most significant program written in your language is its own compiler
[x] The most significant program written in your language isn't even its own compiler
[ ] No language spec
[x] "The implementation is the spec"
   [ ] The implementation is closed-source  [ ] covered by patents  [ ] not owned by you
[ ] Your type system is unsound  [ ] Your language cannot be unambiguously parsed
   [ ] a proof of same is attached
   [ ] invoking this proof crashes the compiler
[ ] The name of your language makes it impossible to find on Google
[x] Interpreted languages will never be as fast as C
[ ] Compiled languages will never be "extensible"
[ ] Writing a compiler that understands English is AI-complete
[ ] Your language relies on an optimization which has never been shown possible
[x] There are less than 100 programmers on Earth smart enough to use your language
[ ] ____________________________ takes exponential time
[ ] ____________________________ is known to be undecidable

Your implementation has the following flaws:
[x] CPUs do not work that way
[ ] RAM does not work that way
[ ] VMs do not work that way
[ ] Compilers do not work that way
[x] Compilers cannot work that way
[ ] Shift-reduce conflicts in parsing seem to be resolved using rand()
[x] You require the compiler to be present at runtime
[x] You require the language runtime to be present at compile-time
[x] Your compiler errors are completely inscrutable
[ ] Dangerous behavior is only a warning
[ ] The compiler crashes if you look at it funny
[x] The VM crashes if you look at it funny  (see example below) 
[ ] You don't seem to understand basic optimization techniques
[ ] You don't seem to understand basic systems programming
[ ] You don't seem to understand pointers
[ ] You don't seem to understand functions

Additionally, your marketing has the following problems:
[x] Unsupported claims of increased productivity
[ ] Unsupported claims of greater "ease of use"
[ ] Obviously rigged benchmarks
   [ ] Graphics, simulation, or crypto benchmarks where your code just calls
       handwritten assembly through your FFI
   [ ] String-processing benchmarks where you just call PCRE
   [ ] Matrix-math benchmarks where you just call BLAS
[x] Noone really believes that your language is faster than:
    [x] assembly  [x] C  [x] FORTRAN  [x] Java  [x] Ruby  [ ] Prolog
[ ] Rejection of orthodox programming-language theory without justification
[ ] Rejection of orthodox systems programming without justification
[ ] Rejection of orthodox algorithmic theory without justification
[ ] Rejection of basic computer science without justification

Taking the wider ecosystem into account, I would like to note that:
[ ] Your complex sample code would be one line in: _______________________
[ ] We already have an unsafe imperative language
[ ] We already have a safe imperative OO language
[ ] We already have a safe statically-typed eager functional language
[ ] You have reinvented Lisp but worse
[ ] You have reinvented Javascript but worse
[ ] You have reinvented Java but worse
[ ] You have reinvented C++ but worse
[ ] You have reinvented PHP but worse
[ ] You have reinvented PHP better, but that's still no justification
[x] You have reinvented Brainfuck but non-ironically

In conclusion, this is what I think of you:
[x] You have some interesting ideas, but this won't fly.
[ ] This is a bad language, and you should feel bad for inventing it.
[ ] Programming in this language is an adequate punishment for inventing it.

examples

"The VM crashes if you look at it funny":
user=> (defmacro re2 [x] (str "a" ~x))
#'user/re2
user=> (re2 1)
java.lang.IllegalStateException: Var clojure.core/unquote is unbound. (NO_SOURCE_FILE:0)
(only few people on Earth understand this error and actually no one of them understands why this error is not presented by compiler while defmacro)

Tuesday, October 11, 2011

New Python simple http request library

Where

http://docs.python-requests.org/en/latest


What and why

A successful attempt at simplifying HTTP requests in python.
Full support for cookies, headers, HEAD method and sessions (use of with block).
Code looks simple and clean (can't think of better complement).


Code example

>>> r = requests.get('https://api.github.com', auth=('user', 'pass'))
>>> r.status_code
204
>>> r.headers['content-type']
'application/json'
>>> print r.cookies
{'requests-is': 'awesome'}

Hooks

There are hooks available. One can have a function called pre-request or post-request.
http://docs.python-requests.org/en/latest/user/advanced/#event-hooks


Recommendations

This library is used internally at Twitter

Friday, September 16, 2011

No plugins in IE10 in Metro (smartphone) mode

http://www.infoq.com/news/2011/09/Metro-Plug-ins

Microsoft's IE 10 in Metro (smartphone) mode will not feature any plugins (not even Silverlight). It will only work with HTML5.

Actually this means that Silverlight is dead and Flash is rapidly drowning, despite late iPhone success.

Tuesday, July 19, 2011

The Baseball of Greed

Apple deals massive patent blow to HTC, Android in serious trouble | ZDNet

All right, there you have it. Patents just made Android die. Did it? Well.. at least in the US.

Now Europe has it's chance to outgrow USA technically. We don't have absurd laws that let one company basically smash other legitimate business with a Baseball of Greed.

Now I'll never buy anything from Apple not only for bad usability and aesthetic reasons, but also for moral ones. Any Apple user is from now on an enemy of free market!