Pergunta

Anteriormente, perguntei ao pergunta.

O problema é que as demandas da nossa estrutura de arquivos são muito altas.

Por exemplo, estamos tentando criar um contêiner com até 4500 arquivos e dados de 500 MB.

A estrutura de arquivo deste contêiner consiste em

  • Sqlite db (abaixo de 1 MB)
  • Arquivo XML baseado em texto
  • Imagens dentro de uma estrutura de pastas dinâmica que compõe o restante dos 4.500 arquivos

  • Após a criação inicial, os arquivos de imagens são lidos apenas com exceção da exclusão.

  • O pequeno banco de dados é usado regularmente quando o contêiner é acessado.

Alcatrão, zíper e coisas são muito lentos (mesmo com 0 compressão). Slow é subjetivo, eu sei, mas, para não ser um recipiente desse tamanho é superior a 20 segundos.

Alguma ideia?

Foi útil?

Solução

Três coisas.

1) O que Timothy Walters disse que está certo, vou entrar em mais detalhes.

2) 4500 arquivos e 500 MB de dados são simplesmente muitos dados e gravações de disco. Se você está operando em todo o conjunto de dados, será lento. Apenas I/S verdade.

3) Como outros mencionaram, não há detalhes no caso de uso.

Se assumirmos apenas um cenário de acesso aleatório, o que Timothy diz que está praticamente morto e a implementação é direta.

Em poucas palavras, aqui está o que você faz.

Você concatena todos os arquivos em um único blob. Enquanto você os concorda, você rastreia o nome do arquivo, o comprimento do arquivo e o deslocamento que o arquivo inicia dentro da blob. Você escreve essas informações em um bloco de dados, classificado pelo nome. Vamos chamar isso de Índice ou bloco de TOC.

Em seguida, então você concatena os dois arquivos juntos. No caso simples, você tem o bloco TOC primeiro e depois o bloco de dados.

Quando você deseja obter dados deste formato, pesquise no TOC para o nome do arquivo, pegue o deslocamento desde o início do bloco de dados, adicione o tamanho do bloco TOC e leia o arquivo de dados File_Length. Simples.

Se você quiser ser inteligente, pode colocar o TOC no final do arquivo BLOB. Em seguida, anexa no final, o deslocamento para o início do TOC. Em seguida, você está até o final do arquivo, backup de 4 ou 8 bytes (dependendo do tamanho do seu número), pegue esse valor e mais longe até o início do seu TOC. Então você voltará à estaca zero. Você faz isso para não precisar reconstruir o arquivo duas vezes no início.

Se você colocar seu TOC em blocos (digamos 1k byte de tamanho), poderá executar facilmente uma pesquisa binária no TOC. Basta preencher cada bloco com as entradas de informações do arquivo e, quando você ficar sem quarto, escreva um marcador, pad com zeros e avançar para o próximo bloco. Para fazer a pesquisa binária, você já sabe o tamanho do TOC, começa no meio, leia o primeiro nome do arquivo e vá a partir daí. Em breve, você encontrará o bloco e depois lerá no bloco e o digitaliza para o arquivo. Isso o torna eficiente para ler sem ter todo o TOC em RAM. O outro benefício é que o bloqueio requer menos atividade em disco do que um esquema encadeado como alcatrão (onde você precisa rastejar o arquivo para encontrar alguma coisa).

Eu sugiro que você também preencha os arquivos para bloquear o tamanho, discos como trabalhos com blocos de dados de tamanho normal, isso também não é difícil.

Atualizar isso sem reconstruir a coisa toda é difícil. Se você deseja um sistema de contêiner atualizável, também pode procurar alguns dos designs mais simples do sistema de arquivos, porque é isso que você está realmente procurando nesse caso.

Quanto à portabilidade, sugiro que você armazene seus números binários em ordem de rede, pois a maioria das bibliotecas padrão possui rotinas para lidar com esses detalhes para você.

Outras dicas

Como você parece estar fazendo operações arbitrárias do sistema de arquivos em seu contêiner (por exemplo, criação, exclusão de novos arquivos no contêiner, substituindo arquivos existentes, anexando), acho que você deve optar por algum tipo de sistema de arquivos. Alocar um arquivo grande e, em seguida, crie uma estrutura de sistema de arquivos.

Existem várias opções para o sistema de arquivos disponíveis: para Berkeley UFS e Linux Ext2/ext3, existem bibliotecas de modo de usuário disponíveis. Também pode ser possível encontrar uma implementação de gordura em algum lugar. Certifique -se de entender a estrutura do sistema de arquivos e escolha um que permita estender - eu sei que o EXT2 é bastante fácil de estender (por outro grupo de blocos), e a gordura é difícil de estender (precisam anexar a gordura).

Como alternativa, você pode colocar um formato de disco virtual, mas abaixo do sistema de arquivos, permitindo o remapeamento arbitrário de blocos. Em seguida, os blocos "gratuitos" do sistema de arquivos não precisam aparecer no disco e você pode alocar o disco virtual muito maior que o arquivo de contêiner real.

Trabalhando na suposição de que você só precisará de acesso somente leitura aos arquivos, por que não apenas mesclar todos eles e ter um segundo arquivo "índice" (ou um índice no cabeçalho) que informa o nome do arquivo, inicie posição e comprimento. Tudo o que você precisa fazer é procurar o ponto de partida e ler o número correto de bytes. O método variará dependendo do seu idioma, mas é bastante direto na maioria deles.

A parte mais difícil se torna criando seu arquivo de dados + índice, e mesmo isso é bastante básico!

Uma imagem de disco ISO pode fazer o truque. Ele deve ser capaz de sustentar muitos arquivos com facilidade e é suportado por muitas peças de software em todos os principais sistemas operacionais.

Primeiro, obrigado por expandir sua pergunta, ajuda muito a fornecer melhores respostas.

Dado que você precisará de um banco de dados SQLite de qualquer maneira, você já analisou o desempenho de colocar tudo no banco de dados? Minha experiência é baseada no SQL Server 2000/2005/2008, por isso não tenho certeza dos recursos do SQLite, mas tenho certeza de que será uma opção muito rápida para procurar registros e obter os dados, enquanto ainda permite deletar e/ou opções de atualização.

Normalmente, eu não recomendaria colocar arquivos dentro do banco de dados, mas, dado que o tamanho total de todas as imagens é de cerca de 500 MB para 4500 imagens que você está analisando um pouco mais de 100k por imagem, certo? Se você estiver usando um caminho dinâmico para armazenar as imagens, em um banco de dados um pouco mais normalizado, você pode ter uma tabela "ImagePaths" que mapeia cada caminho para um ID, pode procurar imagens com esse pathid e carregar os dados do Coluna BLOB conforme necessário.

O (s) arquivo (s) XML também pode estar no banco de dados SQLite, que fornece um único 'arquivo de dados' para o seu aplicativo que pode se mover entre o Windows e o OSX sem problemas. Você pode simplesmente confiar no seu mecanismo sqlite para fornecer o desempenho e a compatibilidade necessários.

Como você otimiza depende do seu uso, por exemplo, se você precisar frequentemente obter todas as imagens em um determinado caminho, ter um pathid (como um número inteiro de desempenho) seria rápido, mas se você está mostrando todas as imagens que iniciam Com "A" e simplesmente mostrar o caminho como uma propriedade, então um índice na coluna Imagename seria mais útil.

Estou um pouco preocupado, porém, que isso soa como otimização prematura, pois você realmente precisa encontrar uma solução que funcione 'rápido o suficiente', abstrair a mecânica dela para que seu aplicativo (ou ambos os aplicativos se você tiver versões Mac e PC) use Um repositório simples ou similar e você pode alterar o método de armazenamento/recuperação à vontade, sem nenhuma implicação no seu aplicativo.

Verificar Sistema de arquivos sólidos - Parece ser o que você precisa.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top