четверг, 9 октября 2014 г.

Баг на баге и багом погоняет :-)

Из исходников Flume

  1. // (1) At the time of this writing, Hadoop has a bug which causes the
  2. // non-native gzip implementation to create invalid gzip files when
  3. // finish() and resetState() are called. See HADOOP-8522.
  4. //
  5. // (2) Even if HADOOP-8522 is fixed, the JDK GZipInputStream is unable
  6. // to read multi-member (concatenated) gzip files. See this Sun bug:
  7. // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4691425

понедельник, 7 апреля 2014 г.

Google App Engine печаль :(


Захотел наконец то сделать что-нибудь полезное на Google App Engine.
Самое полезное - это заставить его читать stream с моей IP камеры и писать видео в
Google Cloud Storage. Казалось бы ничего солжного:

response = urllib2.urlopen("http://myhost/videostream.asf?user=guest&pwd=guest&resolution=64")

block_size = 1024
while True:
     try:
       buffer = response.read(block_size)
...
Но Гугл оказался хитер. Ибо негоже это, держать персистент соединение со всякими там непорядочными хостами, да еще за бесплатно. От лукавого это.
Оказывается в App Engine своя реализация механизма URL Fetch, и поверх неё работают  urllib, urllib2httplib и все остальные сетевые товарищи. И как не старайся, а вычитать и сохранить stream не получится. Т.к URL Fetch не отдаст управление, пока не вычитает весь контент, а как известно у потока нет конца.

Опечален. Хотелось бесплатно.

вторник, 4 марта 2014 г.

Сериализация java bean в JSON

Давно задумывался над сериализацией JSON в java сущности и обратно.
Чтобы красиво, грациозно, и главное - производительно. Еще одно требование, чтобы сериализация производилась в строки, это наиболее универсальный формат для межсистемного взаимодействия. Пo этой причине Protobuf не рассматривал. Как правило использовал org.codehaus.jettison.json.JSONObject и ручную сериализацию. Внутри него используется LinkedHashMap поэтому операции с полями происходят быстро.

public class Geo
{

    private static final String LAT_FIELD = "lat";
    private static final String LON_FIELD = "lon";

    private float lat;
    private float lon;

    public String toJSON()
    {
        JSONObject json = new JSONObject();

        try {
            json.put(LAT_FIELD, lat);
            json.put(LON_FIELD, lon);
        } catch (JSONException e) {
            LOG.error("Cannot convert Geo object into json.", e);
        }

        return json.toString();
    }


    public static Geo fromJSON(final String json) throws JSONException
    {
        JSONObject jsonObject = new JSONObject(json);
        Geo geo = new Geo();

        geo.setLon((float) jsonObject.optDouble(LON_FIELD, Float.NaN));
        geo.setLat((float) jsonObject.optDouble(LAT_FIELD, Float.NaN));

        return geo;
    }
}


Надо ли говорить, что при большом количестве полей, такой подход адски неудобен.
Не красиво и трудозатратно, зато сносно, с точки зрения производительности, плюс поддержка валидации.
Всегда знал о такой штуке как com.google.gson.Gson но обходил его стороной, т.к он использует рефлексию, казалось что это снизит производительность.
Но красота использования Gson,

public class Geo
{
    private float lat;
    private float lon;

    public String toJSON()
    {
        Gson gson = new Gson();
        return gson.toJson(this);
    }

    public static Geo fromJSON(final String json)
    {
        Gson gson = new Gson();
        return gson.fromJson(json, Geo.class);
    }
}

...и безобразность ручной сериализации не давали покоя.
Решил на днях замерить производительность этих двух подходов.
Всё как всегда, цикл на миллион, и время в наносекундах.

Результаты:

Сериализация сущности в строку
Gson              4088893178
JSONObject  4543766682

Десериализация из строки:
Gson              2728182025
JSONObject  4180603421

Приятно удивлен производительностью Gson, оказывается в некоторых случаях она в полтора раза выше. Радости нет предела. Теперь буду пользоваться им.