diff --git a/Source/Entities/MOSRotating.cpp b/Source/Entities/MOSRotating.cpp index fd036c301f..0b357c7f1c 100644 --- a/Source/Entities/MOSRotating.cpp +++ b/Source/Entities/MOSRotating.cpp @@ -1696,13 +1696,20 @@ void MOSRotating::Draw(BITMAP* pTargetBitmap, const Vector& targetPos, DrawMode } if (m_HFlipped && pFlipBitmap) { - bool drawIntermediate = mode != g_DrawMOID; + bool cachedColor = false; + if (mode == g_DrawColor && !m_SpriteModified && pFlipBitmap->w == m_aSprite[m_Frame]->w && pFlipBitmap->h == m_aSprite[m_Frame]->h) { + if (BITMAP* cachedBitmap = ContentFile::GetFlippedBitmap(m_aSprite[m_Frame])) { + pFlipBitmap = cachedBitmap; + cachedColor = true; + } + } + bool drawIntermediate = !cachedColor && mode != g_DrawMOID && mode != g_DrawTrans; if (drawIntermediate) { // Don't size the intermediate bitmaps to the m_Scale, because the scaling happens after they are done clear_to_color(pFlipBitmap, keyColor); // Draw either the source color bitmap or the intermediate material bitmap onto the intermediate flipping bitmap - if (mode == g_DrawColor || mode == g_DrawTrans) { + if (mode == g_DrawColor) { draw_sprite_h_flip(pFlipBitmap, m_aSprite[m_Frame], 0, 0); } else { // If using the temp bitmap (which is always larger than the sprite) make sure the flipped image ends up in the upper right corner as if it was just as small as the sprite bitmap diff --git a/Source/System/ContentFile.cpp b/Source/System/ContentFile.cpp index 3d7b9b4b8f..46ba2ffd0c 100644 --- a/Source/System/ContentFile.cpp +++ b/Source/System/ContentFile.cpp @@ -20,6 +20,7 @@ using namespace RTE; const std::string ContentFile::c_ClassName = "ContentFile"; std::array, ContentFile::BitDepths::BitDepthCount> ContentFile::s_LoadedBitmaps; +std::unordered_map ContentFile::s_FlippedBitmaps; std::unordered_map ContentFile::s_MemoryPNGs; std::unordered_map ContentFile::s_LoadedSamples; std::unordered_map ContentFile::s_PathHashes; @@ -53,6 +54,10 @@ int ContentFile::Create(const ContentFile& reference) { } void ContentFile::FreeAllLoaded() { + for (const auto& [source, flipped]: s_FlippedBitmaps) { + destroy_bitmap(flipped); + } + s_FlippedBitmaps.clear(); for (int depth = BitDepths::Eight; depth < BitDepths::BitDepthCount; ++depth) { for (const auto& [bitmapPath, bitmapPtr]: s_LoadedBitmaps[depth]) { destroy_bitmap(bitmapPtr); @@ -210,7 +215,8 @@ void ContentFile::ManuallyLoadDataPNG(const std::string& filePath, SDL_Surface* surface->w * SDL_BYTESPERPIXEL(surface->format)); } - s_LoadedBitmaps[BitDepths::Eight].try_emplace(filePath, bitmap); + auto [entry, inserted] = s_LoadedBitmaps[BitDepths::Eight].try_emplace(filePath, bitmap); + s_FlippedBitmaps.try_emplace(entry->second, nullptr); } void ContentFile::ReloadAllBitmaps() { @@ -222,6 +228,27 @@ void ContentFile::ReloadAllBitmaps() { g_ConsoleMan.PrintString("SYSTEM: Sprites reloaded"); } +BITMAP* ContentFile::GetFlippedBitmap(BITMAP* bitmap) { + auto entry = s_FlippedBitmaps.find(bitmap); + if (entry == s_FlippedBitmaps.end()) { + return nullptr; + } + if (!entry->second) { + entry->second = create_bitmap_ex(8, bitmap->w, bitmap->h); + clear_to_color(entry->second, ColorKeys::g_MaskColor); + draw_sprite_h_flip(entry->second, bitmap, 0, 0); + } + return entry->second; +} + +void ContentFile::RemoveFlippedBitmap(BITMAP* bitmap) { + auto entry = s_FlippedBitmaps.find(bitmap); + if (entry != s_FlippedBitmaps.end()) { + destroy_bitmap(entry->second); + s_FlippedBitmaps.erase(entry); + } +} + BITMAP* ContentFile::GetAsBitmap(int conversionMode, bool storeBitmap, const std::string& dataPathToSpecificFrame) { if (m_DataPath.empty()) { return nullptr; @@ -243,6 +270,7 @@ BITMAP* ContentFile::GetAsBitmap(int conversionMode, bool storeBitmap, const std std::unordered_map::iterator foundBitmap = s_LoadedBitmaps[BitDepths::Eight].find(dataPathToLoad); if (foundBitmap != s_LoadedBitmaps[BitDepths::Eight].end()) { returnBitmap = foundBitmap->second; + RemoveFlippedBitmap(returnBitmap); s_LoadedBitmaps[BitDepths::Eight].erase(dataPathToLoad); } @@ -269,6 +297,7 @@ BITMAP* ContentFile::GetAsBitmap(int conversionMode, bool storeBitmap, const std // Insert the bitmap into the map, PASSING OVER OWNERSHIP OF THE LOADED DATAFILE if (storeBitmap) { s_LoadedBitmaps[bitDepth].try_emplace(dataPathToLoad, returnBitmap); + s_FlippedBitmaps.try_emplace(returnBitmap, nullptr); } } @@ -448,6 +477,8 @@ void ContentFile::ReloadBitmap(const std::string& filePath, int conversionMode) set_color_conversion((conversionMode == COLORCONV_NONE) ? COLORCONV_NONE : conversionMode); BITMAP* loadedBitmap = (*bmpItr).second; + RemoveFlippedBitmap(loadedBitmap); + s_FlippedBitmaps.try_emplace(loadedBitmap, nullptr); SDL_Surface* newImage = LoadImageAsSurface(conversionMode, filePath); diff --git a/Source/System/ContentFile.h b/Source/System/ContentFile.h index 454511d13b..94129699c5 100644 --- a/Source/System/ContentFile.h +++ b/Source/System/ContentFile.h @@ -124,6 +124,9 @@ namespace RTE { /// Reloads all BITMAPs in the cache from disk, allowing any changes to be reflected at runtime. static void ReloadAllBitmaps(); + /// Gets a cached horizontal flip of a loaded sprite bitmap, or nullptr for a bitmap outside this cache. Ownership stays with ContentFile. + static BITMAP* GetFlippedBitmap(BITMAP* bitmap); + /// Gets the data represented by this ContentFile object as an Allegro BITMAP, loading it into the static maps if it's not already loaded. Note that ownership of the BITMAP is NOT transferred! /// @param conversionMode The Allegro color conversion mode to use when loading this bitmap. /// @param storeBitmap Whether to store the BITMAP in the relevant static map after loading it or not. If this is false, ownership of the BITMAP IS transferred! @@ -180,6 +183,7 @@ namespace RTE { static std::unordered_map s_PathHashes; //!< Static map containing the hash values of paths of all loaded data files. static std::array, BitDepths::BitDepthCount> s_LoadedBitmaps; //!< Static map containing all the already loaded BITMAPs and their paths for each bit depth. + static std::unordered_map s_FlippedBitmaps; //!< Horizontal flips of unmodified shared sprite bitmaps. static std::unordered_map s_MemoryPNGs; //!< Static map containing in-memory PNG files for save/load static std::unordered_map s_LoadedSamples; //!< Static map containing all the already loaded FSOUND_SAMPLEs and their paths. @@ -239,6 +243,7 @@ namespace RTE { /// @param filePath The filepath to the bitmap we want to reload. /// @param conversionMode The Allegro color conversion mode to use when reloading this bitmap. static void ReloadBitmap(const std::string& filePath, int conversionMode = 0); + static void RemoveFlippedBitmap(BITMAP* bitmap); /// Set alpha value of non mask color pixels to 255 for 32-bit bitmaps. (WARN: would override existing alpha values!) static void AddAlphaChannel(BITMAP* bitmap); diff --git a/Tools/Benchmarks/CaptureSpriteGame.py b/Tools/Benchmarks/CaptureSpriteGame.py new file mode 100644 index 0000000000..0cd0267c14 --- /dev/null +++ b/Tools/Benchmarks/CaptureSpriteGame.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python3 +import argparse +import json +import pathlib +import shlex +import subprocess + +parser = argparse.ArgumentParser(description='Build seeded game captures from the FlippedSprites engine objects.') +parser.add_argument('build_directory', type=pathlib.Path) +parser.add_argument('output_directory', type=pathlib.Path) +parser.add_argument('--replace-object', action='append', default=[]) +args = parser.parse_args() +build = args.build_directory.resolve() +output = args.output_directory.resolve() +repo = pathlib.Path(__file__).resolve().parents[2] +commands = json.loads((build / 'compile_commands.json').read_text()) +movable = (repo / 'Source/Managers/MovableMan.cpp').read_text() +movable = 'namespace RTE { long long profileTravel=0, profileColor=0, profileClear=0; }\n' + movable +movable = movable.replace('void MovableMan::Update() {', 'void MovableMan::Update() {\n profileTravel=profileColor=profileClear=0;') +movable = movable.replace('g_SceneMan.ClearMOColorLayer();', '{ const auto started=g_TimerMan.GetAbsoluteTime(); g_SceneMan.ClearMOColorLayer(); profileClear=g_TimerMan.GetAbsoluteTime()-started; }') +movable = movable.replace('\tTravel();', '\t{ const auto started=g_TimerMan.GetAbsoluteTime(); Travel(); profileTravel=g_TimerMan.GetAbsoluteTime()-started; }') +movable = movable.replace('Draw(g_SceneMan.GetMOColorBitmap());', '{ const auto started=g_TimerMan.GetAbsoluteTime(); Draw(g_SceneMan.GetMOColorBitmap()); profileColor=g_TimerMan.GetAbsoluteTime()-started; }') +main = (repo / 'Source/Main.cpp').read_text() +main = main.replace('void RunGameLoop() {', '''namespace RTE { extern long long profileTravel, profileColor, profileClear; } +void RunGameLoop() { + struct CaptureSample { long long simulation, movable; int particles; long long travel, color, clear, gridWait; }; + std::vector captureSamples; +''') +main = main.replace('g_PerformanceMan.StartPerformanceMeasurement(PerformanceMan::SimTotal);', '''g_RandomGenerator.Seed(731 + captureSamples.size()); + const auto captureStart=g_TimerMan.GetAbsoluteTime(); + g_PerformanceMan.StartPerformanceMeasurement(PerformanceMan::SimTotal);''') +main = main.replace('g_MovableMan.CompleteQueuedMOIDDrawings();', '''const auto waitStart=g_TimerMan.GetAbsoluteTime(); + g_MovableMan.CompleteQueuedMOIDDrawings(); + const auto gridWait=g_TimerMan.GetAbsoluteTime()-waitStart;''') +main = main.replace('g_MovableMan.Update();', '''const auto movableStart=g_TimerMan.GetAbsoluteTime(); + g_MovableMan.Update(); + const auto movableEnd=g_TimerMan.GetAbsoluteTime();''') +main = main.replace('g_PerformanceMan.StopPerformanceMeasurement(PerformanceMan::SimTotal);', '''g_PerformanceMan.StopPerformanceMeasurement(PerformanceMan::SimTotal); + captureSamples.push_back({g_TimerMan.GetAbsoluteTime()-captureStart, movableEnd-movableStart, g_MovableMan.GetParticleCount(), profileTravel, profileColor, profileClear, gridWait});''') +main = main.replace('g_PerformanceMan.UpdateMSPF(updateTotalTime, drawTotalTime);', '''g_PerformanceMan.UpdateMSPF(updateTotalTime, drawTotalTime); + if (captureSamples.size() >= 240) { + for (size_t i=0; i +#include +using namespace RTE; + +struct SceneAccess : SceneMan { + static Scene* SceneMan::* currentScene() { return &SceneAccess::m_pCurrentScene; } +}; +struct TerrainFixture : SLTerrain { + TerrainFixture(const std::string& path) { + m_BitmapFile = ContentFile(path.c_str()); m_WrapX = true; m_WrapY = false; Create(); + } +}; +Material fixtureMaterial; +struct SpriteFixture : MOSRotating { + SpriteFixture(const std::vector& frames, int i) { + m_aSprite = frames; + m_FrameCount = frames.size(); + int width = frames[0]->w, height = frames[0]->h; + m_pFlipBitmap = create_bitmap_ex(8, width, height); + m_pTempBitmap = create_bitmap_ex(8, width * 2, height * 2); + m_SpriteOffset = Vector(-width * 0.5F + 0.25F, -height * 0.5F - 0.75F); + m_SpriteRadius = std::hypot(width, height); + m_SpriteDiameter = m_SpriteRadius * 2; + m_Pos = Vector(80 + i % 8 * 48, 80 + i / 8 % 8 * 48); + m_HFlipped = true; + m_Rotation.SetRadAngle(i * 0.137F); + } + ~SpriteFixture() override { destroy_bitmap(m_pTempBitmap); m_pTempBitmap = nullptr; } + Material const* GetMaterial() const override { return &fixtureMaterial; } + void configure(int frame, bool flip, float angle, float scale, Vector position) { + m_Frame = frame; m_HFlipped = flip; m_Rotation.SetRadAngle(angle); m_Scale = scale; m_Pos = position; + } + void overwriteScratch() { clear_to_color(m_pFlipBitmap, 173); } + void flash() { m_FlashWhiteTimer.Reset(); m_FlashWhiteTimer.SetRealTimeLimitMS(10000); } + void stopFlash() { m_FlashWhiteTimer.SetRealTimeLimitMS(0); } + void copySprite(const SpriteFixture& reference) { MOSprite::Create(reference); } +}; +static_assert(sizeof(SpriteFixture) == sizeof(MOSRotating)); +uint64_t hashBytes(uint64_t hash, const unsigned char* bytes, size_t size) { + for (size_t i = 0; i < size; ++i) hash = (hash ^ bytes[i]) * 1099511628211ULL; + return hash; +} +uint64_t hashBitmap(uint64_t hash, BITMAP* bitmap) { + for (int y = 0; y < bitmap->h; ++y) hash = hashBytes(hash, bitmap->line[y], bitmap->w); + return hash; +} +BITMAP* pattern(int width, int height, int seed) { + BITMAP* bitmap = create_bitmap_ex(8, width, height); + for (int y = 0; y < height; ++y) for (int x = 0; x < width; ++x) + _putpixel(bitmap, x, y, (x * 17 + y * 13 + seed) % 7 == 0 || x < y / 3 ? 0 : 20 + (x + y + seed) % 200); + return bitmap; +} +double milliseconds(std::chrono::steady_clock::time_point start) { + return std::chrono::duration(std::chrono::steady_clock::now() - start).count(); +} +int main(int argc, char** argv) { + std::cout << std::unitbuf; + install_allegro(SYSTEM_NONE, &errno, atexit); + System::EnableFilePathCaseSensitivity(false); + ThreadMan::Construct(); TimerMan::Construct(); SettingsMan::Construct(); PresetMan::Construct(); + SceneMan::Construct(); MovableMan::Construct(); LuaMan::Construct(); ConsoleMan::Construct(); FrameMan::Construct(); + fixtureMaterial.SetIndex(37); + PALETTE palette{}; + for (int i = 0; i < 256; ++i) palette[i].r = palette[i].g = palette[i].b = i % 64; + std::string fixturePath = "Mods/FlippedSpritesBenchmark-" + std::to_string(getpid()); + std::filesystem::create_directories(fixturePath); + std::vector paths; + auto loadPattern = [&](int width, int height, int seed) { + std::string path = fixturePath + "/" + std::to_string(paths.size()) + ".bmp"; + BITMAP* bitmap = pattern(width, height, seed); + save_bitmap(path.c_str(), bitmap, palette); destroy_bitmap(bitmap); + paths.push_back(path); + return ContentFile(path.c_str()).GetAsBitmap(); + }; + std::string terrainPath = fixturePath + "/terrain.bmp"; + BITMAP* terrainBitmap = pattern(512, 512, 0); + save_bitmap(terrainPath.c_str(), terrainBitmap, palette); destroy_bitmap(terrainBitmap); + Scene scene; + scene.Create(new TerrainFixture(terrainPath)); + std::filesystem::remove(terrainPath); + g_SceneMan.*SceneAccess::currentScene() = &scene; + BITMAP* target = create_bitmap_ex(8, 512, 512); + std::vector sources; + for (int seed = 0; seed < 3; ++seed) sources.push_back(loadPattern(24 + seed % 2 * 8, 20 + seed % 2 * 8, seed)); + uint64_t hash = 1469598103934665603ULL; + int cases = 0; + { + SpriteFixture sprite(sources, 0); + for (int frame = 0; frame < 3; ++frame) for (bool flip : {false, true}) + for (float angle : {0.0F, 0.13F, -1.27F, 3.14159265F}) for (float scale : {0.5F, 1.0F, 1.7F}) + for (Vector camera : {Vector(), Vector(-50, 0), Vector(300, 0)}) + for (DrawMode mode : {g_DrawColor, g_DrawWhite, g_DrawMaterial, g_DrawDoor, g_DrawColor}) { + sprite.configure(frame, flip, angle, scale, Vector(cases % 2 ? 5 : 507, 200.75F)); + sprite.overwriteScratch(); + clear_to_color(target, 11); + sprite.Draw(target, camera, mode, true); + hash = hashBitmap(hash, target); ++cases; + } + sprite.configure(0, true, 0.23F, 1, Vector(200, 200)); + for (int edit = 0; edit < 4; ++edit) { + if (edit) sprite.SetSpritePixelIndex(8 + edit, 10, 0, 43 + edit, -1, false); + clear_to_color(target, 11); sprite.Draw(target, Vector(), g_DrawColor, true); + hash = hashBitmap(hash, target); ++cases; + } + sprite.SetAllSpritePixelIndexes(0, 63, 0, false); + clear_to_color(target, 11); sprite.Draw(target, Vector(), g_DrawColor, true); + hash = hashBitmap(hash, target); ++cases; + SpriteFixture clone(sources, 0); + clone.copySprite(sprite); + for (int edit = 0; edit < 3; ++edit) { + sprite.SetSpritePixelIndex(11 + edit, 10, 0, 112 + edit, -1, false); + clear_to_color(target, 11); clone.Draw(target, Vector(), g_DrawColor, true); + hash = hashBitmap(hash, target); ++cases; + } + sprite.flash(); + clear_to_color(target, 11); sprite.Draw(target, Vector(), g_DrawColor, true); + hash = hashBitmap(hash, target); ++cases; + sprite.stopFlash(); + clear_to_color(target, 11); sprite.Draw(target, Vector(), g_DrawColor, true); + hash = hashBitmap(hash, target); ++cases; + } + std::string path = fixturePath + "/reload.bmp"; + save_bitmap(path.c_str(), sources[0], palette); + BITMAP* loaded = ContentFile(path.c_str()).GetAsBitmap(); + { + SpriteFixture sprite({loaded}, 0); + for (int reload = 0; reload < 3; ++reload) { + if (reload) { + BITMAP* replacement = pattern(24 + (reload == 2 ? 8 : 0), 20, 77 + reload); + save_bitmap(path.c_str(), replacement, palette); destroy_bitmap(replacement); + ContentFile::ReloadAllBitmaps(); + if (ContentFile(path.c_str()).GetAsBitmap() != loaded) return 2; + } + clear_to_color(target, 11); sprite.Draw(target, Vector(), g_DrawColor, true); + hash = hashBitmap(hash, target); ++cases; + } + } + std::filesystem::remove(path); + std::string memoryPath = fixturePath + "/memory.png"; + SDL_Surface* surface = SDL_CreateSurface(24, 20, SDL_PIXELFORMAT_INDEX8); + for (int y = 0; y < 20; ++y) std::memcpy(static_cast(surface->pixels) + y * surface->pitch, sources[0]->line[y], 24); + ContentFile::ManuallyLoadDataPNG(memoryPath, surface); + ContentFile memoryFile(memoryPath.c_str()); + BITMAP* transferred = memoryFile.GetAsBitmap(); + { + SpriteFixture sprite({transferred}, 0); + clear_to_color(target, 11); sprite.Draw(target, Vector(), g_DrawColor, true); + hash = hashBitmap(hash, target); ++cases; + if (memoryFile.GetAsBitmap(0, false) != transferred) return 4; + for (int edit = 0; edit < 2; ++edit) { + _putpixel(transferred, 5 + edit, 6, 78 + edit); + clear_to_color(target, 11); sprite.Draw(target, Vector(), g_DrawColor, true); + hash = hashBitmap(hash, target); ++cases; + } + } + destroy_bitmap(transferred); + std::cout << "behavior_hash=" << hash << " cases=" << cases << '\n'; + if (argc > 1 && std::string(argv[1]) == "--gpu") { + GLResourceMan::Construct(); + g_FrameMan.SetTransTableFromPreset(TransparencyPreset::HalfTrans); + SDL_Init(SDL_INIT_VIDEO); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); + SDL_Window* window = SDL_CreateWindow("Draw benchmark", 512, 512, SDL_WINDOW_OPENGL | SDL_WINDOW_HIDDEN); + SDL_GLContext context = SDL_GL_CreateContext(window); + gladLoadGL((GLADloadfunc)SDL_GL_GetProcAddress); + rlLoadExtensions((void*)SDL_GL_GetProcAddress); + rlglInit(512, 512); rlViewport(0, 0, 512, 512); + rlMatrixMode(RL_PROJECTION); rlLoadIdentity(); rlOrtho(0, 512, 512, 0, -1, 1); + rlMatrixMode(RL_MODELVIEW); rlLoadIdentity(); + uint64_t gpuHash = 1469598103934665603ULL; + SpriteFixture sprite({sources[0]}, 0); + for (bool flip : {false, true}) for (float angle : {0.0F, 0.17F, -0.95F}) { + sprite.configure(0, flip, angle, 1, Vector(200, 200)); + glClearColor(0.17F, 0.23F, 0.31F, 1); glClear(GL_COLOR_BUFFER_BIT); + sprite.Draw(target, Vector(), g_DrawTrans, true); + rlDrawRenderBatchActive(); + std::vector pixels(512 * 512 * 4); + glReadPixels(0, 0, 512, 512, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data()); + int drawnPixels = 0; + for (size_t i = 0; i < pixels.size(); i += 4) drawnPixels += std::memcmp(pixels.data(), pixels.data() + i, 4) != 0; + if (!drawnPixels) return 3; + std::cout << "gpu_flip=" << flip << " angle=" << angle << " drawn_pixels=" << drawnPixels << '\n'; + gpuHash = hashBytes(gpuHash, pixels.data(), pixels.size()); + } + std::cout << "gpu_hash=" << gpuHash << " cases=6\n"; + g_GLResourceMan.Destroy(); rlglClose(); SDL_GL_DestroyContext(context); SDL_DestroyWindow(window); SDL_Quit(); + } else if (argc == 1) { + for (auto [size, unique] : {std::pair{12, 1}, {24, 8}, {64, 8}, {128, 8}, {24, 512}, {64, 512}}) { + std::vector frames; + for (int i = 0; i < unique; ++i) frames.push_back(loadPattern(size, size, i)); + std::vector> objects; + for (int i = 0; i < 512; ++i) objects.push_back(std::make_unique(std::vector{frames[i % unique]}, i)); + auto start = std::chrono::steady_clock::now(); + for (const auto& object : objects) object->Draw(target, Vector(), g_DrawColor, true); + std::cout << "size=" << size << " unique=" << unique << " cold_ms=" << milliseconds(start) << " draws=512\n"; + for (int sample = -1; sample < 5; ++sample) { + start = std::chrono::steady_clock::now(); + for (int repeat = 0; repeat < 128; ++repeat) for (const auto& object : objects) object->Draw(target, Vector(), g_DrawColor, true); + if (sample >= 0) std::cout << "size=" << size << " unique=" << unique << " sample=" << sample << " ms=" << milliseconds(start) << " draws=65536\n"; + } + std::cout << "size=" << size << " unique=" << unique << " pixels_hash=" << hashBitmap(1469598103934665603ULL, target) << '\n'; + } + } + ContentFile::FreeAllLoaded(); + std::filesystem::remove_all(fixturePath); + destroy_bitmap(target); + g_SceneMan.*SceneAccess::currentScene() = nullptr; +} diff --git a/Tools/Benchmarks/FlippedSprites.md b/Tools/Benchmarks/FlippedSprites.md new file mode 100644 index 0000000000..9fb2f79710 --- /dev/null +++ b/Tools/Benchmarks/FlippedSprites.md @@ -0,0 +1,105 @@ +The sprite benchmark calls the production `MOSRotating::Draw` function through 512 debris fixtures. +It links the existing release engine objects, with separate baseline and changed `MOSRotating` and `ContentFile` objects. +The fixtures load patterned BMPs through `ContentFile`. +Each sample contains 65,536 flipped color draws, with rotation and scene wrapping. +Each process includes one warmup sample and five recorded samples per workload. + +The pixel checks cover 1,096 cases. +These cases include frame changes, flips, rotations, scales, scene seams, camera offsets, white flashes, material silhouettes, and door silhouettes. +They also cover scratch bitmap changes, repeated sprite edits, copies of edited sprites, reloads, changed source dimensions, and memory bitmap ownership transfer. +The GPU checks call the production transparent draw path in a real OpenGL context. +They read six framebuffer images and require visible pixels. + +Baseline and changed builds produced the same CPU hash: `15073311523546579531`. +Both builds produced the same GPU hash: `15926731766284440575`. +All six workload pixel hashes also matched across all processes. +The GPU startup prints one `GLAD: ERROR 1280 in glGetIntegerv!` message in both builds. +The six draws produce visible pixels and matching framebuffer hashes. + +The measurements used an Apple M3 Pro with GCC 15.2.0, C++20, `-O3`, and `NDEBUG`. +The baseline revision was `41e6b7010817936e09d2929330b7519852a1fcca`. +Three process pairs ran in this order: baseline/changed, changed/baseline, baseline/changed. +The table uses the median of 15 samples per workload. + +| Sprite size | Unique assets | Baseline, ms | Changed, ms | CPU time reduction | Added bitmap storage | +| --- | ---: | ---: | ---: | ---: | ---: | +| 12×12 | 1 | 22.355 | 15.843 | 29.1% | 344 B | +| 24×24 | 8 | 90.951 | 61.750 | 32.1% | 6.8 KiB | +| 64×64 | 8 | 484.790 | 331.360 | 31.6% | 36.8 KiB | +| 128×128 | 8 | 1593.830 | 1028.640 | 35.5% | 136.8 KiB | +| 24×24 | 512 | 88.733 | 66.646 | 24.9% | 436 KiB | +| 64×64 | 512 | 491.085 | 346.401 | 29.5% | 2.30 MiB | + +The added bitmap storage includes pixel data, row pointers, and the 104-byte `BITMAP` header on this machine. +It excludes allocator overhead and the map nodes and buckets. +The map keeps one entry per loaded bitmap, with a null value until the first cached flip. +The cache retains flipped bitmaps until reload, ownership transfer, or content cleanup. + +Cold measurements cover the first 512 draws after the source files load. +With 512 unique assets, the 24×24 workload increased from 0.839 ms to 0.889 ms. +The 64×64 workload increased from 4.054 ms to 4.241 ms. +These costs include the first flip allocations. +The workloads with shared assets also improved on their first draw pass. + +The full game ran three alternating pairs with 400 collidable stock gibs and a frag grenade explosion every 60 ticks. +The included activity uses Grasslands and the stock `Gib Metal Grey Small A` preset. +The capture seeds the random generator with `731 + tick` and stops after 240 simulation ticks. +The comparison excludes the first 60 ticks. +All six captures had identical particle counts at every tick, with a peak of 883 particles. + +| Full game measurement | Baseline | Changed | +| --- | ---: | ---: | +| Median of color draw means | 129.394 µs | 102.106 µs | +| Median of simulation means | 2534.261 µs | 2497.439 µs | +| Median of simulation 95th percentiles | 8072 µs | 8177 µs | + +Color drawing took 21.1% less CPU time. +The total simulation difference was about 1.5%, with variation between runs. +Travel still took about 2 ms per simulation tick. +These measurements support a rendering improvement, with limited evidence of a total simulation improvement. +Whole frame measurements had a timer outlier and do not support a frame rate claim. + +Raw draw samples are in [draw.csv](FlippedSpritesResults/draw.csv). +Raw game samples are in [game.csv](FlippedSpritesResults/game.csv). +The results directory also contains the workload summaries and the GPU outputs. + +Build the engine with Meson and Ninja before you compile the benchmark. +Run this command from the repository root: + +```sh +python3 Tools/Benchmarks/FlippedSprites.py build /tmp/flipped-sprites +``` + +The runner builds the baseline sources from Git and the changed sources from the current working tree. +If the reused engine build contains other changes, pass `--replace-object Name=/absolute/path/to/pristine/object.o` for each affected object. +The recorded comparison used pristine `Matrix` and `MOSprite` objects. +The runner adds only static members to `ContentFile`; engine object layouts stay compatible. + +On macOS, run the pixel checks and GPU checks with the engine library directory: + +```sh +DYLD_LIBRARY_PATH="$PWD/external/lib/macos" /tmp/flipped-sprites/baseline --check +DYLD_LIBRARY_PATH="$PWD/external/lib/macos" /tmp/flipped-sprites/changed --check +DYLD_LIBRARY_PATH="$PWD/external/lib/macos" /tmp/flipped-sprites/baseline --gpu +DYLD_LIBRARY_PATH="$PWD/external/lib/macos" /tmp/flipped-sprites/changed --gpu +``` + +For CPU measurements, omit the final argument. +Repeat each executable three times and alternate the process order. +On Linux, use `LD_LIBRARY_PATH` with the engine library directory. +The fixtures disable the engine file path cache because they create new BMP files after startup. +The fixture size assertion protects the fixed object pool allocation used by `MOSRotating`. + +For a full game capture, run this command with the same object replacement arguments: + +```sh +python3 Tools/Benchmarks/CaptureSpriteGame.py build /tmp/flipped-sprites +``` + +Copy [PerformanceStress.rte](PerformanceStress.rte) into the runtime `Mods` directory. +In `Userdata/Settings.ini`, set `LaunchIntoActivity = 1`, `DefaultActivityType = GAScripted`, and `DefaultActivityName = Debris Performance Stress`. +Set `DefaultSceneName = Grasslands`. +Run each capture executable from the normal game runtime directory, with the normal libraries and data. +On macOS, copy the executable into the existing app bundle before you run it. +Capture the `-cout` output until `PERF_CAPTURE_DONE`, then stop the process. +Repeat three pairs and compare the `PERF_PROFILE` rows from ticks 60 through 239. diff --git a/Tools/Benchmarks/FlippedSprites.py b/Tools/Benchmarks/FlippedSprites.py new file mode 100644 index 0000000000..c9fd2ae1b3 --- /dev/null +++ b/Tools/Benchmarks/FlippedSprites.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python3 +import argparse +import json +import pathlib +import shlex +import subprocess + +parser = argparse.ArgumentParser(description='Link baseline and changed Draw benchmarks with real engine objects.') +parser.add_argument('build_directory', type=pathlib.Path) +parser.add_argument('output_directory', type=pathlib.Path) +parser.add_argument('--baseline-ref', default='41e6b7010817936e09d2929330b7519852a1fcca') +parser.add_argument('--replace-object', action='append', default=[], help='Name=/path/to/pristine/object.o') +args = parser.parse_args() +build = args.build_directory.resolve() +output = args.output_directory.resolve() +output.mkdir(parents=True, exist_ok=True) +repo = pathlib.Path(__file__).resolve().parents[2] +commands = json.loads((build / 'compile_commands.json').read_text()) + +def compile_file(name, source, destination): + command = shlex.split(next(x['command'] for x in commands if x['file'].endswith('/' + name))) + command = command[:command.index('-MD')] + command = [arg for arg in command if arg not in {'-ICortexCommand.p', '-fpch-preprocess'}] + includes = ['-I' + str(path) for path in [repo / 'Source', *(repo / 'Source').iterdir()] if path.is_dir()] + command[1:1] = includes + command += ['-g', '-c', str(source), '-o', str(destination)] + subprocess.run(command, cwd=build, check=True) + +benchmark = output / 'benchmark.o' +compile_file('MOSRotating.cpp', pathlib.Path(__file__).with_suffix('.cpp'), benchmark) +base_link = shlex.split(subprocess.check_output(['ninja', '-C', str(build), '-t', 'commands', 'CortexCommand'], text=True).splitlines()[-1]) +for variant in ['baseline', 'changed']: + replacements = dict(argument.split('=', 1) for argument in args.replace_object) + for name, folder in [('MOSRotating', 'Entities'), ('ContentFile', 'System')]: + relative = 'Source/' + folder + '/' + name + '.cpp' + source = repo / relative + if variant == 'baseline': + source = output / (name + '-baseline.cpp') + source.write_bytes(subprocess.check_output(['git', 'show', args.baseline_ref + ':' + relative], cwd=repo)) + destination = output / (name + '-' + variant + '.o') + compile_file(name + '.cpp', source, destination) + replacements[name] = str(destination) + link = base_link.copy() + link[link.index('-o') + 1] = str(output / variant) + link[link.index('CortexCommand.p/Source_Main.cpp.o')] = str(benchmark) + for name, path in replacements.items(): + index = next(i for i, arg in enumerate(link) if arg.endswith('_' + name + '.cpp.o')) + link[index] = str(pathlib.Path(path).resolve()) + subprocess.run(link, cwd=build, check=True) diff --git a/Tools/Benchmarks/FlippedSpritesResults/baseline-gpu.txt b/Tools/Benchmarks/FlippedSpritesResults/baseline-gpu.txt new file mode 100644 index 0000000000..a023d5ed2a --- /dev/null +++ b/Tools/Benchmarks/FlippedSpritesResults/baseline-gpu.txt @@ -0,0 +1,9 @@ +behavior_hash=15073311523546579531 cases=1096 +GLAD: ERROR 1280 in glGetIntegerv! +gpu_flip=0 angle=0 drawn_pixels=480 +gpu_flip=0 angle=0.17 drawn_pixels=479 +gpu_flip=0 angle=-0.95 drawn_pixels=482 +gpu_flip=1 angle=0 drawn_pixels=480 +gpu_flip=1 angle=0.17 drawn_pixels=480 +gpu_flip=1 angle=-0.95 drawn_pixels=481 +gpu_hash=15926731766284440575 cases=6 diff --git a/Tools/Benchmarks/FlippedSpritesResults/changed-gpu.txt b/Tools/Benchmarks/FlippedSpritesResults/changed-gpu.txt new file mode 100644 index 0000000000..a023d5ed2a --- /dev/null +++ b/Tools/Benchmarks/FlippedSpritesResults/changed-gpu.txt @@ -0,0 +1,9 @@ +behavior_hash=15073311523546579531 cases=1096 +GLAD: ERROR 1280 in glGetIntegerv! +gpu_flip=0 angle=0 drawn_pixels=480 +gpu_flip=0 angle=0.17 drawn_pixels=479 +gpu_flip=0 angle=-0.95 drawn_pixels=482 +gpu_flip=1 angle=0 drawn_pixels=480 +gpu_flip=1 angle=0.17 drawn_pixels=480 +gpu_flip=1 angle=-0.95 drawn_pixels=481 +gpu_hash=15926731766284440575 cases=6 diff --git a/Tools/Benchmarks/FlippedSpritesResults/draw.csv b/Tools/Benchmarks/FlippedSpritesResults/draw.csv new file mode 100644 index 0000000000..5367510b1e --- /dev/null +++ b/Tools/Benchmarks/FlippedSpritesResults/draw.csv @@ -0,0 +1,217 @@ +variant,pair,size,unique,sample,ms +baseline,1,12,1,cold,0.278 +baseline,1,12,1,0,22.739 +baseline,1,12,1,1,22.475 +baseline,1,12,1,2,22.467 +baseline,1,12,1,3,22.355 +baseline,1,12,1,4,22.396 +baseline,1,24,8,cold,0.822 +baseline,1,24,8,0,91.683 +baseline,1,24,8,1,90.741 +baseline,1,24,8,2,90.863 +baseline,1,24,8,3,90.657 +baseline,1,24,8,4,90.265 +baseline,1,64,8,cold,3.964 +baseline,1,64,8,0,487.292 +baseline,1,64,8,1,485.389 +baseline,1,64,8,2,482.23 +baseline,1,64,8,3,482.086 +baseline,1,64,8,4,481.937 +baseline,1,128,8,cold,12.586 +baseline,1,128,8,0,1588.73 +baseline,1,128,8,1,1591.02 +baseline,1,128,8,2,1588.78 +baseline,1,128,8,3,1594.71 +baseline,1,128,8,4,1586.96 +baseline,1,24,512,cold,0.825 +baseline,1,24,512,0,88.658 +baseline,1,24,512,1,88.661 +baseline,1,24,512,2,88.546 +baseline,1,24,512,3,88.853 +baseline,1,24,512,4,88.576 +baseline,1,64,512,cold,3.949 +baseline,1,64,512,0,482.625 +baseline,1,64,512,1,481.428 +baseline,1,64,512,2,482.648 +baseline,1,64,512,3,482.758 +baseline,1,64,512,4,484.009 +baseline,2,12,1,cold,0.271 +baseline,2,12,1,0,22.36 +baseline,2,12,1,1,22.413 +baseline,2,12,1,2,22.258 +baseline,2,12,1,3,22.244 +baseline,2,12,1,4,22.226 +baseline,2,24,8,cold,0.858 +baseline,2,24,8,0,90.807 +baseline,2,24,8,1,90.951 +baseline,2,24,8,2,92.055 +baseline,2,24,8,3,90.858 +baseline,2,24,8,4,90.484 +baseline,2,64,8,cold,3.979 +baseline,2,64,8,0,484.073 +baseline,2,64,8,1,483.957 +baseline,2,64,8,2,484.778 +baseline,2,64,8,3,484.79 +baseline,2,64,8,4,484.361 +baseline,2,128,8,cold,12.416 +baseline,2,128,8,0,1596.3 +baseline,2,128,8,1,1593.83 +baseline,2,128,8,2,1591.36 +baseline,2,128,8,3,1601.8 +baseline,2,128,8,4,1611.45 +baseline,2,24,512,cold,0.839 +baseline,2,24,512,0,93.83 +baseline,2,24,512,1,93.802 +baseline,2,24,512,2,93.817 +baseline,2,24,512,3,93.841 +baseline,2,24,512,4,93.71 +baseline,2,64,512,cold,4.072 +baseline,2,64,512,0,498.586 +baseline,2,64,512,1,495.821 +baseline,2,64,512,2,496.68 +baseline,2,64,512,3,496.972 +baseline,2,64,512,4,497.039 +baseline,3,12,1,cold,0.272 +baseline,3,12,1,0,22.429 +baseline,3,12,1,1,22.215 +baseline,3,12,1,2,22.141 +baseline,3,12,1,3,22.178 +baseline,3,12,1,4,22.149 +baseline,3,24,8,cold,0.874 +baseline,3,24,8,0,92.551 +baseline,3,24,8,1,95.023 +baseline,3,24,8,2,94.463 +baseline,3,24,8,3,100.234 +baseline,3,24,8,4,98.671 +baseline,3,64,8,cold,4.288 +baseline,3,64,8,0,499.412 +baseline,3,64,8,1,498.833 +baseline,3,64,8,2,497.802 +baseline,3,64,8,3,498.792 +baseline,3,64,8,4,498.807 +baseline,3,128,8,cold,12.634 +baseline,3,128,8,0,1568.41 +baseline,3,128,8,1,1580.59 +baseline,3,128,8,2,1601.39 +baseline,3,128,8,3,1617.94 +baseline,3,128,8,4,1621.94 +baseline,3,24,512,cold,0.87 +baseline,3,24,512,0,88.733 +baseline,3,24,512,1,89.344 +baseline,3,24,512,2,88.056 +baseline,3,24,512,3,88.628 +baseline,3,24,512,4,88.057 +baseline,3,64,512,cold,4.054 +baseline,3,64,512,0,4316.2 +baseline,3,64,512,1,502.097 +baseline,3,64,512,2,491.085 +baseline,3,64,512,3,481.417 +baseline,3,64,512,4,481.434 +changed,1,12,1,cold,0.222 +changed,1,12,1,0,15.843 +changed,1,12,1,1,15.803 +changed,1,12,1,2,15.832 +changed,1,12,1,3,15.761 +changed,1,12,1,4,15.783 +changed,1,24,8,cold,0.697 +changed,1,24,8,0,61.656 +changed,1,24,8,1,61.677 +changed,1,24,8,2,61.549 +changed,1,24,8,3,61.658 +changed,1,24,8,4,61.75 +changed,1,64,8,cold,2.787 +changed,1,64,8,0,331.36 +changed,1,64,8,1,331.455 +changed,1,64,8,2,330.853 +changed,1,64,8,3,330.686 +changed,1,64,8,4,330.369 +changed,1,128,8,cold,8.038 +changed,1,128,8,0,1021 +changed,1,128,8,1,1018.78 +changed,1,128,8,2,1017.47 +changed,1,128,8,3,1019.36 +changed,1,128,8,4,1019.77 +changed,1,24,512,cold,0.906 +changed,1,24,512,0,63.913 +changed,1,24,512,1,63.857 +changed,1,24,512,2,63.772 +changed,1,24,512,3,63.689 +changed,1,24,512,4,63.836 +changed,1,64,512,cold,4.241 +changed,1,64,512,0,346.794 +changed,1,64,512,1,346.239 +changed,1,64,512,2,346.653 +changed,1,64,512,3,346.084 +changed,1,64,512,4,346.401 +changed,2,12,1,cold,0.228 +changed,2,12,1,0,15.837 +changed,2,12,1,1,15.89 +changed,2,12,1,2,15.812 +changed,2,12,1,3,15.876 +changed,2,12,1,4,15.826 +changed,2,24,8,cold,0.674 +changed,2,24,8,0,62.114 +changed,2,24,8,1,62.061 +changed,2,24,8,2,61.849 +changed,2,24,8,3,61.84 +changed,2,24,8,4,61.964 +changed,2,64,8,cold,2.824 +changed,2,64,8,0,332.358 +changed,2,64,8,1,331.152 +changed,2,64,8,2,330.616 +changed,2,64,8,3,331.223 +changed,2,64,8,4,331.156 +changed,2,128,8,cold,7.945 +changed,2,128,8,0,1024.92 +changed,2,128,8,1,1026.21 +changed,2,128,8,2,1029.4 +changed,2,128,8,3,1028.64 +changed,2,128,8,4,1029.31 +changed,2,24,512,cold,0.87 +changed,2,24,512,0,66.826 +changed,2,24,512,1,66.646 +changed,2,24,512,2,66.689 +changed,2,24,512,3,66.519 +changed,2,24,512,4,66.574 +changed,2,64,512,cold,4.219 +changed,2,64,512,0,353.105 +changed,2,64,512,1,350.961 +changed,2,64,512,2,351.948 +changed,2,64,512,3,349.809 +changed,2,64,512,4,350.014 +changed,3,12,1,cold,0.217 +changed,3,12,1,0,15.886 +changed,3,12,1,1,15.985 +changed,3,12,1,2,16.17 +changed,3,12,1,3,16.055 +changed,3,12,1,4,16.149 +changed,3,24,8,cold,0.666 +changed,3,24,8,0,61.702 +changed,3,24,8,1,61.583 +changed,3,24,8,2,61.616 +changed,3,24,8,3,64.224 +changed,3,24,8,4,64.068 +changed,3,64,8,cold,2.831 +changed,3,64,8,0,341.941 +changed,3,64,8,1,334.288 +changed,3,64,8,2,334.239 +changed,3,64,8,3,334.907 +changed,3,64,8,4,335.666 +changed,3,128,8,cold,7.803 +changed,3,128,8,0,1051.2 +changed,3,128,8,1,1051.09 +changed,3,128,8,2,1067.18 +changed,3,128,8,3,1053.47 +changed,3,128,8,4,1053.51 +changed,3,24,512,cold,0.889 +changed,3,24,512,0,69.879 +changed,3,24,512,1,72.843 +changed,3,24,512,2,72.899 +changed,3,24,512,3,72.69 +changed,3,24,512,4,72.82 +changed,3,64,512,cold,4.36 +changed,3,64,512,0,332.802 +changed,3,64,512,1,333.305 +changed,3,64,512,2,333.076 +changed,3,64,512,3,334.667 +changed,3,64,512,4,333.246 diff --git a/Tools/Benchmarks/FlippedSpritesResults/game-summary.json b/Tools/Benchmarks/FlippedSpritesResults/game-summary.json new file mode 100644 index 0000000000..f6986c5fa1 --- /dev/null +++ b/Tools/Benchmarks/FlippedSpritesResults/game-summary.json @@ -0,0 +1,55 @@ +{ + "baseline": [ + { + "pair": 1, + "simulation_mean_us": 2578.5833333333335, + "simulation_p95_us": 8645, + "color_mean_us": 129.39444444444445, + "color_p95_us": 198, + "travel_mean_us": 2073.9555555555557 + }, + { + "pair": 2, + "simulation_mean_us": 2488.016666666667, + "simulation_p95_us": 8072, + "color_mean_us": 125.9888888888889, + "color_p95_us": 186, + "travel_mean_us": 1989.861111111111 + }, + { + "pair": 3, + "simulation_mean_us": 2534.261111111111, + "simulation_p95_us": 8067, + "color_mean_us": 129.41666666666666, + "color_p95_us": 190, + "travel_mean_us": 2015.75 + } + ], + "changed": [ + { + "pair": 1, + "simulation_mean_us": 2499.6444444444446, + "simulation_p95_us": 8196, + "color_mean_us": 102.86666666666666, + "color_p95_us": 155, + "travel_mean_us": 2015.3111111111111 + }, + { + "pair": 2, + "simulation_mean_us": 2497.438888888889, + "simulation_p95_us": 8177, + "color_mean_us": 102.10555555555555, + "color_p95_us": 156, + "travel_mean_us": 2008.95 + }, + { + "pair": 3, + "simulation_mean_us": 2476.483333333333, + "simulation_p95_us": 8160, + "color_mean_us": 101.06111111111112, + "color_p95_us": 155, + "travel_mean_us": 1998.5555555555557 + } + ], + "particles_equal": true +} diff --git a/Tools/Benchmarks/FlippedSpritesResults/game.csv b/Tools/Benchmarks/FlippedSpritesResults/game.csv new file mode 100644 index 0000000000..414e3fd5e8 --- /dev/null +++ b/Tools/Benchmarks/FlippedSpritesResults/game.csv @@ -0,0 +1,1441 @@ +variant,pair,tick,simulation_us,movable_us,particles,travel_us,color_us,clear_us,grid_wait_us +baseline,1,0,6026,496,508,0,164,149,0 +baseline,1,1,15303,15240,487,14728,111,7,0 +baseline,1,2,11929,11890,455,11540,119,6,0 +baseline,1,3,9947,9889,412,9456,121,4,0 +baseline,1,4,7418,7369,359,7062,116,4,0 +baseline,1,5,5353,5296,314,4933,113,11,0 +baseline,1,6,4206,4155,274,3860,105,8,0 +baseline,1,7,2974,2913,248,2644,91,9,0 +baseline,1,8,2619,2565,242,2321,90,4,0 +baseline,1,9,2040,1989,256,1784,78,7,1 +baseline,1,10,1812,1721,271,1489,86,5,1 +baseline,1,11,1857,1781,361,1528,96,8,0 +baseline,1,12,1574,1484,372,1171,80,4,1 +baseline,1,13,1596,1515,383,1247,82,4,1 +baseline,1,14,1323,1217,391,1045,74,7,1 +baseline,1,15,1404,1352,390,1032,91,6,0 +baseline,1,16,1277,1169,390,932,84,6,0 +baseline,1,17,1201,1154,393,934,75,5,1 +baseline,1,18,1635,1119,413,881,75,3,3 +baseline,1,19,1175,1079,419,847,74,11,1 +baseline,1,20,1199,1126,429,853,80,13,0 +baseline,1,21,1121,1037,425,808,75,3,0 +baseline,1,22,1091,1026,432,815,70,9,1 +baseline,1,23,1093,1035,451,851,73,3,0 +baseline,1,24,1128,1085,448,835,65,3,1 +baseline,1,25,1156,1074,449,785,80,5,1 +baseline,1,26,1068,1020,443,842,69,4,0 +baseline,1,27,1013,968,433,784,68,3,1 +baseline,1,28,1052,972,434,784,69,7,0 +baseline,1,29,1049,962,424,754,60,4,0 +baseline,1,30,1025,942,416,716,69,3,0 +baseline,1,31,1019,922,409,695,69,5,1 +baseline,1,32,1073,986,401,732,71,3,0 +baseline,1,33,1027,971,392,704,74,5,0 +baseline,1,34,1012,921,385,743,64,9,1 +baseline,1,35,981,932,374,714,65,6,0 +baseline,1,36,1055,890,374,665,67,4,0 +baseline,1,37,958,900,367,667,62,7,0 +baseline,1,38,885,820,362,627,57,5,0 +baseline,1,39,924,851,352,654,61,6,1 +baseline,1,40,924,843,342,645,64,5,0 +baseline,1,41,924,848,309,629,62,4,0 +baseline,1,42,1010,896,283,630,62,4,1 +baseline,1,43,960,813,274,621,66,6,0 +baseline,1,44,915,848,267,660,61,4,0 +baseline,1,45,905,854,267,645,63,4,1 +baseline,1,46,916,872,259,654,63,3,0 +baseline,1,47,879,830,251,645,61,8,0 +baseline,1,48,857,777,240,592,60,10,1 +baseline,1,49,880,769,235,564,55,5,1 +baseline,1,50,868,817,237,642,59,3,0 +baseline,1,51,901,812,245,607,60,3,1 +baseline,1,52,858,777,239,572,57,6,0 +baseline,1,53,865,787,229,599,60,7,0 +baseline,1,54,805,762,221,605,51,4,0 +baseline,1,55,815,767,213,612,65,4,0 +baseline,1,56,874,711,203,560,54,4,0 +baseline,1,57,882,786,200,596,53,8,1 +baseline,1,58,758,707,193,562,53,3,0 +baseline,1,59,851,705,190,541,52,3,0 +baseline,1,60,6593,846,696,525,197,4,1 +baseline,1,61,17419,17339,666,16750,179,4,0 +baseline,1,62,12580,12451,630,12033,167,3,0 +baseline,1,63,10700,10640,580,10201,172,5,1 +baseline,1,64,8645,8582,528,8146,158,4,0 +baseline,1,65,6078,6034,506,5635,148,5,0 +baseline,1,66,4842,4791,489,4441,151,4,0 +baseline,1,67,3920,3865,459,3498,141,4,0 +baseline,1,68,3331,3180,420,2860,138,4,0 +baseline,1,69,2607,2546,397,2270,119,4,0 +baseline,1,70,2379,2314,400,1981,144,4,0 +baseline,1,71,2141,2082,454,1822,141,4,0 +baseline,1,72,1986,1935,468,1687,133,5,1 +baseline,1,73,1940,1891,473,1622,124,18,0 +baseline,1,74,1899,1802,475,1543,115,4,0 +baseline,1,75,1715,1591,486,1348,120,5,0 +baseline,1,76,1713,1659,480,1386,123,3,1 +baseline,1,77,1567,1520,473,1272,112,4,1 +baseline,1,78,1629,1532,470,1196,125,5,0 +baseline,1,79,1586,1509,483,1270,103,5,0 +baseline,1,80,1644,1595,481,1261,134,4,0 +baseline,1,81,1657,1524,490,1257,113,10,0 +baseline,1,82,1631,1549,532,1224,114,14,0 +baseline,1,83,1523,1439,566,1212,109,4,0 +baseline,1,84,1584,1524,587,1227,111,11,0 +baseline,1,85,1435,1332,587,1091,107,5,1 +baseline,1,86,1639,1531,583,1163,128,13,0 +baseline,1,87,1535,1358,572,1065,120,5,1 +baseline,1,88,1399,1356,568,1092,121,3,0 +baseline,1,89,1428,1381,565,1080,98,13,0 +baseline,1,90,1355,1306,554,1016,101,4,1 +baseline,1,91,1822,1310,547,1081,96,5,0 +baseline,1,92,1434,1349,547,1037,108,4,1 +baseline,1,93,1338,1250,533,993,104,5,1 +baseline,1,94,1426,1228,530,1002,90,4,1 +baseline,1,95,1379,1277,564,1050,108,4,0 +baseline,1,96,1413,1363,582,1033,113,5,0 +baseline,1,97,1359,1267,561,1002,102,4,1 +baseline,1,98,1323,1236,545,966,107,4,1 +baseline,1,99,1343,1262,537,958,91,5,1 +baseline,1,100,1370,1185,539,954,104,5,1 +baseline,1,101,1407,1359,534,1112,109,8,0 +baseline,1,102,1372,1324,533,1003,100,16,0 +baseline,1,103,1296,1246,524,987,95,8,0 +baseline,1,104,1328,1279,505,986,94,7,0 +baseline,1,105,1235,1158,488,914,99,4,0 +baseline,1,106,1336,1149,483,891,99,5,0 +baseline,1,107,1274,1224,482,987,97,5,1 +baseline,1,108,1306,1257,472,957,101,10,0 +baseline,1,109,1256,1174,447,909,86,12,0 +baseline,1,110,1210,1163,434,938,90,11,0 +baseline,1,111,1157,1111,420,884,84,3,0 +baseline,1,112,1159,1113,406,880,98,3,0 +baseline,1,113,1283,1077,386,851,86,3,0 +baseline,1,114,1157,1109,369,898,85,4,1 +baseline,1,115,1068,1000,358,806,85,4,0 +baseline,1,116,1103,1032,347,816,94,7,1 +baseline,1,117,1101,1050,342,805,93,15,0 +baseline,1,118,1083,1006,333,809,83,11,0 +baseline,1,119,1284,978,332,768,83,4,0 +baseline,1,120,6996,1081,840,739,211,6,0 +baseline,1,121,17592,17547,811,16954,216,9,0 +baseline,1,122,13018,12970,772,12501,186,4,1 +baseline,1,123,10672,10623,720,10070,200,4,0 +baseline,1,124,8138,8038,655,7548,200,8,0 +baseline,1,125,6558,6362,614,5923,207,4,0 +baseline,1,126,5273,5229,581,4755,186,5,0 +baseline,1,127,3961,3911,579,3459,165,4,0 +baseline,1,128,3308,3242,529,2795,176,6,1 +baseline,1,129,2826,2742,514,2376,147,4,0 +baseline,1,130,2693,2620,514,2237,171,5,1 +baseline,1,131,2311,2264,509,1956,158,9,0 +baseline,1,132,2414,2206,507,1907,150,11,1 +baseline,1,133,2186,2137,504,1779,161,3,0 +baseline,1,134,2095,2042,497,1705,133,10,1 +baseline,1,135,2124,2017,511,1701,175,5,1 +baseline,1,136,2011,1925,537,1631,150,3,1 +baseline,1,137,2062,1981,548,1622,144,6,0 +baseline,1,138,1980,1840,552,1531,155,3,0 +baseline,1,139,2143,2033,565,1634,151,6,1 +baseline,1,140,1982,1902,560,1539,159,9,0 +baseline,1,141,1952,1862,552,1464,145,10,0 +baseline,1,142,1831,1756,557,1458,139,13,0 +baseline,1,143,1854,1814,572,1497,139,4,1 +baseline,1,144,1797,1711,582,1415,129,4,0 +baseline,1,145,1978,1754,586,1380,140,4,0 +baseline,1,146,1751,1692,588,1334,130,5,0 +baseline,1,147,1719,1629,579,1316,141,11,1 +baseline,1,148,1707,1668,590,1326,133,4,0 +baseline,1,149,1796,1708,580,1323,114,9,1 +baseline,1,150,1773,1670,571,1318,147,9,0 +baseline,1,151,1711,1645,565,1324,138,11,0 +baseline,1,152,1853,1647,570,1288,126,3,0 +baseline,1,153,1717,1627,572,1323,124,13,0 +baseline,1,154,1585,1498,561,1227,119,7,0 +baseline,1,155,1583,1491,566,1192,136,5,0 +baseline,1,156,1591,1492,565,1200,132,4,1 +baseline,1,157,1498,1434,550,1167,116,7,0 +baseline,1,158,1572,1391,554,1114,124,3,1 +baseline,1,159,1485,1439,551,1114,116,11,1 +baseline,1,160,1508,1420,540,1122,136,7,0 +baseline,1,161,1520,1441,538,1105,122,6,0 +baseline,1,162,1577,1491,539,1157,120,6,1 +baseline,1,163,1414,1376,532,1119,111,8,0 +baseline,1,164,1954,1319,524,1058,106,3,1 +baseline,1,165,1493,1401,513,1104,126,4,0 +baseline,1,166,1418,1326,492,1064,115,13,1 +baseline,1,167,1465,1391,478,1062,119,15,0 +baseline,1,168,1346,1254,478,1005,107,7,1 +baseline,1,169,1392,1311,462,1034,111,4,0 +baseline,1,170,1424,1376,449,1101,117,8,0 +baseline,1,171,1438,1222,447,981,118,3,2 +baseline,1,172,1337,1290,446,1045,117,3,0 +baseline,1,173,1318,1227,434,973,119,6,1 +baseline,1,174,1274,1192,424,970,99,6,0 +baseline,1,175,1464,1377,435,1015,128,4,1 +baseline,1,176,1277,1223,430,981,100,3,1 +baseline,1,177,1397,1205,444,955,111,3,0 +baseline,1,178,1398,1296,440,990,117,5,2 +baseline,1,179,1306,1156,438,919,105,3,0 +baseline,1,180,6457,1239,883,823,231,4,0 +baseline,1,181,16226,16173,860,15492,210,14,1 +baseline,1,182,11904,11868,804,11397,202,3,0 +baseline,1,183,9561,9493,742,9040,200,4,1 +baseline,1,184,7653,7465,696,6996,184,9,0 +baseline,1,185,5909,5844,656,5425,198,5,1 +baseline,1,186,4702,4616,625,4209,169,4,0 +baseline,1,187,3641,3583,584,3126,162,4,0 +baseline,1,188,2840,2760,553,2454,152,8,1 +baseline,1,189,2924,2835,526,2421,150,4,1 +baseline,1,190,2514,2427,510,2096,157,3,0 +baseline,1,191,2528,2377,501,2011,148,3,0 +baseline,1,192,2140,2053,488,1741,140,9,0 +baseline,1,193,2126,2039,498,1680,157,3,1 +baseline,1,194,2022,1936,504,1626,135,4,0 +baseline,1,195,2024,1929,496,1571,157,6,1 +baseline,1,196,1867,1821,480,1518,148,3,0 +baseline,1,197,1904,1858,469,1460,129,3,0 +baseline,1,198,1890,1712,477,1414,143,3,0 +baseline,1,199,1805,1737,469,1443,124,9,1 +baseline,1,200,1696,1645,461,1348,141,4,0 +baseline,1,201,1670,1580,454,1273,129,7,0 +baseline,1,202,1640,1541,447,1245,134,4,1 +baseline,1,203,1565,1517,440,1244,139,3,0 +baseline,1,204,1655,1590,431,1222,125,5,0 +baseline,1,205,1658,1446,423,1127,143,4,0 +baseline,1,206,1574,1483,404,1220,129,7,0 +baseline,1,207,1623,1519,401,1177,135,3,1 +baseline,1,208,1531,1433,419,1152,129,7,1 +baseline,1,209,1521,1475,420,1162,123,4,0 +baseline,1,210,1602,1540,416,1193,136,3,1 +baseline,1,211,1588,1407,406,1100,129,4,1 +baseline,1,212,1473,1428,410,1178,114,7,0 +baseline,1,213,1404,1345,411,1075,122,8,0 +baseline,1,214,1470,1371,406,1070,121,10,0 +baseline,1,215,1527,1431,401,1086,138,9,1 +baseline,1,216,1505,1409,389,1068,116,8,1 +baseline,1,217,1656,1412,379,1020,123,4,1 +baseline,1,218,1433,1363,377,1048,113,14,1 +baseline,1,219,1376,1271,374,1007,113,3,1 +baseline,1,220,1298,1222,374,973,128,9,1 +baseline,1,221,1406,1360,366,1013,109,4,0 +baseline,1,222,1317,1224,363,969,104,14,0 +baseline,1,223,1330,1249,357,975,123,2,0 +baseline,1,224,1442,1270,355,1028,110,2,0 +baseline,1,225,1336,1263,357,1005,110,4,1 +baseline,1,226,1339,1257,363,996,116,3,0 +baseline,1,227,1318,1211,367,957,104,4,1 +baseline,1,228,1379,1335,355,1008,113,6,1 +baseline,1,229,1296,1215,350,959,98,6,0 +baseline,1,230,1433,1334,345,935,127,4,1 +baseline,1,231,1424,1185,345,915,104,3,0 +baseline,1,232,1238,1164,340,928,105,6,0 +baseline,1,233,1234,1186,339,941,110,3,0 +baseline,1,234,1270,1218,331,963,109,13,1 +baseline,1,235,1297,1244,331,973,118,5,0 +baseline,1,236,1268,1212,325,942,112,4,0 +baseline,1,237,1543,1075,314,837,100,2,1 +baseline,1,238,1360,1117,294,846,106,3,0 +baseline,1,239,1275,1124,290,838,94,3,1 +baseline,2,0,6619,558,508,1,153,178,0 +baseline,2,1,15386,15343,487,14859,109,3,0 +baseline,2,2,11481,11435,455,11028,117,3,0 +baseline,2,3,9747,9701,412,9248,119,3,0 +baseline,2,4,7186,7135,359,6816,111,5,0 +baseline,2,5,5508,5444,314,5066,109,12,0 +baseline,2,6,4182,4115,274,3816,95,6,0 +baseline,2,7,2936,2886,248,2624,97,9,1 +baseline,2,8,2613,2524,242,2302,94,4,0 +baseline,2,9,2012,1945,256,1667,86,4,0 +baseline,2,10,1743,1651,271,1450,81,8,1 +baseline,2,11,1680,1583,361,1364,84,6,0 +baseline,2,12,1479,1414,372,1211,73,8,1 +baseline,2,13,1432,1332,383,1123,74,4,0 +baseline,2,14,1302,1242,391,1039,68,12,1 +baseline,2,15,1210,1134,390,946,74,3,2 +baseline,2,16,1222,1117,390,909,80,4,2 +baseline,2,17,1233,1176,393,932,78,4,0 +baseline,2,18,1210,1124,413,881,76,3,0 +baseline,2,19,1130,1036,419,835,67,15,0 +baseline,2,20,1145,1070,429,882,67,5,1 +baseline,2,21,1106,1055,425,862,71,14,0 +baseline,2,22,1141,1041,432,813,75,4,1 +baseline,2,23,1224,1138,451,881,68,9,0 +baseline,2,24,1127,1079,448,832,66,4,0 +baseline,2,25,1075,994,449,766,65,12,0 +baseline,2,26,1116,1011,443,754,64,5,1 +baseline,2,27,1044,947,433,741,63,5,1 +baseline,2,28,1179,1089,434,755,77,9,0 +baseline,2,29,1041,994,424,738,61,7,0 +baseline,2,30,1025,961,416,709,72,7,1 +baseline,2,31,1016,957,409,685,68,4,0 +baseline,2,32,967,902,401,698,62,8,0 +baseline,2,33,1045,958,392,704,67,4,4 +baseline,2,34,1022,918,385,673,67,4,1 +baseline,2,35,1035,908,374,654,69,3,0 +baseline,2,36,1006,912,374,696,63,13,0 +baseline,2,37,914,830,367,639,61,7,0 +baseline,2,38,898,823,362,646,56,4,0 +baseline,2,39,912,832,352,623,57,4,0 +baseline,2,40,923,861,342,634,68,4,0 +baseline,2,41,941,825,309,603,58,4,0 +baseline,2,42,848,766,283,597,56,4,0 +baseline,2,43,907,859,274,662,61,4,1 +baseline,2,44,952,892,267,620,62,12,0 +baseline,2,45,929,867,267,624,71,6,0 +baseline,2,46,1001,934,259,654,71,9,0 +baseline,2,47,918,826,251,590,71,4,0 +baseline,2,48,1043,975,240,660,70,5,1 +baseline,2,49,906,843,235,600,64,6,1 +baseline,2,50,958,879,237,585,71,5,1 +baseline,2,51,920,848,245,609,68,5,0 +baseline,2,52,878,813,239,586,66,4,1 +baseline,2,53,851,800,229,640,56,11,0 +baseline,2,54,1059,876,221,597,62,3,0 +baseline,2,55,931,829,213,611,62,4,1 +baseline,2,56,837,765,203,568,56,4,0 +baseline,2,57,948,839,200,577,56,7,0 +baseline,2,58,842,745,193,545,55,3,0 +baseline,2,59,889,775,190,555,55,4,0 +baseline,2,60,6322,815,696,481,199,4,0 +baseline,2,61,16203,16133,666,15544,183,5,0 +baseline,2,62,11670,11629,630,11196,167,8,0 +baseline,2,63,10178,10134,580,9645,170,7,0 +baseline,2,64,8072,8011,528,7570,164,8,0 +baseline,2,65,5566,5503,506,5135,157,4,0 +baseline,2,66,4704,4564,489,4135,154,4,0 +baseline,2,67,3752,3709,459,3336,134,6,1 +baseline,2,68,3199,3148,420,2724,138,4,0 +baseline,2,69,2537,2494,397,2097,112,4,0 +baseline,2,70,2201,2145,400,1835,132,3,1 +baseline,2,71,2118,2071,454,1700,134,12,1 +baseline,2,72,1973,1917,468,1621,128,10,0 +baseline,2,73,2023,1844,473,1508,124,4,0 +baseline,2,74,1742,1700,475,1433,110,7,0 +baseline,2,75,1643,1574,486,1274,115,4,0 +baseline,2,76,1543,1479,480,1218,125,3,1 +baseline,2,77,1527,1471,473,1187,115,9,0 +baseline,2,78,1567,1484,470,1161,116,4,0 +baseline,2,79,1579,1436,483,1171,106,4,0 +baseline,2,80,1467,1418,481,1165,113,4,0 +baseline,2,81,1500,1410,490,1131,124,3,0 +baseline,2,82,1532,1440,532,1192,106,6,1 +baseline,2,83,1511,1439,566,1142,116,4,0 +baseline,2,84,1493,1395,587,1093,100,4,1 +baseline,2,85,1329,1279,587,1039,105,7,0 +baseline,2,86,1472,1264,583,997,104,4,0 +baseline,2,87,1427,1333,572,1023,107,16,0 +baseline,2,88,1312,1224,568,983,104,6,0 +baseline,2,89,1368,1260,565,993,101,4,0 +baseline,2,90,1302,1222,554,968,103,4,0 +baseline,2,91,1300,1243,547,976,103,5,0 +baseline,2,92,1406,1197,547,973,107,4,1 +baseline,2,93,1373,1266,533,997,98,4,0 +baseline,2,94,1399,1305,530,1032,90,5,0 +baseline,2,95,1293,1219,564,985,101,4,1 +baseline,2,96,1255,1198,582,966,101,8,0 +baseline,2,97,1247,1168,561,918,90,3,0 +baseline,2,98,1234,1167,545,909,104,3,0 +baseline,2,99,1360,1167,537,933,89,4,0 +baseline,2,100,1277,1227,539,941,95,14,0 +baseline,2,101,1268,1191,534,918,99,4,0 +baseline,2,102,1321,1234,533,899,99,10,0 +baseline,2,103,1247,1140,524,888,92,9,1 +baseline,2,104,1268,1175,505,925,90,4,0 +baseline,2,105,1291,1108,488,856,94,4,0 +baseline,2,106,1209,1132,483,901,97,4,0 +baseline,2,107,1206,1139,482,852,88,4,1 +baseline,2,108,1175,1092,472,851,87,4,0 +baseline,2,109,1145,1098,447,878,78,3,0 +baseline,2,110,1186,1087,434,816,88,4,1 +baseline,2,111,1647,1011,420,789,96,3,1 +baseline,2,112,1217,1136,406,863,85,4,1 +baseline,2,113,1142,1059,386,802,85,4,0 +baseline,2,114,1131,1092,369,825,77,6,0 +baseline,2,115,1044,992,358,789,83,4,0 +baseline,2,116,1088,1019,347,758,95,4,0 +baseline,2,117,1081,1020,342,767,90,7,1 +baseline,2,118,1134,939,333,711,84,3,1 +baseline,2,119,1234,1121,332,810,76,12,0 +baseline,2,120,6717,1033,840,670,205,4,0 +baseline,2,121,16461,16389,811,15780,218,4,0 +baseline,2,122,11991,11951,772,11460,194,5,0 +baseline,2,123,10004,9964,720,9402,192,56,0 +baseline,2,124,7611,7470,655,6977,173,4,0 +baseline,2,125,5874,5831,614,5387,192,4,0 +baseline,2,126,4927,4881,581,4480,162,6,0 +baseline,2,127,3789,3734,579,3338,155,4,1 +baseline,2,128,3086,3050,529,2724,150,3,0 +baseline,2,129,2843,2784,514,2363,164,8,0 +baseline,2,130,2520,2472,514,2151,158,3,0 +baseline,2,131,2432,2230,509,1881,147,3,0 +baseline,2,132,2282,2242,507,1883,145,3,0 +baseline,2,133,2085,2004,504,1678,151,7,0 +baseline,2,134,2070,1967,497,1671,141,5,0 +baseline,2,135,2053,1954,511,1647,150,8,0 +baseline,2,136,1986,1931,537,1630,158,9,0 +baseline,2,137,2072,1918,548,1610,152,3,1 +baseline,2,138,1984,1906,552,1517,151,14,0 +baseline,2,139,1977,1934,565,1607,135,6,0 +baseline,2,140,1870,1782,560,1470,150,4,0 +baseline,2,141,1822,1743,552,1446,131,6,1 +baseline,2,142,1924,1815,557,1490,138,8,2 +baseline,2,143,1900,1833,572,1464,139,6,0 +baseline,2,144,1918,1693,582,1390,121,3,0 +baseline,2,145,1786,1724,586,1382,135,3,0 +baseline,2,146,1652,1591,588,1312,126,4,0 +baseline,2,147,1688,1643,579,1313,123,7,0 +baseline,2,148,1672,1604,590,1321,123,17,0 +baseline,2,149,1672,1580,580,1265,125,14,1 +baseline,2,150,1788,1612,571,1278,142,4,0 +baseline,2,151,1691,1636,565,1308,127,9,1 +baseline,2,152,1632,1570,570,1249,123,3,1 +baseline,2,153,1655,1601,572,1261,135,5,1 +baseline,2,154,1521,1438,561,1169,124,4,1 +baseline,2,155,1547,1457,566,1186,127,7,0 +baseline,2,156,1623,1468,565,1155,123,4,2 +baseline,2,157,1574,1499,550,1170,123,6,0 +baseline,2,158,1464,1405,554,1130,125,4,0 +baseline,2,159,1530,1487,551,1210,116,6,0 +baseline,2,160,1588,1519,540,1155,133,5,0 +baseline,2,161,1486,1408,538,1109,132,14,0 +baseline,2,162,1430,1362,539,1089,122,13,0 +baseline,2,163,1554,1350,532,1065,122,4,0 +baseline,2,164,1495,1425,524,1094,107,9,0 +baseline,2,165,1408,1329,513,1052,133,5,1 +baseline,2,166,1401,1345,492,1076,107,5,0 +baseline,2,167,1410,1322,478,1001,113,10,0 +baseline,2,168,1377,1286,478,1013,111,9,1 +baseline,2,169,1441,1303,462,996,101,4,1 +baseline,2,170,1406,1302,449,1012,126,10,1 +baseline,2,171,1363,1318,447,1070,116,8,0 +baseline,2,172,1337,1248,446,979,110,3,1 +baseline,2,173,1338,1239,434,950,115,3,1 +baseline,2,174,1285,1202,424,964,98,4,0 +baseline,2,175,1422,1340,435,995,126,4,0 +baseline,2,176,1422,1210,430,952,102,4,0 +baseline,2,177,1297,1215,444,952,110,3,0 +baseline,2,178,1277,1197,440,937,114,4,1 +baseline,2,179,1221,1118,438,888,99,3,1 +baseline,2,180,6648,1274,883,838,204,5,0 +baseline,2,181,16138,16064,860,15474,208,14,0 +baseline,2,182,12189,12043,804,11542,186,3,0 +baseline,2,183,9548,9496,742,9019,186,2,0 +baseline,2,184,7854,7415,696,6995,167,7,1 +baseline,2,185,5910,5870,656,5465,192,3,0 +baseline,2,186,4646,4572,625,4098,180,4,0 +baseline,2,187,3549,3485,584,3097,160,6,1 +baseline,2,188,2878,2740,553,2423,149,3,0 +baseline,2,189,2644,2555,526,2261,136,10,1 +baseline,2,190,2523,2436,510,2099,159,4,1 +baseline,2,191,2411,2354,501,1975,153,6,0 +baseline,2,192,2148,2058,488,1752,141,3,1 +baseline,2,193,2056,1967,498,1659,139,7,0 +baseline,2,194,2074,1975,504,1662,136,10,0 +baseline,2,195,2112,1891,496,1545,142,3,0 +baseline,2,196,1874,1787,480,1483,146,9,1 +baseline,2,197,1787,1706,469,1390,136,4,1 +baseline,2,198,1891,1802,477,1400,145,4,0 +baseline,2,199,1776,1696,469,1327,130,3,1 +baseline,2,200,1738,1662,461,1284,149,3,0 +baseline,2,201,1686,1606,454,1284,132,4,0 +baseline,2,202,1641,1433,447,1170,127,3,0 +baseline,2,203,1666,1570,440,1253,138,8,1 +baseline,2,204,1565,1480,431,1223,112,9,3 +baseline,2,205,1554,1459,423,1169,141,4,1 +baseline,2,206,1567,1483,404,1153,128,3,0 +baseline,2,207,1584,1484,401,1152,124,5,1 +baseline,2,208,1510,1442,419,1183,125,7,0 +baseline,2,209,1509,1347,420,1092,125,4,1 +baseline,2,210,1612,1505,416,1167,131,5,1 +baseline,2,211,1445,1392,406,1097,122,7,0 +baseline,2,212,1409,1335,410,1084,120,10,0 +baseline,2,213,1522,1436,411,1089,128,8,1 +baseline,2,214,1396,1306,406,1060,114,4,0 +baseline,2,215,1557,1330,401,1064,132,3,1 +baseline,2,216,1451,1362,389,1094,120,13,0 +baseline,2,217,1328,1237,379,986,112,12,0 +baseline,2,218,1282,1199,377,971,110,3,0 +baseline,2,219,1334,1254,374,1007,113,3,1 +baseline,2,220,1317,1244,374,1000,117,6,1 +baseline,2,221,1411,1345,366,1027,111,4,0 +baseline,2,222,1390,1210,363,940,126,3,0 +baseline,2,223,1366,1269,357,972,118,3,1 +baseline,2,224,1361,1294,355,1014,106,10,0 +baseline,2,225,1282,1208,357,958,115,2,0 +baseline,2,226,1251,1211,363,964,116,3,0 +baseline,2,227,1301,1224,367,953,102,4,1 +baseline,2,228,1584,1228,355,971,114,4,0 +baseline,2,229,1331,1233,350,952,97,9,0 +baseline,2,230,1261,1157,345,925,113,3,0 +baseline,2,231,1267,1153,345,900,113,7,1 +baseline,2,232,1239,1184,340,917,107,4,1 +baseline,2,233,1219,1132,339,887,105,7,2 +baseline,2,234,1371,1164,331,913,100,3,0 +baseline,2,235,1248,1152,331,903,110,8,0 +baseline,2,236,1297,1216,325,874,119,7,1 +baseline,2,237,1223,1139,314,870,103,4,0 +baseline,2,238,1255,1188,294,868,101,6,1 +baseline,2,239,1196,1104,290,882,94,6,0 +baseline,3,0,6580,557,508,0,162,167,0 +baseline,3,1,15379,15328,487,14785,105,4,0 +baseline,3,2,11463,11423,455,10991,114,7,0 +baseline,3,3,9757,9720,412,9315,121,3,0 +baseline,3,4,7587,7527,359,7144,112,4,0 +baseline,3,5,5360,5310,314,4948,107,10,0 +baseline,3,6,4285,4222,274,3808,101,9,0 +baseline,3,7,3009,2939,248,2631,97,4,0 +baseline,3,8,2701,2642,242,2345,87,5,0 +baseline,3,9,2038,1988,256,1754,75,4,1 +baseline,3,10,1825,1724,271,1460,84,4,1 +baseline,3,11,1680,1598,361,1362,83,13,0 +baseline,3,12,1483,1384,372,1178,71,5,0 +baseline,3,13,1431,1349,383,1127,77,4,0 +baseline,3,14,1418,1320,391,1031,72,4,0 +baseline,3,15,1289,1172,390,939,81,4,0 +baseline,3,16,1152,1110,390,904,74,3,0 +baseline,3,17,1134,1069,393,872,70,5,0 +baseline,3,18,1220,1131,413,903,75,4,0 +baseline,3,19,1209,1167,419,935,73,6,0 +baseline,3,20,1081,1030,429,845,70,4,1 +baseline,3,21,1243,1170,425,859,87,6,0 +baseline,3,22,1219,1123,432,883,74,21,1 +baseline,3,23,1197,1134,451,879,77,5,0 +baseline,3,24,1070,1019,448,799,69,9,1 +baseline,3,25,1152,1040,449,802,79,10,1 +baseline,3,26,1153,1048,443,809,77,10,0 +baseline,3,27,1047,968,433,727,66,4,1 +baseline,3,28,1111,1017,434,736,63,9,0 +baseline,3,29,1083,1014,424,812,65,8,0 +baseline,3,30,1072,983,416,728,72,6,1 +baseline,3,31,1005,921,409,672,73,4,0 +baseline,3,32,970,895,401,687,61,4,1 +baseline,3,33,991,903,392,689,71,9,2 +baseline,3,34,1091,1007,385,730,67,5,0 +baseline,3,35,1032,884,374,643,64,4,0 +baseline,3,36,919,857,374,677,61,6,0 +baseline,3,37,933,854,367,641,65,4,1 +baseline,3,38,897,845,362,668,58,7,1 +baseline,3,39,915,842,352,640,59,7,1 +baseline,3,40,910,811,342,628,58,4,1 +baseline,3,41,929,853,309,627,61,14,0 +baseline,3,42,926,806,283,600,62,7,0 +baseline,3,43,907,817,274,588,63,10,1 +baseline,3,44,879,792,267,610,59,8,1 +baseline,3,45,786,734,267,578,72,4,1 +baseline,3,46,947,882,259,650,64,8,1 +baseline,3,47,869,777,251,578,58,4,0 +baseline,3,48,882,743,240,550,58,7,1 +baseline,3,49,839,760,235,558,53,9,1 +baseline,3,50,800,738,237,559,62,5,0 +baseline,3,51,778,725,245,580,60,4,0 +baseline,3,52,837,768,239,564,56,4,0 +baseline,3,53,861,785,229,589,56,12,0 +baseline,3,54,812,725,221,554,52,7,1 +baseline,3,55,951,751,213,551,56,4,0 +baseline,3,56,876,780,203,568,58,4,0 +baseline,3,57,842,779,200,569,56,4,0 +baseline,3,58,785,721,193,526,53,3,0 +baseline,3,59,898,779,190,521,49,3,0 +baseline,3,60,6264,787,696,470,182,3,0 +baseline,3,61,16159,16068,666,15539,173,8,0 +baseline,3,62,12004,11870,630,11416,163,3,0 +baseline,3,63,9957,9902,580,9410,165,3,0 +baseline,3,64,8067,8002,528,7550,152,4,0 +baseline,3,65,5631,5588,506,5207,153,7,1 +baseline,3,66,4574,4517,489,4149,140,3,0 +baseline,3,67,3785,3746,459,3371,126,4,0 +baseline,3,68,3169,3023,420,2640,128,4,0 +baseline,3,69,2482,2427,397,2095,110,6,0 +baseline,3,70,2291,2201,400,1814,136,4,1 +baseline,3,71,2050,1982,454,1690,122,8,0 +baseline,3,72,1972,1887,468,1590,124,6,1 +baseline,3,73,1967,1879,473,1504,129,4,0 +baseline,3,74,1903,1737,475,1417,109,4,1 +baseline,3,75,1706,1609,486,1295,124,5,0 +baseline,3,76,1623,1552,480,1236,116,17,0 +baseline,3,77,1554,1469,473,1194,109,8,0 +baseline,3,78,1533,1452,470,1166,115,4,0 +baseline,3,79,1508,1455,483,1164,96,4,1 +baseline,3,80,1603,1429,481,1160,121,4,0 +baseline,3,81,1506,1428,490,1125,105,4,1 +baseline,3,82,1516,1430,532,1174,109,4,0 +baseline,3,83,1574,1497,566,1170,110,8,1 +baseline,3,84,1492,1442,587,1134,102,4,0 +baseline,3,85,1423,1319,587,1051,104,6,0 +baseline,3,86,1409,1360,583,1104,114,4,0 +baseline,3,87,1425,1264,572,983,98,10,0 +baseline,3,88,1445,1361,568,1022,108,4,1 +baseline,3,89,1320,1245,565,990,106,5,1 +baseline,3,90,2300,2171,554,1698,181,8,1 +baseline,3,91,2034,1843,547,1448,143,8,0 +baseline,3,92,1663,1546,547,1127,124,5,0 +baseline,3,93,1580,1509,533,1059,145,6,0 +baseline,3,94,1362,1300,530,1053,99,12,0 +baseline,3,95,1391,1329,564,1087,101,5,1 +baseline,3,96,1367,1190,582,951,103,7,0 +baseline,3,97,1205,1154,561,903,96,4,0 +baseline,3,98,1381,1313,545,1034,106,4,1 +baseline,3,99,1433,1376,537,1034,100,5,0 +baseline,3,100,1318,1219,539,923,106,5,0 +baseline,3,101,1303,1222,534,946,92,11,1 +baseline,3,102,1397,1190,533,941,103,4,0 +baseline,3,103,1289,1221,524,901,100,18,0 +baseline,3,104,1284,1184,505,879,98,12,1 +baseline,3,105,1225,1127,488,853,86,4,2 +baseline,3,106,1280,1170,483,859,95,4,0 +baseline,3,107,1270,1190,482,880,84,5,0 +baseline,3,108,1229,1163,472,904,100,15,0 +baseline,3,109,1297,1092,447,806,79,4,0 +baseline,3,110,1222,1161,434,857,107,4,0 +baseline,3,111,1612,1109,420,829,99,6,1 +baseline,3,112,1250,1138,406,849,102,5,0 +baseline,3,113,1219,1102,386,812,99,5,0 +baseline,3,114,1136,1026,369,770,88,5,2 +baseline,3,115,1156,937,358,743,83,5,0 +baseline,3,116,1133,1072,347,805,103,5,0 +baseline,3,117,1095,1039,342,775,104,4,1 +baseline,3,118,1095,977,333,751,87,6,1 +baseline,3,119,1065,936,332,733,86,3,1 +baseline,3,120,6293,1074,840,678,235,5,1 +baseline,3,121,17152,16933,811,16254,218,8,1 +baseline,3,122,12062,11991,772,11420,198,9,1 +baseline,3,123,10874,10792,720,10246,211,4,2 +baseline,3,124,7833,7725,655,7144,208,5,1 +baseline,3,125,6410,6310,614,5822,196,11,0 +baseline,3,126,5027,4924,581,4500,192,5,1 +baseline,3,127,4339,4113,579,3652,176,4,0 +baseline,3,128,3285,3194,529,2790,180,9,0 +baseline,3,129,2743,2659,514,2341,157,6,1 +baseline,3,130,2633,2531,514,2149,178,5,0 +baseline,3,131,2342,2245,509,1904,165,6,0 +baseline,3,132,2313,2241,507,1865,157,7,1 +baseline,3,133,2162,2072,504,1676,154,3,1 +baseline,3,134,2098,1895,497,1615,156,3,0 +baseline,3,135,2141,2073,511,1661,163,8,1 +baseline,3,136,2039,1955,537,1582,155,4,1 +baseline,3,137,2066,1991,548,1610,149,7,0 +baseline,3,138,2072,1977,552,1665,150,4,0 +baseline,3,139,2297,2222,565,1894,140,4,1 +baseline,3,140,2353,2227,560,1871,144,8,1 +baseline,3,141,1899,1800,552,1439,147,3,1 +baseline,3,142,1870,1811,557,1468,135,14,1 +baseline,3,143,1842,1783,572,1450,146,11,0 +baseline,3,144,1724,1645,582,1355,129,4,0 +baseline,3,145,1895,1841,586,1449,161,4,0 +baseline,3,146,1690,1638,588,1322,142,3,0 +baseline,3,147,1780,1549,579,1248,130,4,0 +baseline,3,148,1837,1748,590,1350,130,9,0 +baseline,3,149,1662,1563,580,1243,118,3,0 +baseline,3,150,1675,1608,571,1264,143,4,1 +baseline,3,151,1596,1512,565,1242,131,4,0 +baseline,3,152,1583,1515,570,1235,124,4,0 +baseline,3,153,1588,1491,572,1210,140,5,1 +baseline,3,154,1725,1458,561,1151,124,4,1 +baseline,3,155,1629,1528,566,1177,143,8,0 +baseline,3,156,1903,1811,565,1519,128,5,1 +baseline,3,157,1583,1503,550,1221,127,4,0 +baseline,3,158,1530,1446,554,1118,132,10,0 +baseline,3,159,1436,1391,551,1136,113,4,1 +baseline,3,160,1856,1677,540,1324,136,5,1 +baseline,3,161,1801,1721,538,1394,127,4,0 +baseline,3,162,1447,1374,539,1064,111,3,1 +baseline,3,163,1564,1473,532,1097,120,10,1 +baseline,3,164,1458,1370,524,1064,106,13,0 +baseline,3,165,1432,1346,513,1059,128,11,0 +baseline,3,166,1559,1316,492,1002,116,4,1 +baseline,3,167,1320,1264,478,1005,115,3,1 +baseline,3,168,1334,1252,478,991,115,3,1 +baseline,3,169,1484,1439,462,1100,109,4,0 +baseline,3,170,1370,1266,449,976,123,11,1 +baseline,3,171,1352,1245,447,984,115,5,2 +baseline,3,172,1416,1368,446,1036,117,5,0 +baseline,3,173,1417,1221,434,920,109,6,0 +baseline,3,174,1325,1215,424,971,105,5,1 +baseline,3,175,1407,1303,435,986,117,6,0 +baseline,3,176,1363,1260,430,967,108,6,1 +baseline,3,177,1284,1194,444,938,111,4,0 +baseline,3,178,1264,1209,440,962,106,5,1 +baseline,3,179,1439,1126,438,880,97,3,1 +baseline,3,180,6594,1244,883,828,226,4,1 +baseline,3,181,16287,16215,860,15576,191,16,0 +baseline,3,182,11837,11787,804,11296,176,4,1 +baseline,3,183,9604,9547,742,9065,189,6,1 +baseline,3,184,7812,7355,696,6936,190,5,0 +baseline,3,185,6004,5857,656,5428,190,3,1 +baseline,3,186,4705,4613,625,4156,168,4,1 +baseline,3,187,3595,3508,584,3101,147,10,0 +baseline,3,188,2926,2848,553,2461,178,7,0 +baseline,3,189,2742,2649,526,2295,149,5,0 +baseline,3,190,2526,2462,510,2124,156,6,1 +baseline,3,191,2424,2333,501,1969,146,4,1 +baseline,3,192,2256,2111,488,1754,137,5,0 +baseline,3,193,2123,2058,498,1666,130,4,0 +baseline,3,194,1948,1869,504,1564,126,4,0 +baseline,3,195,1962,1869,496,1549,150,3,1 +baseline,3,196,1872,1778,480,1452,140,14,1 +baseline,3,197,1810,1760,469,1433,147,4,0 +baseline,3,198,1857,1683,477,1378,145,14,0 +baseline,3,199,1718,1608,469,1333,129,4,0 +baseline,3,200,1801,1698,461,1313,138,3,0 +baseline,3,201,1692,1645,454,1305,144,3,0 +baseline,3,202,1544,1456,447,1188,128,10,0 +baseline,3,203,1603,1506,440,1187,142,3,1 +baseline,3,204,1581,1479,431,1181,115,4,1 +baseline,3,205,1671,1411,423,1125,141,4,1 +baseline,3,206,1581,1497,404,1193,129,11,1 +baseline,3,207,1486,1413,401,1131,125,7,1 +baseline,3,208,1641,1546,419,1177,124,6,1 +baseline,3,209,1533,1434,420,1122,120,3,1 +baseline,3,210,1475,1414,416,1137,140,5,0 +baseline,3,211,1529,1471,406,1188,119,3,0 +baseline,3,212,1566,1342,410,1051,126,4,1 +baseline,3,213,1429,1331,411,1073,115,5,1 +baseline,3,214,1485,1374,406,1037,114,4,1 +baseline,3,215,1372,1299,401,1033,123,7,0 +baseline,3,216,1378,1302,389,1029,118,7,1 +baseline,3,217,1328,1232,379,996,121,4,0 +baseline,3,218,1383,1196,377,942,124,3,1 +baseline,3,219,1279,1194,374,944,109,3,0 +baseline,3,220,1310,1220,374,959,122,4,0 +baseline,3,221,1317,1222,366,946,124,4,1 +baseline,3,222,1269,1204,363,956,113,6,0 +baseline,3,223,1271,1206,357,948,115,4,0 +baseline,3,224,1276,1215,355,973,102,4,0 +baseline,3,225,1465,1272,357,999,120,4,0 +baseline,3,226,1342,1241,363,959,114,10,0 +baseline,3,227,1360,1288,367,963,102,3,0 +baseline,3,228,1316,1231,355,937,115,4,0 +baseline,3,229,1267,1179,350,898,95,10,0 +baseline,3,230,1290,1195,345,914,117,7,2 +baseline,3,231,1408,1172,345,898,113,3,1 +baseline,3,232,1297,1221,340,914,109,3,1 +baseline,3,233,1179,1124,339,889,107,7,0 +baseline,3,234,1155,1089,331,860,94,2,0 +baseline,3,235,1228,1148,331,914,122,4,0 +baseline,3,236,1245,1190,325,967,109,14,0 +baseline,3,237,1275,1165,314,869,111,5,0 +baseline,3,238,1361,1119,294,829,103,3,0 +baseline,3,239,1201,1055,290,831,99,3,0 +changed,1,0,6657,521,508,1,134,162,0 +changed,1,1,15610,15565,487,15007,100,9,0 +changed,1,2,11784,11744,455,11386,104,7,1 +changed,1,3,9853,9814,412,9443,109,4,0 +changed,1,4,7431,7362,359,7038,105,6,1 +changed,1,5,5410,5364,314,5009,99,7,0 +changed,1,6,4163,4113,274,3806,87,12,1 +changed,1,7,3004,2921,248,2614,88,3,0 +changed,1,8,2630,2536,242,2305,79,13,0 +changed,1,9,2006,1919,256,1655,70,4,0 +changed,1,10,1760,1709,271,1468,74,4,1 +changed,1,11,1791,1732,361,1498,71,3,1 +changed,1,12,1470,1400,372,1206,62,6,0 +changed,1,13,1507,1438,383,1175,76,6,0 +changed,1,14,1385,1325,391,1076,71,6,0 +changed,1,15,1360,1295,390,1015,80,4,0 +changed,1,16,1186,1138,390,953,67,4,1 +changed,1,17,1262,1118,393,874,69,4,0 +changed,1,18,1163,1088,413,884,63,15,0 +changed,1,19,1298,1247,419,950,67,4,0 +changed,1,20,1221,1127,429,871,65,5,1 +changed,1,21,1092,1016,425,829,67,3,0 +changed,1,22,1119,1075,432,859,62,4,0 +changed,1,23,1098,997,451,797,61,4,0 +changed,1,24,1055,1007,448,806,61,4,1 +changed,1,25,1106,1002,449,793,66,4,0 +changed,1,26,1081,990,443,752,63,9,1 +changed,1,27,1046,980,433,759,62,7,0 +changed,1,28,1035,987,434,789,56,8,5 +changed,1,29,1048,1001,424,778,55,5,0 +changed,1,30,1032,957,416,750,60,7,1 +changed,1,31,1013,913,409,681,56,4,0 +changed,1,32,1067,1022,401,739,59,14,0 +changed,1,33,1006,919,392,659,56,4,1 +changed,1,34,921,876,385,701,61,4,0 +changed,1,35,1051,957,374,665,60,7,1 +changed,1,36,1036,878,374,673,54,3,0 +changed,1,37,971,880,367,671,62,3,1 +changed,1,38,899,815,362,633,49,3,0 +changed,1,39,930,887,352,638,51,4,1 +changed,1,40,990,918,342,634,57,3,0 +changed,1,41,899,810,309,623,54,4,0 +changed,1,42,964,820,283,590,48,3,1 +changed,1,43,911,807,274,623,53,4,1 +changed,1,44,866,816,267,632,48,4,0 +changed,1,45,881,790,267,597,58,3,1 +changed,1,46,875,822,259,577,52,4,0 +changed,1,47,878,802,251,573,61,6,0 +changed,1,48,885,832,240,635,46,4,0 +changed,1,49,889,754,235,553,46,6,0 +changed,1,50,823,777,237,608,52,3,0 +changed,1,51,877,827,245,611,57,9,0 +changed,1,52,795,720,239,563,46,3,0 +changed,1,53,842,745,229,595,47,3,1 +changed,1,54,848,799,221,582,45,4,0 +changed,1,55,841,743,213,564,47,11,0 +changed,1,56,880,742,203,569,42,6,0 +changed,1,57,864,799,200,641,47,3,0 +changed,1,58,883,808,193,552,43,8,0 +changed,1,59,896,795,190,598,39,8,0 +changed,1,60,6510,764,696,475,162,4,0 +changed,1,61,16744,16643,666,16040,153,5,1 +changed,1,62,11977,11827,630,11391,135,2,0 +changed,1,63,10163,10111,580,9690,144,6,0 +changed,1,64,8196,8141,528,7685,129,3,0 +changed,1,65,5787,5743,506,5319,128,4,0 +changed,1,66,4568,4506,489,4170,126,5,0 +changed,1,67,3795,3744,459,3369,119,3,0 +changed,1,68,3082,3021,420,2718,111,4,0 +changed,1,69,2516,2353,397,2081,96,3,0 +changed,1,70,2202,2115,400,1880,101,4,0 +changed,1,71,1998,1923,454,1661,109,3,1 +changed,1,72,1973,1907,468,1623,112,4,0 +changed,1,73,1888,1802,473,1514,97,5,0 +changed,1,74,1849,1764,475,1450,91,4,0 +changed,1,75,1688,1617,486,1315,95,4,0 +changed,1,76,1583,1456,480,1232,93,3,1 +changed,1,77,1552,1475,473,1226,93,6,1 +changed,1,78,1433,1337,470,1126,90,4,0 +changed,1,79,1501,1402,483,1168,85,13,0 +changed,1,80,1617,1514,481,1265,93,10,0 +changed,1,81,1415,1314,490,1119,80,4,1 +changed,1,82,1528,1417,532,1162,96,9,0 +changed,1,83,1493,1388,566,1152,92,9,1 +changed,1,84,1449,1360,587,1065,81,4,0 +changed,1,85,1428,1377,587,1066,86,4,1 +changed,1,86,1298,1230,583,1003,85,6,0 +changed,1,87,1382,1300,572,990,96,5,0 +changed,1,88,1392,1308,568,1019,87,15,0 +changed,1,89,1405,1227,565,973,79,6,0 +changed,1,90,1253,1179,554,958,80,6,0 +changed,1,91,1337,1248,547,990,79,8,0 +changed,1,92,1298,1207,547,981,87,7,0 +changed,1,93,1315,1265,533,993,88,8,0 +changed,1,94,1231,1184,530,978,78,6,1 +changed,1,95,1278,1217,564,988,89,7,1 +changed,1,96,1410,1225,582,955,79,4,0 +changed,1,97,1333,1274,561,935,82,3,1 +changed,1,98,1289,1227,545,930,80,4,0 +changed,1,99,1183,1131,537,898,72,7,1 +changed,1,100,1321,1211,539,941,84,5,0 +changed,1,101,1264,1169,534,930,91,7,0 +changed,1,102,1189,1107,533,895,74,4,2 +changed,1,103,1366,1153,524,873,78,4,1 +changed,1,104,1141,1079,505,877,70,7,1 +changed,1,105,1253,1158,488,880,79,16,0 +changed,1,106,1186,1117,483,906,75,8,0 +changed,1,107,1224,1138,482,884,74,6,0 +changed,1,108,1172,1122,472,892,73,13,0 +changed,1,109,1306,1081,447,824,66,4,0 +changed,1,110,1135,1043,434,835,68,3,0 +changed,1,111,1599,1101,420,785,74,4,1 +changed,1,112,1102,1038,406,822,72,4,0 +changed,1,113,1109,1021,386,806,80,4,1 +changed,1,114,1109,1066,369,790,67,3,0 +changed,1,115,1042,953,358,769,70,4,0 +changed,1,116,1213,981,347,739,67,20,0 +changed,1,117,1070,987,342,771,65,12,0 +changed,1,118,1089,1010,333,754,72,5,0 +changed,1,119,1046,901,332,736,65,3,1 +changed,1,120,6907,1098,840,690,182,3,0 +changed,1,121,16983,16898,811,16235,183,14,1 +changed,1,122,12255,12064,772,11601,163,3,0 +changed,1,123,10080,10030,720,9546,164,3,0 +changed,1,124,7685,7642,655,7193,142,3,0 +changed,1,125,5963,5899,614,5473,169,4,1 +changed,1,126,5015,4968,581,4553,150,3,1 +changed,1,127,3812,3755,579,3414,137,4,1 +changed,1,128,3294,3252,529,2814,127,3,0 +changed,1,129,2899,2687,514,2320,128,3,0 +changed,1,130,2597,2531,514,2182,132,9,0 +changed,1,131,2372,2332,509,1941,124,11,0 +changed,1,132,2287,2211,507,1850,121,4,1 +changed,1,133,2159,2064,504,1718,132,15,0 +changed,1,134,2061,1962,497,1673,115,8,1 +changed,1,135,2084,1992,511,1687,131,6,0 +changed,1,136,2153,1963,537,1620,121,3,0 +changed,1,137,2072,1985,548,1659,124,10,0 +changed,1,138,1910,1860,552,1576,128,4,0 +changed,1,139,1975,1876,565,1568,112,3,0 +changed,1,140,1849,1784,560,1518,112,9,0 +changed,1,141,1935,1875,552,1558,122,6,0 +changed,1,142,1706,1668,557,1402,116,3,0 +changed,1,143,1940,1728,572,1422,113,5,0 +changed,1,144,1782,1681,582,1422,95,5,0 +changed,1,145,1828,1777,586,1530,117,5,0 +changed,1,146,1746,1694,588,1449,106,5,0 +changed,1,147,1701,1630,579,1351,109,4,1 +changed,1,148,1697,1591,590,1279,110,7,1 +changed,1,149,1652,1557,580,1285,101,10,1 +changed,1,150,1815,1583,571,1274,114,3,0 +changed,1,151,1747,1675,565,1414,103,4,0 +changed,1,152,1677,1590,570,1294,99,10,0 +changed,1,153,1650,1557,572,1246,106,10,0 +changed,1,154,1511,1423,561,1176,99,4,1 +changed,1,155,1506,1419,566,1160,105,7,0 +changed,1,156,1529,1467,565,1201,98,7,0 +changed,1,157,1766,1547,550,1251,106,4,0 +changed,1,158,1572,1507,554,1216,103,5,0 +changed,1,159,1561,1468,551,1195,99,9,0 +changed,1,160,1498,1401,540,1116,103,4,0 +changed,1,161,1375,1281,538,1062,98,4,0 +changed,1,162,1383,1331,539,1072,97,6,0 +changed,1,163,1481,1379,532,1096,95,4,0 +changed,1,164,1533,1305,524,1044,87,4,1 +changed,1,165,1454,1348,513,1093,98,11,0 +changed,1,166,1468,1375,492,1088,91,14,1 +changed,1,167,1292,1245,478,999,91,6,0 +changed,1,168,1340,1298,478,1070,91,4,0 +changed,1,169,1422,1354,462,1095,87,5,1 +changed,1,170,1353,1261,449,1031,88,7,1 +changed,1,171,1471,1243,447,973,101,3,0 +changed,1,172,1401,1309,446,1027,91,20,0 +changed,1,173,1264,1172,434,952,83,9,1 +changed,1,174,1319,1228,424,966,89,4,1 +changed,1,175,1372,1272,435,1005,90,7,1 +changed,1,176,1293,1218,430,963,81,8,0 +changed,1,177,1341,1148,444,931,84,3,0 +changed,1,178,1224,1132,440,903,80,6,0 +changed,1,179,1350,1221,438,950,90,4,1 +changed,1,180,6667,1237,883,853,176,3,0 +changed,1,181,16440,16341,860,15821,174,5,1 +changed,1,182,12115,12072,804,11612,155,11,0 +changed,1,183,9827,9678,742,9239,155,4,0 +changed,1,184,7948,7534,696,7075,145,3,1 +changed,1,185,5958,5918,656,5547,154,6,0 +changed,1,186,4682,4626,625,4169,146,4,0 +changed,1,187,3563,3505,584,3140,137,7,1 +changed,1,188,2891,2820,553,2451,119,4,0 +changed,1,189,2884,2713,526,2334,124,3,0 +changed,1,190,2516,2426,510,2106,138,5,1 +changed,1,191,2390,2307,501,1969,128,3,0 +changed,1,192,2162,2079,488,1780,112,3,0 +changed,1,193,2075,1973,498,1690,129,8,0 +changed,1,194,1937,1850,504,1607,100,5,0 +changed,1,195,1946,1864,496,1566,129,3,1 +changed,1,196,1927,1700,480,1444,115,10,0 +changed,1,197,1892,1823,469,1510,112,4,0 +changed,1,198,1810,1721,477,1424,116,13,0 +changed,1,199,1735,1647,469,1341,99,12,0 +changed,1,200,1771,1679,461,1340,114,18,1 +changed,1,201,1578,1527,454,1260,106,4,0 +changed,1,202,1641,1471,447,1193,104,3,0 +changed,1,203,1518,1450,440,1210,109,6,1 +changed,1,204,1472,1394,431,1172,91,4,0 +changed,1,205,1524,1423,423,1136,108,9,1 +changed,1,206,1504,1433,404,1158,101,3,0 +changed,1,207,1592,1530,401,1300,97,4,1 +changed,1,208,1583,1485,419,1216,100,12,0 +changed,1,209,1490,1340,420,1114,100,4,1 +changed,1,210,1586,1494,416,1155,102,14,0 +changed,1,211,1526,1426,406,1152,101,17,0 +changed,1,212,1384,1303,410,1069,100,5,0 +changed,1,213,1462,1359,411,1075,97,8,1 +changed,1,214,1389,1284,406,1045,87,6,0 +changed,1,215,1448,1353,401,1069,107,8,0 +changed,1,216,1537,1314,389,1058,93,3,1 +changed,1,217,1411,1332,379,1036,88,11,0 +changed,1,218,1315,1207,377,976,91,19,0 +changed,1,219,1302,1197,374,974,88,8,0 +changed,1,220,1316,1209,374,976,105,7,2 +changed,1,221,1245,1188,366,965,86,4,0 +changed,1,222,1389,1333,363,1061,88,7,0 +changed,1,223,1491,1261,357,983,98,3,0 +changed,1,224,1283,1223,355,986,81,2,1 +changed,1,225,1305,1259,357,1030,80,3,1 +changed,1,226,1289,1191,363,947,97,4,1 +changed,1,227,1379,1278,367,952,85,10,0 +changed,1,228,1316,1212,355,940,87,9,0 +changed,1,229,1270,1185,350,937,77,7,1 +changed,1,230,1482,1213,345,903,99,4,1 +changed,1,231,1355,1260,345,947,89,15,0 +changed,1,232,1312,1219,340,941,89,3,0 +changed,1,233,1193,1116,339,880,83,4,1 +changed,1,234,1174,1105,331,889,72,4,0 +changed,1,235,1206,1110,331,895,91,3,0 +changed,1,236,1211,1159,325,931,83,4,0 +changed,1,237,1281,1060,314,839,81,3,0 +changed,1,238,1216,1140,294,892,77,14,0 +changed,1,239,1183,1039,290,822,66,2,1 +changed,2,0,6159,533,508,0,139,173,0 +changed,2,1,15469,15419,487,14876,98,4,0 +changed,2,2,11575,11532,455,11139,105,5,0 +changed,2,3,9868,9821,412,9463,108,4,0 +changed,2,4,7351,7311,359,6982,97,11,0 +changed,2,5,5392,5305,314,5007,94,4,0 +changed,2,6,4156,4109,274,3780,93,4,1 +changed,2,7,3093,3032,248,2770,79,7,0 +changed,2,8,2729,2664,242,2377,83,7,1 +changed,2,9,2059,1993,256,1712,65,4,0 +changed,2,10,1716,1611,271,1424,74,4,0 +changed,2,11,1694,1617,361,1380,66,7,0 +changed,2,12,1524,1474,372,1284,63,9,0 +changed,2,13,1548,1453,383,1172,81,7,1 +changed,2,14,1371,1270,391,1049,68,3,1 +changed,2,15,1203,1141,390,962,66,7,0 +changed,2,16,1215,1121,390,928,65,3,0 +changed,2,17,1238,1130,393,910,75,9,0 +changed,2,18,1269,1200,413,960,63,4,0 +changed,2,19,1174,1081,419,859,60,4,0 +changed,2,20,1203,1121,429,832,65,12,0 +changed,2,21,1163,1053,425,851,60,4,0 +changed,2,22,1126,1033,432,848,62,5,0 +changed,2,23,1097,1012,451,804,57,6,0 +changed,2,24,1074,1022,448,825,67,5,0 +changed,2,25,1102,989,449,778,60,8,1 +changed,2,26,1099,1049,443,824,60,4,0 +changed,2,27,1043,958,433,770,57,4,1 +changed,2,28,1117,1034,434,792,54,13,1 +changed,2,29,1079,973,424,750,55,20,2 +changed,2,30,1095,927,416,697,58,4,1 +changed,2,31,1032,923,409,686,56,10,2 +changed,2,32,995,904,401,707,54,4,0 +changed,2,33,1030,949,392,684,55,5,1 +changed,2,34,1041,931,385,694,53,7,1 +changed,2,35,955,897,374,684,54,4,0 +changed,2,36,1034,961,374,698,63,9,0 +changed,2,37,944,896,367,702,50,3,0 +changed,2,38,978,870,362,634,51,5,2 +changed,2,39,856,808,352,622,46,7,0 +changed,2,40,950,899,342,656,55,5,0 +changed,2,41,976,899,309,706,49,7,0 +changed,2,42,915,829,283,634,54,9,0 +changed,2,43,880,835,274,656,48,3,0 +changed,2,44,909,764,267,572,48,4,1 +changed,2,45,900,857,267,636,48,4,1 +changed,2,46,829,779,259,582,48,3,0 +changed,2,47,780,739,251,576,46,4,0 +changed,2,48,853,777,240,564,43,4,0 +changed,2,49,857,779,235,572,44,6,1 +changed,2,50,873,699,237,549,45,4,0 +changed,2,51,834,760,245,598,52,4,0 +changed,2,52,922,822,239,584,52,4,1 +changed,2,53,871,779,229,590,55,4,0 +changed,2,54,848,755,221,569,42,4,0 +changed,2,55,781,714,213,556,45,4,1 +changed,2,56,848,771,203,553,41,6,0 +changed,2,57,903,732,200,556,43,4,1 +changed,2,58,857,773,193,562,42,8,0 +changed,2,59,884,727,190,547,44,3,0 +changed,2,60,6234,817,696,473,169,3,1 +changed,2,61,16224,16124,666,15642,150,4,0 +changed,2,62,11710,11664,630,11276,136,3,0 +changed,2,63,9978,9848,580,9424,146,4,1 +changed,2,64,8177,8112,528,7735,135,3,1 +changed,2,65,5647,5574,506,5236,133,4,0 +changed,2,66,4552,4472,489,4161,116,7,0 +changed,2,67,3769,3699,459,3373,121,4,0 +changed,2,68,3011,2930,420,2665,111,4,0 +changed,2,69,2555,2456,397,2145,99,5,2 +changed,2,70,2290,2090,400,1826,95,4,1 +changed,2,71,2207,2108,454,1773,112,8,0 +changed,2,72,1937,1838,468,1599,105,6,0 +changed,2,73,1850,1749,473,1527,95,5,0 +changed,2,74,1823,1723,475,1433,91,16,1 +changed,2,75,1656,1552,486,1321,98,9,1 +changed,2,76,1559,1471,480,1254,86,4,0 +changed,2,77,1591,1398,473,1173,97,4,0 +changed,2,78,1459,1366,470,1109,97,4,0 +changed,2,79,1486,1388,483,1176,81,5,1 +changed,2,80,1551,1454,481,1168,93,14,0 +changed,2,81,1513,1418,490,1182,92,7,1 +changed,2,82,1552,1457,532,1175,83,5,1 +changed,2,83,1577,1470,566,1170,91,5,1 +changed,2,84,1570,1520,587,1267,78,3,0 +changed,2,85,1489,1393,587,1087,86,9,0 +changed,2,86,1516,1431,583,1080,84,4,1 +changed,2,87,2716,2648,572,1072,89,6,1 +changed,2,88,1506,1444,568,1093,87,13,1 +changed,2,89,1414,1245,565,1027,87,5,0 +changed,2,90,1351,1247,554,1020,88,4,1 +changed,2,91,1347,1244,547,1033,77,4,1 +changed,2,92,1273,1225,547,1030,80,4,0 +changed,2,93,1330,1246,533,1033,76,15,0 +changed,2,94,1265,1170,530,970,76,4,1 +changed,2,95,1339,1239,564,1016,75,5,0 +changed,2,96,1429,1202,582,989,86,4,1 +changed,2,97,1327,1271,561,1034,83,5,0 +changed,2,98,1268,1199,545,957,77,4,1 +changed,2,99,1308,1253,537,938,81,5,0 +changed,2,100,1304,1193,539,934,78,5,0 +changed,2,101,1241,1160,534,941,82,6,0 +changed,2,102,1201,1139,533,922,74,5,0 +changed,2,103,1359,1133,524,876,72,5,0 +changed,2,104,1289,1208,505,935,86,9,0 +changed,2,105,1277,1191,488,890,83,6,0 +changed,2,106,1185,1095,483,874,76,5,0 +changed,2,107,1226,1119,482,856,71,5,1 +changed,2,108,1161,1112,472,924,72,9,0 +changed,2,109,1311,1092,447,881,69,4,0 +changed,2,110,1252,1159,434,853,82,9,1 +changed,2,111,1582,1106,420,828,72,6,0 +changed,2,112,1237,1177,406,911,69,9,1 +changed,2,113,1225,1112,386,835,79,4,1 +changed,2,114,1103,1027,369,802,64,4,1 +changed,2,115,1131,1070,358,796,75,4,0 +changed,2,116,1163,933,347,751,69,4,0 +changed,2,117,1252,1142,342,857,77,9,0 +changed,2,118,1058,952,333,747,70,11,1 +changed,2,119,1132,974,332,751,69,4,1 +changed,2,120,6553,988,840,659,185,4,0 +changed,2,121,16807,16741,811,16123,185,5,0 +changed,2,122,12561,12394,772,11861,162,7,0 +changed,2,123,9958,9919,720,9498,162,3,0 +changed,2,124,7550,7500,655,7080,156,9,0 +changed,2,125,5920,5842,614,5393,154,5,0 +changed,2,126,5037,4958,581,4533,150,4,0 +changed,2,127,3834,3788,579,3382,127,3,0 +changed,2,128,3193,3136,529,2752,141,7,0 +changed,2,129,2746,2582,514,2311,128,4,0 +changed,2,130,2570,2493,514,2170,133,3,0 +changed,2,131,2309,2220,509,1903,122,3,1 +changed,2,132,2290,2212,507,1917,118,6,1 +changed,2,133,2002,1932,504,1665,115,6,0 +changed,2,134,1979,1906,497,1646,105,6,0 +changed,2,135,2060,1958,511,1695,123,10,0 +changed,2,136,2119,1904,537,1604,137,3,0 +changed,2,137,2073,1983,548,1678,121,5,0 +changed,2,138,1992,1908,552,1553,112,4,1 +changed,2,139,1942,1855,565,1584,105,8,1 +changed,2,140,1932,1841,560,1496,125,5,0 +changed,2,141,1848,1769,552,1481,110,7,1 +changed,2,142,1839,1760,557,1481,107,7,0 +changed,2,143,1907,1650,572,1417,106,4,0 +changed,2,144,1832,1750,582,1497,95,10,1 +changed,2,145,1739,1645,586,1371,117,4,0 +changed,2,146,1669,1619,588,1317,107,5,0 +changed,2,147,1652,1573,579,1282,104,4,0 +changed,2,148,1637,1571,590,1275,120,4,0 +changed,2,149,1715,1482,580,1249,96,4,1 +changed,2,150,1622,1523,571,1260,106,8,0 +changed,2,151,1646,1577,565,1289,109,7,0 +changed,2,152,1647,1574,570,1273,97,4,0 +changed,2,153,1690,1605,572,1237,115,8,1 +changed,2,154,1565,1485,561,1180,93,4,0 +changed,2,155,1649,1554,566,1230,106,8,1 +changed,2,156,1647,1446,565,1194,102,5,0 +changed,2,157,1523,1444,550,1168,99,14,0 +changed,2,158,1540,1449,554,1160,95,12,1 +changed,2,159,1571,1481,551,1146,93,10,0 +changed,2,160,1505,1399,540,1107,98,4,1 +changed,2,161,1516,1433,538,1079,99,4,1 +changed,2,162,1485,1277,539,1052,90,5,0 +changed,2,163,1434,1374,532,1090,90,6,0 +changed,2,164,1409,1353,524,1090,90,3,0 +changed,2,165,1521,1421,513,1053,101,5,0 +changed,2,166,1479,1392,492,1108,91,4,0 +changed,2,167,1384,1321,478,1030,88,11,0 +changed,2,168,1408,1308,478,1036,95,8,1 +changed,2,169,1392,1245,462,983,78,10,0 +changed,2,170,1428,1381,449,1097,95,11,0 +changed,2,171,1307,1210,447,987,90,7,1 +changed,2,172,1313,1221,446,980,89,9,1 +changed,2,173,1295,1202,434,958,89,6,2 +changed,2,174,1211,1174,424,951,79,4,0 +changed,2,175,1395,1207,435,964,82,7,2 +changed,2,176,1481,1392,430,1065,88,4,0 +changed,2,177,1307,1229,444,953,82,5,0 +changed,2,178,1277,1187,440,906,84,7,1 +changed,2,179,1291,1188,438,956,75,4,0 +changed,2,180,6374,1295,883,864,182,6,0 +changed,2,181,16478,16393,860,15774,177,4,0 +changed,2,182,12340,12135,804,11621,162,3,1 +changed,2,183,9694,9643,742,9189,160,7,0 +changed,2,184,7977,7497,696,7019,154,4,0 +changed,2,185,5981,5916,656,5496,152,6,0 +changed,2,186,4534,4484,625,4124,137,9,1 +changed,2,187,3485,3429,584,3083,135,4,1 +changed,2,188,2873,2762,553,2444,121,3,0 +changed,2,189,2702,2612,526,2278,124,5,0 +changed,2,190,2479,2384,510,2074,135,8,0 +changed,2,191,2335,2235,501,1960,127,4,1 +changed,2,192,2140,2057,488,1746,113,10,0 +changed,2,193,2007,1954,498,1700,117,3,1 +changed,2,194,1915,1856,504,1585,107,6,0 +changed,2,195,2024,1821,496,1554,117,3,0 +changed,2,196,1841,1748,480,1470,115,3,1 +changed,2,197,1768,1725,469,1462,107,6,0 +changed,2,198,1860,1763,477,1409,121,7,0 +changed,2,199,1737,1644,469,1365,109,5,1 +changed,2,200,1633,1563,461,1300,106,3,0 +changed,2,201,1762,1562,454,1183,104,3,0 +changed,2,202,1596,1493,447,1254,107,4,0 +changed,2,203,1487,1423,440,1176,100,4,0 +changed,2,204,1578,1486,431,1200,95,12,0 +changed,2,205,1581,1466,423,1163,105,4,2 +changed,2,206,1541,1434,404,1179,103,6,1 +changed,2,207,1587,1494,401,1156,94,9,0 +changed,2,208,1629,1454,419,1149,100,6,0 +changed,2,209,1463,1374,420,1133,90,6,1 +changed,2,210,1514,1447,416,1152,100,8,1 +changed,2,211,1492,1407,406,1149,100,8,0 +changed,2,212,1461,1370,410,1085,98,9,0 +changed,2,213,1416,1317,411,1071,97,4,0 +changed,2,214,1424,1339,406,1096,92,3,0 +changed,2,215,1485,1278,401,1053,97,3,0 +changed,2,216,1520,1427,389,1053,105,7,1 +changed,2,217,1312,1236,379,984,86,4,1 +changed,2,218,1337,1274,377,993,99,7,1 +changed,2,219,1281,1218,374,965,80,9,0 +changed,2,220,1443,1396,374,1086,90,4,0 +changed,2,221,1258,1170,366,951,89,15,1 +changed,2,222,1402,1186,363,942,84,4,1 +changed,2,223,1321,1221,357,986,99,4,0 +changed,2,224,1234,1198,355,970,80,8,1 +changed,2,225,1337,1246,357,978,86,9,0 +changed,2,226,1344,1258,363,938,93,8,1 +changed,2,227,1251,1162,367,949,94,5,0 +changed,2,228,1433,1204,355,901,82,3,1 +changed,2,229,1276,1185,350,973,87,4,0 +changed,2,230,1254,1158,345,915,86,6,1 +changed,2,231,1193,1144,345,945,82,4,0 +changed,2,232,1310,1221,340,937,85,16,0 +changed,2,233,1240,1140,339,919,86,12,1 +changed,2,234,1202,1125,331,890,75,4,0 +changed,2,235,1309,1081,331,856,81,3,0 +changed,2,236,1233,1144,325,904,88,4,0 +changed,2,237,1197,1101,314,880,81,10,0 +changed,2,238,1208,1110,294,871,81,10,1 +changed,2,239,1203,1051,290,828,73,3,1 +changed,3,0,6277,629,508,1,137,167,0 +changed,3,1,15464,15419,487,14909,100,3,0 +changed,3,2,11597,11548,455,11126,107,3,0 +changed,3,3,9863,9819,412,9432,107,7,0 +changed,3,4,7441,7384,359,7003,92,5,0 +changed,3,5,5298,5202,314,4938,98,4,0 +changed,3,6,4272,4192,274,3907,87,10,0 +changed,3,7,3003,2944,248,2629,88,8,0 +changed,3,8,2606,2544,242,2344,72,6,0 +changed,3,9,1952,1897,256,1671,66,17,0 +changed,3,10,1788,1715,271,1471,79,4,0 +changed,3,11,1669,1594,361,1381,75,12,1 +changed,3,12,1504,1460,372,1228,64,4,0 +changed,3,13,1376,1310,383,1096,72,7,0 +changed,3,14,1340,1285,391,1109,64,4,0 +changed,3,15,1249,1181,390,975,66,9,0 +changed,3,16,1267,1185,390,916,73,3,0 +changed,3,17,1186,1079,393,860,68,4,1 +changed,3,18,1163,1088,413,893,67,16,0 +changed,3,19,1223,1128,419,864,64,5,1 +changed,3,20,1104,1011,429,813,62,14,0 +changed,3,21,1138,1044,425,837,66,7,0 +changed,3,22,1131,1045,432,872,62,5,1 +changed,3,23,1131,1064,451,820,60,6,0 +changed,3,24,1165,1071,448,866,66,6,1 +changed,3,25,995,944,449,768,59,7,0 +changed,3,26,1097,996,443,786,59,4,0 +changed,3,27,1016,953,433,752,59,13,0 +changed,3,28,1035,944,434,725,58,13,0 +changed,3,29,1065,960,424,770,52,5,1 +changed,3,30,1031,904,416,708,59,14,0 +changed,3,31,1021,922,409,729,58,6,0 +changed,3,32,979,901,401,686,57,5,0 +changed,3,33,914,860,392,711,55,4,0 +changed,3,34,931,866,385,678,50,7,0 +changed,3,35,950,871,374,683,54,16,0 +changed,3,36,1021,911,374,686,52,6,1 +changed,3,37,918,872,367,684,51,6,0 +changed,3,38,1034,980,362,698,50,5,0 +changed,3,39,898,841,352,673,49,5,0 +changed,3,40,934,830,342,634,54,10,1 +changed,3,41,967,877,309,685,53,16,0 +changed,3,42,986,828,283,604,47,5,0 +changed,3,43,991,893,274,630,59,4,1 +changed,3,44,859,808,267,575,49,4,0 +changed,3,45,894,826,267,630,56,5,0 +changed,3,46,860,783,259,582,49,4,0 +changed,3,47,925,824,251,610,52,6,0 +changed,3,48,855,804,240,598,54,5,0 +changed,3,49,880,743,235,555,47,4,1 +changed,3,50,840,788,237,591,50,7,0 +changed,3,51,904,820,245,592,47,9,9 +changed,3,52,868,773,239,613,45,3,0 +changed,3,53,843,793,229,643,50,5,1 +changed,3,54,887,785,221,563,45,5,0 +changed,3,55,838,735,213,572,46,4,0 +changed,3,56,944,736,203,541,44,4,1 +changed,3,57,859,763,200,595,42,9,0 +changed,3,58,801,739,193,544,40,4,0 +changed,3,59,853,707,190,529,45,9,0 +changed,3,60,6364,780,696,474,174,5,0 +changed,3,61,16492,16447,666,15927,148,4,0 +changed,3,62,11915,11752,630,11349,144,3,0 +changed,3,63,10112,10061,580,9570,149,7,0 +changed,3,64,8160,8102,528,7693,135,7,0 +changed,3,65,5560,5499,506,5157,130,3,1 +changed,3,66,4551,4498,489,4137,114,6,1 +changed,3,67,3803,3727,459,3341,120,4,1 +changed,3,68,3128,2970,420,2661,104,5,0 +changed,3,69,2526,2479,397,2108,104,7,0 +changed,3,70,2165,2114,400,1810,110,4,0 +changed,3,71,2125,2041,454,1709,108,4,0 +changed,3,72,1933,1879,468,1621,109,7,0 +changed,3,73,1865,1773,473,1534,101,4,1 +changed,3,74,1863,1778,475,1451,89,5,0 +changed,3,75,1758,1626,486,1316,97,3,0 +changed,3,76,1545,1501,480,1262,93,5,0 +changed,3,77,1598,1515,473,1208,95,3,0 +changed,3,78,1510,1438,470,1149,95,5,0 +changed,3,79,1618,1554,483,1244,88,10,0 +changed,3,80,1572,1473,481,1169,97,4,0 +changed,3,81,1489,1333,490,1108,90,5,0 +changed,3,82,1489,1409,532,1167,90,5,0 +changed,3,83,1470,1422,566,1181,84,6,0 +changed,3,84,1507,1417,587,1118,81,5,0 +changed,3,85,1362,1272,587,1045,84,5,0 +changed,3,86,1323,1253,583,1030,83,5,0 +changed,3,87,1324,1267,572,1027,81,9,1 +changed,3,88,1351,1174,568,975,80,4,0 +changed,3,89,1235,1180,565,956,74,4,1 +changed,3,90,1440,1341,554,1019,81,12,0 +changed,3,91,1401,1309,547,1001,75,7,0 +changed,3,92,1330,1243,547,969,83,8,1 +changed,3,93,1354,1276,533,1010,76,8,0 +changed,3,94,1342,1260,530,969,74,9,0 +changed,3,95,1399,1211,564,970,77,4,0 +changed,3,96,1250,1207,582,1004,75,3,0 +changed,3,97,1316,1267,561,961,85,15,0 +changed,3,98,1293,1195,545,952,83,8,0 +changed,3,99,1231,1187,537,953,72,7,0 +changed,3,100,1251,1179,539,922,80,8,0 +changed,3,101,1302,1255,534,958,79,7,1 +changed,3,102,1343,1142,533,884,71,4,1 +changed,3,103,1180,1115,524,893,72,5,0 +changed,3,104,1227,1136,505,901,65,9,0 +changed,3,105,1208,1102,488,887,76,6,1 +changed,3,106,1165,1102,483,899,70,9,0 +changed,3,107,1123,1047,482,846,70,4,2 +changed,3,108,1207,1153,472,912,73,8,0 +changed,3,109,1390,1114,447,857,65,9,0 +changed,3,110,1163,1083,434,864,71,6,1 +changed,3,111,1516,1028,420,783,72,4,0 +changed,3,112,1081,1014,406,813,66,4,0 +changed,3,113,1141,1043,386,809,65,8,1 +changed,3,114,1109,1023,369,789,60,12,0 +changed,3,115,1125,1080,358,810,67,6,0 +changed,3,116,1202,991,347,733,73,5,1 +changed,3,117,1084,1001,342,770,68,13,1 +changed,3,118,1078,989,333,730,65,17,1 +changed,3,119,1065,942,332,735,71,3,1 +changed,3,120,6398,1035,840,678,195,4,0 +changed,3,121,16761,16683,811,15980,188,8,0 +changed,3,122,12132,11968,772,11514,158,3,1 +changed,3,123,10020,9967,720,9490,162,4,0 +changed,3,124,7479,7434,655,7021,150,6,0 +changed,3,125,5990,5931,614,5455,151,4,0 +changed,3,126,4931,4827,581,4412,151,7,1 +changed,3,127,3762,3710,579,3391,128,7,0 +changed,3,128,3209,3127,529,2768,136,6,1 +changed,3,129,2707,2545,514,2285,119,4,0 +changed,3,130,2521,2479,514,2179,130,3,1 +changed,3,131,2310,2270,509,1970,126,4,0 +changed,3,132,2236,2193,507,1875,121,8,0 +changed,3,133,2018,1969,504,1710,115,6,0 +changed,3,134,2211,2156,497,1824,111,9,0 +changed,3,135,2198,1980,511,1637,127,3,0 +changed,3,136,1970,1887,537,1619,135,4,1 +changed,3,137,2050,1978,548,1632,118,15,0 +changed,3,138,1878,1789,552,1524,125,13,0 +changed,3,139,1927,1882,565,1604,122,6,0 +changed,3,140,1913,1848,560,1503,117,7,1 +changed,3,141,1964,1756,552,1499,105,4,1 +changed,3,142,1794,1750,557,1499,115,8,0 +changed,3,143,1840,1767,572,1445,111,16,1 +changed,3,144,1732,1641,582,1407,99,4,0 +changed,3,145,1717,1618,586,1346,112,3,1 +changed,3,146,1649,1565,588,1288,101,6,0 +changed,3,147,1620,1542,579,1256,101,5,0 +changed,3,148,1811,1594,590,1328,105,5,1 +changed,3,149,1707,1642,580,1331,86,16,1 +changed,3,150,1614,1548,571,1211,117,3,1 +changed,3,151,1679,1575,565,1271,115,8,0 +changed,3,152,1614,1570,570,1257,98,7,0 +changed,3,153,1692,1598,572,1258,101,8,0 +changed,3,154,1585,1426,561,1138,93,4,0 +changed,3,155,1590,1507,566,1176,104,3,0 +changed,3,156,1531,1444,565,1174,107,3,1 +changed,3,157,1446,1388,550,1166,93,6,0 +changed,3,158,1464,1406,554,1109,96,5,1 +changed,3,159,1436,1355,551,1119,99,4,0 +changed,3,160,1442,1356,540,1096,93,4,1 +changed,3,161,1522,1304,538,1037,97,3,0 +changed,3,162,1421,1329,539,1054,92,4,1 +changed,3,163,1436,1389,532,1155,95,7,0 +changed,3,164,1468,1391,524,1139,93,14,0 +changed,3,165,1401,1318,513,1069,101,15,0 +changed,3,166,1440,1352,492,1042,91,7,1 +changed,3,167,1373,1230,478,988,89,5,0 +changed,3,168,1317,1252,478,1022,86,4,0 +changed,3,169,1416,1345,462,1034,87,8,1 +changed,3,170,1366,1262,449,1007,87,12,1 +changed,3,171,1341,1249,447,1027,90,5,0 +changed,3,172,1330,1286,446,1012,90,4,0 +changed,3,173,1321,1239,434,955,81,11,1 +changed,3,174,1382,1214,424,944,75,3,1 +changed,3,175,1430,1364,435,1088,91,7,1 +changed,3,176,1272,1211,430,968,88,4,0 +changed,3,177,1323,1234,444,940,83,15,1 +changed,3,178,1302,1205,440,942,76,10,0 +changed,3,179,1212,1117,438,887,71,3,0 +changed,3,180,6801,1236,883,846,181,4,0 +changed,3,181,16195,16095,860,15467,178,8,1 +changed,3,182,11951,11919,804,11476,156,3,0 +changed,3,183,9631,9571,742,9102,164,6,0 +changed,3,184,7733,7286,696,6925,151,4,0 +changed,3,185,5937,5899,656,5452,155,4,1 +changed,3,186,4742,4575,625,4186,141,4,0 +changed,3,187,3590,3519,584,3105,129,3,1 +changed,3,188,2920,2818,553,2478,134,4,0 +changed,3,189,2732,2650,526,2318,118,4,0 +changed,3,190,2417,2353,510,2077,132,3,0 +changed,3,191,2344,2244,501,1962,132,11,2 +changed,3,192,2143,2051,488,1744,114,4,0 +changed,3,193,2122,1888,498,1636,124,3,1 +changed,3,194,2034,1949,504,1632,105,8,1 +changed,3,195,1836,1790,496,1535,110,4,1 +changed,3,196,1884,1787,480,1436,118,8,1 +changed,3,197,1832,1765,469,1430,116,11,1 +changed,3,198,1796,1695,477,1444,109,4,0 +changed,3,199,1773,1678,469,1353,110,3,0 +changed,3,200,1750,1546,461,1281,105,4,0 +changed,3,201,1675,1576,454,1260,102,13,1 +changed,3,202,1553,1453,447,1214,101,11,0 +changed,3,203,1639,1546,440,1246,106,4,2 +changed,3,204,1635,1562,431,1232,94,13,0 +changed,3,205,1475,1382,423,1132,106,9,0 +changed,3,206,1584,1479,404,1187,95,5,1 +changed,3,207,1543,1351,401,1121,101,4,0 +changed,3,208,1541,1495,419,1239,105,7,0 +changed,3,209,1472,1421,420,1122,92,14,0 +changed,3,210,1532,1419,416,1148,100,9,1 +changed,3,211,1514,1439,406,1170,94,6,0 +changed,3,212,1431,1380,410,1152,99,4,0 +changed,3,213,1475,1250,411,1029,95,3,1 +changed,3,214,1399,1301,406,1070,88,16,1 +changed,3,215,1498,1380,401,1086,103,9,0 +changed,3,216,1413,1323,389,1043,92,7,0 +changed,3,217,1333,1265,379,997,89,4,0 +changed,3,218,1266,1209,377,980,93,12,0 +changed,3,219,1477,1265,374,987,84,3,0 +changed,3,220,1338,1287,374,1017,94,6,0 +changed,3,221,1309,1210,366,948,86,4,1 +changed,3,222,1366,1271,363,967,93,8,1 +changed,3,223,1254,1170,357,954,87,6,0 +changed,3,224,1339,1252,355,1002,86,7,0 +changed,3,225,1334,1175,357,963,82,4,1 +changed,3,226,1331,1239,363,971,93,4,0 +changed,3,227,1286,1185,367,963,81,7,0 +changed,3,228,1292,1243,355,997,77,5,1 +changed,3,229,1168,1077,350,884,75,8,1 +changed,3,230,1226,1133,345,926,82,9,1 +changed,3,231,1202,1104,345,898,81,3,2 +changed,3,232,1292,1075,340,884,78,4,0 +changed,3,233,1226,1124,339,904,84,12,1 +changed,3,234,1246,1156,331,876,76,7,1 +changed,3,235,1249,1169,331,908,84,5,0 +changed,3,236,1207,1101,325,888,79,7,0 +changed,3,237,1162,1071,314,856,81,8,0 +changed,3,238,1409,1151,294,871,71,4,0 +changed,3,239,1263,1153,290,908,70,5,0 diff --git a/Tools/Benchmarks/FlippedSpritesResults/summary.json b/Tools/Benchmarks/FlippedSpritesResults/summary.json new file mode 100644 index 0000000000..327eda7e2e --- /dev/null +++ b/Tools/Benchmarks/FlippedSpritesResults/summary.json @@ -0,0 +1,212 @@ +[ + { + "size": 12, + "unique": 1, + "baseline": { + "warm_median_ms": 22.355, + "pair_medians_ms": [ + 22.467, + 22.258, + 22.178 + ], + "cold_median_ms": 0.272, + "cold_ms": [ + 0.278, + 0.271, + 0.272 + ], + "pixels_hash": "12316631879379964747" + }, + "changed": { + "warm_median_ms": 15.843, + "pair_medians_ms": [ + 15.803, + 15.837, + 16.055 + ], + "cold_median_ms": 0.222, + "cold_ms": [ + 0.222, + 0.228, + 0.217 + ], + "pixels_hash": "12316631879379964747" + }, + "reduction_pct": 29.129948557369723 + }, + { + "size": 24, + "unique": 8, + "baseline": { + "warm_median_ms": 90.951, + "pair_medians_ms": [ + 90.741, + 90.858, + 95.023 + ], + "cold_median_ms": 0.858, + "cold_ms": [ + 0.822, + 0.858, + 0.874 + ], + "pixels_hash": "5164470368415242364" + }, + "changed": { + "warm_median_ms": 61.75, + "pair_medians_ms": [ + 61.658, + 61.964, + 61.702 + ], + "cold_median_ms": 0.674, + "cold_ms": [ + 0.697, + 0.674, + 0.666 + ], + "pixels_hash": "5164470368415242364" + }, + "reduction_pct": 32.106298996162764 + }, + { + "size": 64, + "unique": 8, + "baseline": { + "warm_median_ms": 484.79, + "pair_medians_ms": [ + 482.23, + 484.361, + 498.807 + ], + "cold_median_ms": 3.979, + "cold_ms": [ + 3.964, + 3.979, + 4.288 + ], + "pixels_hash": "7540584506724982554" + }, + "changed": { + "warm_median_ms": 331.36, + "pair_medians_ms": [ + 330.853, + 331.156, + 334.907 + ], + "cold_median_ms": 2.824, + "cold_ms": [ + 2.787, + 2.824, + 2.831 + ], + "pixels_hash": "7540584506724982554" + }, + "reduction_pct": 31.64875513108769 + }, + { + "size": 128, + "unique": 8, + "baseline": { + "warm_median_ms": 1593.83, + "pair_medians_ms": [ + 1588.78, + 1596.3, + 1601.39 + ], + "cold_median_ms": 12.586, + "cold_ms": [ + 12.586, + 12.416, + 12.634 + ], + "pixels_hash": "17320702199430413249" + }, + "changed": { + "warm_median_ms": 1028.64, + "pair_medians_ms": [ + 1019.36, + 1028.64, + 1053.47 + ], + "cold_median_ms": 7.945, + "cold_ms": [ + 8.038, + 7.945, + 7.803 + ], + "pixels_hash": "17320702199430413249" + }, + "reduction_pct": 35.46112195152556 + }, + { + "size": 24, + "unique": 512, + "baseline": { + "warm_median_ms": 88.733, + "pair_medians_ms": [ + 88.658, + 93.817, + 88.628 + ], + "cold_median_ms": 0.839, + "cold_ms": [ + 0.825, + 0.839, + 0.87 + ], + "pixels_hash": "12191707828478896987" + }, + "changed": { + "warm_median_ms": 66.646, + "pair_medians_ms": [ + 63.836, + 66.646, + 72.82 + ], + "cold_median_ms": 0.889, + "cold_ms": [ + 0.906, + 0.87, + 0.889 + ], + "pixels_hash": "12191707828478896987" + }, + "reduction_pct": 24.891528518138685 + }, + { + "size": 64, + "unique": 512, + "baseline": { + "warm_median_ms": 491.085, + "pair_medians_ms": [ + 482.648, + 496.972, + 491.085 + ], + "cold_median_ms": 4.054, + "cold_ms": [ + 3.949, + 4.072, + 4.054 + ], + "pixels_hash": "651891823647941672" + }, + "changed": { + "warm_median_ms": 346.401, + "pair_medians_ms": [ + 346.401, + 350.961, + 333.246 + ], + "cold_median_ms": 4.241, + "cold_ms": [ + 4.241, + 4.219, + 4.36 + ], + "pixels_hash": "651891823647941672" + }, + "reduction_pct": 29.462109410794458 + } +] diff --git a/Tools/Benchmarks/PerformanceStress.rte/Activities.ini b/Tools/Benchmarks/PerformanceStress.rte/Activities.ini new file mode 100644 index 0000000000..cff322fa4d --- /dev/null +++ b/Tools/Benchmarks/PerformanceStress.rte/Activities.ini @@ -0,0 +1,10 @@ +AddActivity = GAScripted + PresetName = Debris Performance Stress + Description = Fixed debris waves for local performance measurements. + TeamOfPlayer1 = 0 + MinTeamsRequired = 1 + SceneName = Grasslands + ScriptPath = PerformanceStress.rte/Stress.lua + LuaClassName = PerformanceStress + DefaultFogOfWar = 0 + DefaultDeployUnits = 0 diff --git a/Tools/Benchmarks/PerformanceStress.rte/Index.ini b/Tools/Benchmarks/PerformanceStress.rte/Index.ini new file mode 100644 index 0000000000..1ebfe00499 --- /dev/null +++ b/Tools/Benchmarks/PerformanceStress.rte/Index.ini @@ -0,0 +1,3 @@ +DataModule + ModuleName = Performance Stress + IncludeFile = PerformanceStress.rte/Activities.ini diff --git a/Tools/Benchmarks/PerformanceStress.rte/Stress.lua b/Tools/Benchmarks/PerformanceStress.rte/Stress.lua new file mode 100644 index 0000000000..be45eb81c2 --- /dev/null +++ b/Tools/Benchmarks/PerformanceStress.rte/Stress.lua @@ -0,0 +1,35 @@ +function PerformanceStress:StartActivity() + self.ActivityState = Activity.RUNNING + self.ticks = 0 + self.timer = Timer() + self.center = SceneMan:MovePointToGround(Vector(SceneMan.SceneWidth / 2, 0), 0, 3) + self.center.Y = self.center.Y - 100 + PerformanceMan.ShowPerformanceStats = true + print("PERF_START debris_waves") +end + +function PerformanceStress:UpdateActivity() + self.ticks = self.ticks + 1 + CameraMan:SetScrollTarget(self.center, 1, 0) + if self.ticks % 60 == 1 and self.ticks <= 541 then + for i = 1, 400 do + local gib = CreateMOSRotating("Gib Metal Grey Small A", "Base.rte") + gib.Pos = self.center + Vector((i * 17) % 120 - 60, (i * 23) % 80 - 40) + gib.Vel = Vector((i * 7) % 30 - 15, -((i * 11) % 20)) + gib.AngularVel = (i % 20) - 10 + gib.HFlipped = i % 2 == 0 + gib.Lifetime = 3000 + gib.GetsHitByMOs = true + MovableMan:AddParticle(gib) + end + local grenade = CreateTDExplosive("Frag Grenade", "Base.rte") + grenade.Pos = self.center + grenade:GibThis() + end + if self.ticks % 60 == 0 then + print("PERF_SAMPLE ticks=" .. self.ticks .. " real_ms=" .. self.timer.ElapsedRealTimeMS .. " particles=" .. MovableMan:GetParticleCount()) + end + if self.ticks == 600 then + print("PERF_DONE real_ms=" .. self.timer.ElapsedRealTimeMS) + end +end