move repo gmio-benchmarks inside gmio

This commit is contained in:
Hugues Delorme 2015-09-01 17:01:38 +02:00
parent 5a9847f82b
commit 2f6af3ed26
7 changed files with 968 additions and 2 deletions

View File

@ -20,7 +20,7 @@ include(CheckFunctionExists)
include(CheckCSourceCompiles)
include(CheckTypeSize)
project(gmio C)
project(gmio)
set(GMIO_VERSION_MAJOR 0)
set(GMIO_VERSION_MINOR 1)
set(GMIO_VERSION_PATCH 0)
@ -36,6 +36,7 @@ endif ()
# Options
option(GMIO_BUILD_STRICT_C90 "Build with strict conformance to C90 standard" OFF)
option(GMIO_BENCHMARKS "Build performance benchmarks for the gmio library" OFF)
# Find bit size of the target architecture
math(EXPR GMIO_TARGET_ARCH_BIT_SIZE "8 * ${CMAKE_SIZEOF_VOID_P}")
@ -185,9 +186,11 @@ endif()
add_subdirectory(src)
add_subdirectory(tests)
add_subdirectory(doc)
if(GMIO_BENCHMARKS)
add_subdirectory(benchmarks)
endif()
# Examples:
# cmake ../.. -DCMAKE_INSTALL_PREFIX=../../gcc-linux64 -DCMAKE_BUILD_TYPE=Debug -DCMAKE_DEBUG_POSTFIX=.debug
# cmake ../.. -DCMAKE_INSTALL_PREFIX=../../gcc-linux64 -DCMAKE_BUILD_TYPE=Release -DCMAKE_RELEASE_POSTFIX=.release
# make VERBOSE=1 or cmake -DCMAKE_VERBOSE_MAKEFILE=TRUE

117
benchmarks/CMakeLists.txt Normal file
View File

@ -0,0 +1,117 @@
#############################################################################
## gmio
## Copyright Fougue (2 Mar. 2015)
## contact@fougue.pro
##
## This software is a reusable library whose purpose is to provide complete
## I/O support for various CAD file formats (eg. STL)
##
## This software is governed by the CeCILL-B license under French law and
## abiding by the rules of distribution of free software. You can use,
## modify and/ or redistribute the software under the terms of the CeCILL-B
## license as circulated by CEA, CNRS and INRIA at the following URL
## "http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html".
#############################################################################
# Options
option(GMIO_BENCHMARKS_ASSIMP "Build benchmark for Assimp" ON)
option(GMIO_BENCHMARKS_OPENCASCADE "Build benchmark for OpenCascade" ON)
set(ASSIMP_DIR ${CMAKE_SOURCE_DIR} CACHE PATH "Directory where the Assimp library resides")
set(OPENCASCADE_DIR ${CMAKE_SOURCE_DIR} CACHE PATH "Directory where the OpenCascade library resides")
# List source files in commons/
file(GLOB COMMONS_FILES commons/*)
set(COMMONS_FILES ${COMMONS_FILES})
include_directories(${CMAKE_SOURCE_DIR}/src)
include_directories(${CMAKE_BINARY_DIR}/src/gmio_core) # For cmake generated headers
link_directories(${CMAKE_BINARY_DIR}/src)
find_library(GMIO_LIBPATH gmio HINTS ${CMAKE_BINARY_DIR}/src)
get_filename_component(GMIO_LIB_BASENAME ${GMIO_LIBPATH} NAME_WE)
if ("${GMIO_LIB_BASENAME}" STREQUAL "")
set(GMIO_LIB_BASENAME "gmio")
endif()
link_libraries(${GMIO_LIB_BASENAME})
if(CMAKE_COMPILER_IS_GNUCC)
link_libraries(m) # -lm
endif()
add_executable(bench_gmio bench_gmio/main.c ${COMMONS_FILES})
function(get_msvc_vernum outVerNum)
if(MSVC60)
set(${outVerNum} 6 PARENT_SCOPE)
elseif(MSVC70)
set(${outVerNum} 7 PARENT_SCOPE)
elseif(MSVC80)
set(${outVerNum} 8 PARENT_SCOPE)
elseif(MSVC90)
set(${outVerNum} 9 PARENT_SCOPE)
elseif(MSVC10)
set(${outVerNum} 10 PARENT_SCOPE)
elseif(MSVC11)
set(${outVerNum} 11 PARENT_SCOPE)
elseif(MSVC12)
set(${outVerNum} 12 PARENT_SCOPE)
endif()
endfunction()
if(GMIO_BENCHMARKS_ASSIMP)
add_executable(bench_assimp bench_assimp/main.cpp ${COMMONS_FILES})
# Note: we could use target_include_directories() but it's available in cmake > v2.8.10
set_property(
TARGET bench_assimp
APPEND PROPERTY INCLUDE_DIRECTORIES ${ASSIMP_DIR}/include)
# Libs
find_library(LIBPATH_ASSIMP assimp ${ASSIMP_DIR}/lib64)
target_link_libraries(bench_assimp ${LIBPATH_ASSIMP})
endif()
if(GMIO_BENCHMARKS_OPENCASCADE)
add_executable(bench_occ
bench_occ/main.cpp
${CMAKE_SOURCE_DIR}/src/gmio_support/stl_occ.cpp
${COMMONS_FILES})
# TODO: define only if target arch is 64b
# Note: we could use target_compile_definitions() but it's available in cmake > v2.8.10
set_property(
TARGET bench_occ
APPEND PROPERTY COMPILE_DEFINITIONS _OCC64)
if(WIN32)
set_property(
TARGET bench_occ
APPEND PROPERTY COMPILE_DEFINITIONS WNT)
elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
set_property(
TARGET bench_occ
APPEND PROPERTY COMPILE_DEFINITIONS
HAVE_CONFIG_H HAVE_FSTREAM HAVE_IOSTREAM HAVE_IOMANIP HAVE_LIMITS_H)
endif()
# Note: we could use target_include_directories() but it's available in cmake > v2.8.10
set_property(
TARGET bench_occ
APPEND PROPERTY INCLUDE_DIRECTORIES ${OPENCASCADE_DIR}/inc)
# Libs
if(MSVC)
set(_MSVC_VERNUM_ 0) # Init
get_msvc_vernum(_MSVC_VERNUM_)
set(OPENCASCADE_LIBDIR ${OPENCASCADE_DIR}/win64/vc${_MSVC_VERNUM_}/lib)
elseif((${CMAKE_SYSTEM_NAME} MATCHES "Linux") AND CMAKE_COMPILER_IS_GNUCXX)
set(OPENCASCADE_LIBDIR ${OPENCASCADE_DIR}/lin64/gcc/lib)
endif()
message(STATUS ${OPENCASCADE_LIBDIR})
find_library(LIBPATH_OPENCASCADE_TKERNEL TKernel ${OPENCASCADE_LIBDIR})
find_library(LIBPATH_OPENCASCADE_TKMATH TKMath ${OPENCASCADE_LIBDIR})
find_library(LIBPATH_OPENCASCADE_TKSTL TKSTL ${OPENCASCADE_LIBDIR})
target_link_libraries(
bench_occ
${LIBPATH_OPENCASCADE_TKERNEL}
${LIBPATH_OPENCASCADE_TKMATH}
${LIBPATH_OPENCASCADE_TKSTL})
endif()

View File

@ -0,0 +1,365 @@
/****************************************************************************
** gmio benchmarks
** Copyright Fougue (2 Mar. 2015)
** contact@fougue.pro
**
** This software provides performance benchmarks for the gmio library
** (https://github.com/fougue/gmio)
**
** This software is governed by the CeCILL-B license under French law and
** abiding by the rules of distribution of free software. You can use,
** modify and/ or redistribute the software under the terms of the CeCILL-B
** license as circulated by CEA, CNRS and INRIA at the following URL
** "http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html".
****************************************************************************/
#include "../commons/bench_tools.h"
#include <assimp/Importer.hpp>
#include <assimp/Exporter.hpp>
#include <assimp/scene.h>
#include <assimp/cimport.h>
#include <gmio_core/error.h>
#include <gmio_stl/stl_io.h>
#include <cstring>
#include <iostream>
static unsigned totalTriangleCount(const aiScene* scene)
{
unsigned int meshnum = 0;
for (unsigned int i = 0; i < scene->mNumMeshes; ++i) {
for (unsigned int j = 0; j < scene->mMeshes[i]->mNumFaces; ++j)
++meshnum;
}
return meshnum;
}
GMIO_INLINE void copy_gmio_stl_coords(
aiVector3D* vec3, const gmio_stl_coords_t& coords)
{
*vec3 = *((aiVector3D*)&coords);
}
GMIO_INLINE void copy_aiVector3D(
gmio_stl_coords_t* coords, const aiVector3D& vec3)
{
*coords = *((gmio_stl_coords_t*)&vec3);
}
namespace BenchmarkAssimp {
Assimp::Importer* globalImporter = NULL;
const aiScene* globalScene = NULL;
static void bmk_import(const char* filepath)
{
Assimp::Importer* importer = globalImporter;
const aiScene* scene = importer->ReadFile(filepath, 0);
if (aiGetErrorString() != NULL)
std::cerr << aiGetErrorString() << std::endl;
if (scene == NULL || scene->mNumMeshes <= 0) {
std::cerr << "Failed to read file " << filepath << std::endl;
}
globalScene = scene;
std::cout << "BenchAssimp, triCount = "
<< totalTriangleCount(scene) << std::endl;
}
static void bmk_export_stla(const char* filepath)
{
Assimp::Exporter exporter;
// for (std::size_t i = 0; i < exporter.GetExportFormatCount(); ++i) {
// std::cout << exporter.GetExportFormatDescription(i)->id << " "
// << exporter.GetExportFormatDescription(i)->description
// << std::endl;
// }
exporter.Export(globalScene, "stl", filepath);
}
static void bmk_export_stlb(const char* filepath)
{
Assimp::Exporter exporter;
exporter.Export(globalScene, "stlb", filepath);
}
static void bmk_main(const char* filepath)
{
BenchmarkAssimp::globalImporter = new Assimp::Importer;
benchmark(BenchmarkAssimp::bmk_import,
"Assimp::Importer::ReadFile()",
filepath);
benchmark(BenchmarkAssimp::bmk_export_stla,
"Assimp::Exporter::Export(STL_ASCII)",
"__file_bench_assimp.stla");
benchmark(BenchmarkAssimp::bmk_export_stlb,
"Assimp::Exporter::Export(STL_BINARY)",
"__file_bench_assimp.stlb");
delete BenchmarkAssimp::globalImporter;
BenchmarkAssimp::globalImporter = NULL;
}
} // namespace BenchAssimp
namespace BenchmarkGmio {
struct aiSceneHelper
{
aiScene* scene;
uint32_t totalTriangleCount;
int hasToCountTriangle;
};
aiSceneHelper globalSceneHelper = { 0 };
static void allocate_stl_scene(aiScene* pScene)
{
// allocate one mesh
pScene->mNumMeshes = 1;
pScene->mMeshes = new aiMesh*[1];
aiMesh* pMesh = pScene->mMeshes[0] = new aiMesh();
pMesh->mMaterialIndex = 0;
// allocate a single node
pScene->mRootNode = new aiNode();
pScene->mRootNode->mNumMeshes = 1;
pScene->mRootNode->mMeshes = new unsigned int[1];
pScene->mRootNode->mMeshes[0] = 0;
}
static void func_ascii_begin_solid(
void* cookie, size_t stream_size, const char* solid_name)
{
aiSceneHelper* helper = (aiSceneHelper*)cookie;
helper->hasToCountTriangle = 1; // true
aiScene* pScene = helper->scene;
allocate_stl_scene(pScene);
aiMesh* pMesh = pScene->mMeshes[0];
std::strcpy(pScene->mRootNode->mName.data, solid_name);
pScene->mRootNode->mName.length = std::strlen(solid_name);
// try to guess how many vertices we could have
// assume we'll need 200 bytes for each face
const unsigned facetSize = 200u;
pMesh->mNumFaces =
std::max(1u, static_cast<unsigned>(stream_size) / facetSize);
pMesh->mNumVertices = pMesh->mNumFaces * 3;
pMesh->mVertices = new aiVector3D[pMesh->mNumVertices];
pMesh->mNormals = new aiVector3D[pMesh->mNumVertices];
}
static void binary_begin_solid(
void* cookie, uint32_t tri_count, const gmio_stlb_header_t* /*header*/)
{
aiSceneHelper* helper = (aiSceneHelper*)cookie;
helper->hasToCountTriangle = 0; // false
aiScene* pScene = helper->scene;
allocate_stl_scene(pScene);
aiMesh* pMesh = pScene->mMeshes[0];
pScene->mRootNode->mName.Set("<STL_BINARY>");
pMesh->mNumFaces = tri_count;
pMesh->mNumVertices = pMesh->mNumFaces*3;
pMesh->mVertices = new aiVector3D[pMesh->mNumVertices];
pMesh->mNormals = new aiVector3D[pMesh->mNumVertices];
}
static void add_triangle(
void* cookie, uint32_t tri_id, const gmio_stl_triangle_t* triangle)
{
aiSceneHelper* helper = (aiSceneHelper*)cookie;
aiScene* pScene = helper->scene;
aiMesh* pMesh = pScene->mMeshes[0];
if (pMesh->mNumFaces <= tri_id) {
std::cout << "add_triangle() reallocate" << std::endl;
// need to resize the arrays, our size estimate was wrong
#if 0
unsigned int iNeededSize = (unsigned int)(sz-mBuffer) / pMesh->mNumFaces;
if (iNeededSize <= 160)
iNeededSize >>= 1; // prevent endless looping
unsigned int add = (unsigned int)((mBuffer+fileSize)-sz) / iNeededSize;
#endif
unsigned int add = pMesh->mNumFaces;
add += add >> 3; // add 12.5% as buffer
const unsigned int iNeededSize = (pMesh->mNumFaces + add)*3;
aiVector3D* pv = new aiVector3D[iNeededSize];
memcpy(pv, pMesh->mVertices, pMesh->mNumVertices*sizeof(aiVector3D));
delete[] pMesh->mVertices;
pMesh->mVertices = pv;
pv = new aiVector3D[iNeededSize];
memcpy(pv, pMesh->mNormals, pMesh->mNumVertices*sizeof(aiVector3D));
delete[] pMesh->mNormals;
pMesh->mNormals = pv;
pMesh->mNumVertices = iNeededSize;
pMesh->mNumFaces += add;
}
aiVector3D* vp = &pMesh->mVertices[tri_id * 3];
aiVector3D* vn = &pMesh->mNormals[tri_id * 3];
copy_gmio_stl_coords(vn, triangle->normal);
*(vn+1) = *vn;
*(vn+2) = *vn;
copy_gmio_stl_coords(vp, triangle->v1);
copy_gmio_stl_coords(vp+1, triangle->v2);
copy_gmio_stl_coords(vp+2, triangle->v3);
if (helper->hasToCountTriangle)
++(helper->totalTriangleCount);
}
static void end_solid(void* cookie)
{
aiSceneHelper* helper = (aiSceneHelper*)cookie;
aiScene* pScene = helper->scene;
aiMesh* pMesh = pScene->mMeshes[0];
if (helper->hasToCountTriangle) {
pMesh->mNumFaces = helper->totalTriangleCount;
pMesh->mNumVertices = helper->totalTriangleCount * 3;
}
// now copy faces
pMesh->mFaces = new aiFace[pMesh->mNumFaces];
for (unsigned int i = 0, p = 0; i < pMesh->mNumFaces;++i) {
aiFace& face = pMesh->mFaces[i];
face.mIndices = new unsigned int[face.mNumIndices = 3];
for (unsigned int o = 0; o < 3;++o,++p) {
face.mIndices[o] = p;
}
}
// create a single default material, using a light gray diffuse color for
// consistency with other geometric types (e.g., PLY).
aiMaterial* pcMat = new aiMaterial;
aiString s;
s.Set(AI_DEFAULT_MATERIAL_NAME);
pcMat->AddProperty(&s, AI_MATKEY_NAME);
aiColor4D clrDiffuse(0.6f,0.6f,0.6f,1.0f);
pcMat->AddProperty(&clrDiffuse,1,AI_MATKEY_COLOR_DIFFUSE);
pcMat->AddProperty(&clrDiffuse,1,AI_MATKEY_COLOR_SPECULAR);
clrDiffuse = aiColor4D(0.05f,0.05f,0.05f,1.0f);
pcMat->AddProperty(&clrDiffuse,1,AI_MATKEY_COLOR_AMBIENT);
pScene->mNumMaterials = 1;
pScene->mMaterials = new aiMaterial*[1];
pScene->mMaterials[0] = pcMat;
}
static void get_triangle(
const void* cookie, uint32_t tri_id, gmio_stl_triangle_t* triangle)
{
const aiMesh* mesh = (const aiMesh*)cookie;
const aiFace& f = mesh->mFaces[tri_id];
// we need per-face normals. We specified aiProcess_GenNormals as
// pre-requisite for this exporter, but nonetheless we have to expect
// per-vertex normals.
aiVector3D nor;
if (mesh->mNormals) {
for (unsigned int a = 0; a < f.mNumIndices; ++a) {
nor += mesh->mNormals[f.mIndices[a]];
}
nor.Normalize();
}
copy_aiVector3D(&triangle->normal, nor);
#if 0
copy_aiVector3D(&triangle->normal, mesh->mNormals[f.mIndices[0]]);
#endif
copy_aiVector3D(&triangle->v1, mesh->mVertices[f.mIndices[0]]);
copy_aiVector3D(&triangle->v2, mesh->mVertices[f.mIndices[1]]);
copy_aiVector3D(&triangle->v3, mesh->mVertices[f.mIndices[2]]);
}
static void bmk_stl_read(const char* filepath)
{
gmio_stl_mesh_creator_t mesh_creator = { 0 };
mesh_creator.cookie = &globalSceneHelper;
mesh_creator.func_ascii_begin_solid = func_ascii_begin_solid;
mesh_creator.func_binary_begin_solid = binary_begin_solid;
mesh_creator.func_add_triangle = add_triangle;
mesh_creator.func_end_solid = end_solid;
const int error = gmio_stl_read_file(filepath, &mesh_creator, NULL);
if (error != GMIO_ERROR_OK)
printf("gmio error: 0x%X\n", error);
const aiScene* scene = globalSceneHelper.scene;
std::cout << "BenchGmio, triCount = "
<< totalTriangleCount(scene) << std::endl;
}
static void bmk_stl_write(const char* filepath, gmio_stl_format_t format)
{
const aiMesh* sceneMesh = globalSceneHelper.scene->mMeshes[0];
gmio_stl_mesh_t mesh = { 0 };
mesh.cookie = sceneMesh;
mesh.triangle_count = sceneMesh->mNumFaces;
mesh.func_get_triangle = get_triangle;
gmio_stl_write_options_t opts = { 0 };
opts.stla_float32_format = GMIO_FLOAT_TEXT_FORMAT_SHORTEST_UPPERCASE;
opts.stla_float32_prec = 7;
const int error = gmio_stl_write_file(format, filepath, &mesh, NULL, &opts);
if (error != GMIO_ERROR_OK)
printf("gmio error: 0x%X\n", error);
}
static void bmk_stla_write(const char* filepath)
{
bmk_stl_write(filepath, GMIO_STL_FORMAT_ASCII);
}
static void bmk_stlb_write_le(const char* filepath)
{
bmk_stl_write(filepath, GMIO_STL_FORMAT_BINARY_LE);
}
static void bmk_stlb_write_be(const char* filepath)
{
bmk_stl_write(filepath, GMIO_STL_FORMAT_BINARY_BE);
}
static void bmk_main(const char* filepath)
{
BenchmarkGmio::globalSceneHelper.scene = new aiScene;
BenchmarkGmio::globalSceneHelper.totalTriangleCount = 0;
benchmark(BenchmarkGmio::bmk_stl_read,
"gmio_stl_read()",
filepath);
benchmark(BenchmarkGmio::bmk_stla_write,
"gmio_stl_write(STL_ASCII)",
"__file_bench_gmio.stla");
benchmark(BenchmarkGmio::bmk_stlb_write_le,
"gmio_stl_write(STL_BINARY_LE)",
"__file_bench_gmio_le.stlb");
benchmark(BenchmarkGmio::bmk_stlb_write_be,
"gmio_stl_write(STL_BINARY_BE)",
"__file_bench_gmio_be.stlb");
delete BenchmarkGmio::globalSceneHelper.scene;
BenchmarkGmio::globalSceneHelper.scene = NULL;
}
} // namespace BenchmarkGmio
int main(int argc, char** argv)
{
if (argc > 1) {
benchmark_forward_list(BenchmarkAssimp::bmk_main, argc - 1, argv + 1);
benchmark_forward_list(BenchmarkGmio::bmk_main, argc - 1, argv + 1);
}
return 0;
}

View File

@ -0,0 +1,209 @@
/****************************************************************************
** gmio benchmarks
** Copyright Fougue (2 Mar. 2015)
** contact@fougue.pro
**
** This software provides performance benchmarks for the gmio library
** (https://github.com/fougue/gmio)
**
** This software is governed by the CeCILL-B license under French law and
** abiding by the rules of distribution of free software. You can use,
** modify and/ or redistribute the software under the terms of the CeCILL-B
** license as circulated by CEA, CNRS and INRIA at the following URL
** "http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html".
****************************************************************************/
#include <gmio_core/error.h>
#include <gmio_stl/stl_io.h>
#include "../commons/bench_tools.h"
#include <string.h>
typedef struct my_igeom
{
uint32_t facet_count;
} my_igeom_t;
static void dummy_process_triangle(
void* cookie,
uint32_t triangle_id,
const gmio_stl_triangle_t* triangle)
{
my_igeom_t* my_igeom = (my_igeom_t*)(cookie);
if (my_igeom != NULL)
++(my_igeom->facet_count);
}
static void bench_gmio_stl_read(const char* filepath)
{
my_igeom_t cookie = { 0 };
gmio_stl_mesh_creator_t mesh_creator = { 0 };
int error = GMIO_ERROR_OK;
mesh_creator.cookie = &cookie;
mesh_creator.func_add_triangle = dummy_process_triangle;
error = gmio_stl_read_file(filepath, &mesh_creator, NULL);
if (error != GMIO_ERROR_OK)
printf("gmio error: 0x%X\n", error);
}
static gmio_endianness_t to_byte_order(gmio_stl_format_t format)
{
switch (format) {
case GMIO_STL_FORMAT_BINARY_LE:
return GMIO_ENDIANNESS_LITTLE;
case GMIO_STL_FORMAT_BINARY_BE:
return GMIO_ENDIANNESS_BIG;
case GMIO_STL_FORMAT_ASCII:
case GMIO_STL_FORMAT_UNKNOWN:
return GMIO_ENDIANNESS_HOST;
}
return GMIO_ENDIANNESS_UNKNOWN;
}
enum { STL_TRIANGLE_ARRAY_SIZE = 512 };
typedef struct stl_readwrite_conv
{
gmio_transfer_t trsf;
gmio_stl_format_t in_format;
gmio_stl_format_t out_format;
gmio_stl_triangle_t triangle_array[STL_TRIANGLE_ARRAY_SIZE];
unsigned triangle_pos;
uint32_t total_triangle_count;
} stl_readwrite_conv_t;
static void readwrite_ascii_begin_solid(
void* cookie, size_t stream_size, const char* solid_name)
{
stl_readwrite_conv_t* rw_conv = (stl_readwrite_conv_t*)cookie;
gmio_stream_t* stream = &rw_conv->trsf.stream;
if (rw_conv->out_format == GMIO_STL_FORMAT_ASCII) {
stream->func_write(stream->cookie, "solid ", 1, 6);
stream->func_write(stream->cookie, solid_name, 1, strlen(solid_name));
stream->func_write(stream->cookie, "\n", 1, 1);
}
else {
/* For binary STL, facet count <- 0 because it cannot be known at this
* point. Header will be correctly rewritten at the end of the read
* procedure (in gmio_stl_mesh_creator::func_end_solid() callback)
*/
const gmio_endianness_t byte_order = to_byte_order(rw_conv->out_format);
gmio_stlb_write_header(stream, byte_order, NULL, 0);
}
}
static void readwrite_binary_begin_solid(
void* cookie, uint32_t tri_count, const gmio_stlb_header_t* header)
{
stl_readwrite_conv_t* rw_conv = (stl_readwrite_conv_t*)cookie;
gmio_stream_t* stream = &rw_conv->trsf.stream;
if (rw_conv->out_format == GMIO_STL_FORMAT_ASCII) {
stream->func_write(stream->cookie, "solid\n", 1, 6);
}
else {
const gmio_endianness_t byte_order = to_byte_order(rw_conv->out_format);
gmio_stlb_write_header(stream, byte_order, header, tri_count);
}
}
static void readwrite_get_triangle(
const void* cookie, uint32_t tri_id, gmio_stl_triangle_t* triangle)
{
const gmio_stl_triangle_t* tri_array = (const gmio_stl_triangle_t*)cookie;
*triangle = tri_array[tri_id];
}
static void stl_readwrite_flush_triangles(stl_readwrite_conv_t* rw_conv)
{
gmio_stl_mesh_t mesh = { 0 };
gmio_stl_write_options_t options = { 0 };
mesh.cookie = &rw_conv->triangle_array[0];
mesh.triangle_count = rw_conv->triangle_pos;
mesh.func_get_triangle = &readwrite_get_triangle;
options.stl_write_triangles_only = GMIO_TRUE;
options.stla_float32_format = GMIO_FLOAT_TEXT_FORMAT_SCIENTIFIC_LOWERCASE;
options.stla_float32_prec = 6;
gmio_stl_write(rw_conv->out_format, &rw_conv->trsf, &mesh, &options);
rw_conv->triangle_pos = 0;
}
static void readwrite_add_triangle(
void* cookie, uint32_t tri_id, const gmio_stl_triangle_t* triangle)
{
stl_readwrite_conv_t* rw_conv = (stl_readwrite_conv_t*)cookie;
if (rw_conv->triangle_pos >= STL_TRIANGLE_ARRAY_SIZE)
stl_readwrite_flush_triangles(rw_conv);
rw_conv->triangle_array[rw_conv->triangle_pos] = *triangle;
++(rw_conv->triangle_pos);
rw_conv->total_triangle_count = tri_id + 1;
}
static void readwrite_end_solid(void* cookie)
{
stl_readwrite_conv_t* rw_conv = (stl_readwrite_conv_t*)cookie;
gmio_stream_t* stream = &rw_conv->trsf.stream;
if (rw_conv->triangle_pos != 0)
stl_readwrite_flush_triangles(rw_conv);
if (rw_conv->out_format == GMIO_STL_FORMAT_ASCII) {
stream->func_write(stream->cookie, "endsolid", 1, 8);
}
else if (rw_conv->in_format == GMIO_STL_FORMAT_ASCII) {
const gmio_endianness_t byte_order = to_byte_order(rw_conv->out_format);
/* The total facet count has to be written because it wasn't known at
* the beginning of the read procedure */
stream->func_rewind(stream->cookie);
gmio_stlb_write_header(
stream, byte_order, NULL, rw_conv->total_triangle_count);
}
}
static void bench_gmio_stl_readwrite_conv(const char* filepath)
{
FILE* infile = fopen(filepath, "rb");
FILE* outfile = fopen("_readwrite_conv.stl", "wb");
gmio_transfer_t in_trsf = { 0 };
stl_readwrite_conv_t rw_conv = { 0 };
gmio_stl_mesh_creator_t mesh_creator = { 0 };
int error = GMIO_ERROR_OK;
/* rw_conv.out_format = GMIO_STL_FORMAT_BINARY_LE; */
rw_conv.out_format = GMIO_STL_FORMAT_ASCII;
if (infile != NULL) {
in_trsf.buffer = gmio_buffer_malloc(512 * 1024);
in_trsf.stream = gmio_stream_stdio(infile);
rw_conv.in_format = gmio_stl_get_format(&in_trsf.stream);
}
if (outfile != NULL) {
rw_conv.trsf.buffer = gmio_buffer_malloc(512 * 1024);
rw_conv.trsf.stream = gmio_stream_stdio(outfile);
}
mesh_creator.cookie = &rw_conv;
mesh_creator.func_ascii_begin_solid = &readwrite_ascii_begin_solid;
mesh_creator.func_binary_begin_solid = &readwrite_binary_begin_solid;
mesh_creator.func_add_triangle = &readwrite_add_triangle;
mesh_creator.func_end_solid = &readwrite_end_solid;
error = gmio_stl_read(&in_trsf, &mesh_creator);
gmio_buffer_deallocate(&in_trsf.buffer);
gmio_buffer_deallocate(&rw_conv.trsf.buffer);
if (error != GMIO_ERROR_OK)
printf("gmio error: 0x%X\n", error);
}
int main(int argc, char** argv)
{
if (argc > 1) {
benchmark_list(&bench_gmio_stl_read,
"gmio_stl_read_file()",
argc - 1, argv + 1);
benchmark_list(&bench_gmio_stl_readwrite_conv,
"gmio_stl_readwrite_conv()",
argc - 1, argv + 1);
}
return 0;
}

View File

@ -0,0 +1,130 @@
/****************************************************************************
** gmio benchmarks
** Copyright Fougue (2 Mar. 2015)
** contact@fougue.pro
**
** This software provides performance benchmarks for the gmio library
** (https://github.com/fougue/gmio)
**
** This software is governed by the CeCILL-B license under French law and
** abiding by the rules of distribution of free software. You can use,
** modify and/ or redistribute the software under the terms of the CeCILL-B
** license as circulated by CEA, CNRS and INRIA at the following URL
** "http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html".
****************************************************************************/
#include <OSD_Path.hxx>
#include <RWStl.hxx>
#include <StlMesh_Mesh.hxx>
#include <gmio_core/error.h>
#include <gmio_stl/stl_io.h>
#include <gmio_support/stl_occ.h>
#include "../commons/bench_tools.h"
namespace BenchmarkOcc {
Handle_StlMesh_Mesh stlMesh;
static void bmk_RWStl_ReadFile(const char* filepath)
{
stlMesh = RWStl::ReadFile(OSD_Path(filepath));
if (stlMesh.IsNull())
printf("RWStl::ReadFile(): null mesh\n");
}
static void bmk_RWStl_WriteAscii(const char* filepath)
{
if (!RWStl::WriteAscii(stlMesh, OSD_Path(filepath)))
printf("RWStl::WriteAscii() failure\n");
}
static void bmk_RWStl_WriteBinary(const char* filepath)
{
if (!RWStl::WriteBinary(stlMesh, OSD_Path(filepath)))
printf("RWStl::WriteBinary() failure\n");
}
static void bmk_main(const char* filepath)
{
benchmark(BenchmarkOcc::bmk_RWStl_ReadFile,
"RWStl::ReadFile()",
filepath);
benchmark(BenchmarkOcc::bmk_RWStl_WriteAscii,
"RWStl::WriteAscii",
"__file_bench_occ.stla");
benchmark(BenchmarkOcc::bmk_RWStl_WriteBinary,
"RWStl::WriteBinary",
"__file_bench_occ.stlb");
}
} // namespace BenchmarkOcc
namespace BenchmarkGmio {
Handle_StlMesh_Mesh stlMesh;
static void bmk_stl_read(const char* filepath)
{
stlMesh = new StlMesh_Mesh;
gmio_stl_mesh_creator_t mesh_creator = gmio_stl_occmesh_creator(stlMesh);
int error = gmio_stl_read_file(filepath, &mesh_creator, NULL);
if (error != GMIO_ERROR_OK)
printf("gmio error: 0x%X\n", error);
}
static void bmk_stl_write(const char* filepath, gmio_stl_format_t format)
{
const gmio_OccStlMeshDomain occMeshDomain(stlMesh);
const gmio_stl_mesh_t mesh = gmio_stl_occmesh(occMeshDomain);
gmio_stl_write_options_t opts = { 0 };
opts.stla_float32_format = GMIO_FLOAT_TEXT_FORMAT_SHORTEST_UPPERCASE;
opts.stla_float32_prec = 7;
const int error = gmio_stl_write_file(format, filepath, &mesh, NULL, &opts);
if (error != GMIO_ERROR_OK)
printf("gmio error: 0x%X\n", error);
}
static void bmk_stla_write(const char* filepath)
{
bmk_stl_write(filepath, GMIO_STL_FORMAT_ASCII);
}
static void bmk_stlb_write_le(const char* filepath)
{
bmk_stl_write(filepath, GMIO_STL_FORMAT_BINARY_LE);
}
static void bmk_stlb_write_be(const char* filepath)
{
bmk_stl_write(filepath, GMIO_STL_FORMAT_BINARY_BE);
}
static void bmk_main(const char* filepath)
{
benchmark(bmk_stl_read,
"gmio_stl_read()",
filepath);
benchmark(bmk_stla_write,
"gmio_stl_write(STL_ASCII)",
"__file_bench_gmio.stla");
benchmark(bmk_stlb_write_le,
"gmio_stl_write(STL_BINARY_LE)",
"__file_bench_gmio_le.stlb");
benchmark(bmk_stlb_write_be,
"gmio_stl_write(STL_BINARY_BE)",
"__file_bench_gmio_be.stlb");
}
} // namespace BenchmarkGmio
int main(int argc, char** argv)
{
if (argc > 1) {
benchmark_forward_list(BenchmarkOcc::bmk_main, argc - 1, argv + 1);
benchmark_forward_list(BenchmarkGmio::bmk_main, argc - 1, argv + 1);
}
return 0;
}

View File

@ -0,0 +1,106 @@
/****************************************************************************
** gmio benchmarks
** Copyright Fougue (2 Mar. 2015)
** contact@fougue.pro
**
** This software provides performance benchmarks for the gmio library
** (https://github.com/fougue/gmio)
**
** This software is governed by the CeCILL-B license under French law and
** abiding by the rules of distribution of free software. You can use,
** modify and/ or redistribute the software under the terms of the CeCILL-B
** license as circulated by CEA, CNRS and INRIA at the following URL
** "http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html".
****************************************************************************/
#include "bench_tools.h"
#include <stdio.h>
#ifdef WIN32
# include <windows.h>
# define BENCH_TIMER_WINDOWS
#else
# define BENCH_TIMER_LIBC
#endif
typedef struct bench_timer
{
#ifdef BENCH_TIMER_WINDOWS
LARGE_INTEGER start_time;
LARGE_INTEGER frequency;
#elif defined(BENCH_TIMER_LIBC)
clock_t start_tick;
#endif
} bench_timer_t;
void bench_timer_start(bench_timer_t* timer)
{
#ifdef BENCH_TIMER_WINDOWS
QueryPerformanceFrequency(&timer->frequency);
QueryPerformanceCounter(&timer->start_time);
#elif defined(BENCH_TIMER_LIBC)
timer->start_tick = clock();
#endif
}
int64_t bench_timer_elapsed_ms(const bench_timer_t* timer)
{
#ifdef BENCH_TIMER_WINDOWS
LARGE_INTEGER end_time = { 0 };
LARGE_INTEGER elapsed = { 0 };
QueryPerformanceCounter(&end_time);
elapsed.QuadPart = end_time.QuadPart - timer->start_time.QuadPart;
/*
We now have the elapsed number of ticks, along with the
number of ticks-per-second. We use these values
to convert to the number of elapsed microseconds.
To guard against loss-of-precision, we convert
to milliseconds *before* dividing by ticks-per-second.
*/
elapsed.QuadPart *= 1000;
elapsed.QuadPart /= timer->frequency.QuadPart;
return elapsed.QuadPart;
#elif defined(BENCH_TIMER_LIBC)
/* For seconds:
* return (float)((clock() - start_tick) / (float)CLOCKS_PER_SEC); */
return clock() - timer->start_tick;
#endif
}
void benchmark_list(
bench_file_func_t func, const char* title, int argc, char **argv)
{
bench_timer_t timer = { 0 };
int iarg;
if (func == NULL)
return;
bench_timer_start(&timer);
printf("Bench %s ...\n", title);
for (iarg = 0; iarg < argc; ++iarg) {
printf(" File %s ...\n", argv[iarg]);
(*func)(argv[iarg]);
}
/*printf(" exec time: %.2fs\n\n", elapsed_secs(start_tick));*/
printf(" exec time: %lldms\n\n", bench_timer_elapsed_ms(&timer));
}
void benchmark_forward_list(bench_file_func_t func, int argc, char **argv)
{
int i = 0;
while (i < argc) {
func(argv[i]);
++i;
}
}
void benchmark(
bench_file_func_t func, const char *title, const char* filepath)
{
benchmark_list(func, title, 1, (char**)&filepath);
}

View File

@ -0,0 +1,36 @@
/****************************************************************************
** gmio benchmarks
** Copyright Fougue (2 Mar. 2015)
** contact@fougue.pro
**
** This software provides performance benchmarks for the gmio library
** (https://github.com/fougue/gmio)
**
** This software is governed by the CeCILL-B license under French law and
** abiding by the rules of distribution of free software. You can use,
** modify and/ or redistribute the software under the terms of the CeCILL-B
** license as circulated by CEA, CNRS and INRIA at the following URL
** "http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html".
****************************************************************************/
#ifndef BENCH_TOOLS_H
#define BENCH_TOOLS_H
#include <gmio_core/global.h>
GMIO_C_LINKAGE_BEGIN
typedef void (*bench_file_func_t)(const char*);
void benchmark_list(
bench_file_func_t func, const char* title, int argc, char** argv);
void benchmark_forward_list(
bench_file_func_t func, int argc, char** argv);
void benchmark(
bench_file_func_t func, const char* title, const char* filepath);
GMIO_C_LINKAGE_END
#endif /* BENCH_TOOLS_H */