Проблемы производительности WCF + Gzip - PullRequest
0 голосов
/ 01 августа 2011

У меня есть служба WCF, которая возвращает тип контента 'application / x-gzip', который, по сути, выглядит как XML / Json, сжатый с помощью Gzip.Я реализовал GzipMessageEncoder и CustomBinding, как описано по следующей ссылке Карлоса Фигейры:

http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/8c3eafae-b6a1-441f-85ef-90721d941a1a

Для данных, которые возвращает мой сервис, я использую базовую концепцию сетки с JSON, котораяразделяет схему и использует строку [] для каждой строки, чтобы сохранить компактность:

[DataContract]
[KnownType(typeof(JsonContract))]
[KnownType(typeof(ColumnDefinition))]
public class JsonContract
{
    [DataMember]
    public List<ColumnDefinition> Schema { get; set; }

    [DataMember]
    public List<String[]> Rows { get; set; }
}

public class Service : IGzipTest
{
    public JsonContract HttpRequest() 
    {
        // return json data
    }
}

Gzip работает нормально, но я думаю, что производительность на моем клиенте низкая / противоречивая, используя ChannelFactory:

    private ChannelFactory<T> CreateFactory<T>(CustomBinding binding, string endpoint)
    {
        EndpointAddress _endpoint = new EndpointAddress(endpoint);
        ChannelFactory<T> _factory = new ChannelFactory<T>(binding, _endpoint);

        _factory.Endpoint.Behaviors.Add(new WebHttpBehavior());

        return _factory;
    }

Вот как я запускаю службу:

    static string baseAddress = "http://" + Dns.GetHostName() + ":4050/ZipTest";
    static ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress));

    protected void Application_Start(object sender, EventArgs e)
    {
        ThreadPool.SetMinThreads(Environment.ProcessorCount, 9); 

        host.AddServiceEndpoint(typeof(IGzipTest), 
            GzipMapper.GetBinding(), "").Behaviors.Add(new WebHttpBehavior()); 

        host.Open();
    }

При загрузке ~ 512 КБ на ~ 1 МБ данных (то есть после сжатия), это мои результаты производительности на отдельных последовательных тестах:

   1st Request: 4439ms
   2nd Request: 19029ms

   ..and so on

Кажется, что каждый второй звонок в службу занимает примерно 4-5 раз дольше.Даже 4000 мс кажется длинным только для 512 КБ на 1 МБ данных, поэтому мне интересно, что может быть не так.

Например, если я загружаю сам файл .gz из браузера с использованием метода [WebGet], это занимает не более секунды, потому что я в худшем случае набираю 400-500 Кбит / с.

1 Ответ

2 голосов
/ 02 сентября 2011

Я видел подобные колебания, и они были вызваны, по крайней мере, об этом я сейчас думаю, чрезмерным использованием памяти GzipMessageEncoder и буферизованным TransferMode, который используется по умолчанию.Buffered TransferMode использует BufferManagers, которые могут привести к серьезным проблемам с памятью и вызывать для меня исключения OutOfMemoryException.

Какими бы ни были точные причины, я исправил это, а также значительно уменьшил потребление памяти и нагрузку на процессор как серверов, так и клиентов на

  1. Как избавиться от GzipMessageEncoder, см. wcf условное сжатие
  2. Переключение на потоковый TransferMode, см. Как я могу предотвратить BufferManager / PooledBufferManager в моем клиентском приложении WCF оттратить память?
...