Skip to content

Commit

Permalink
reduce binary size
Browse files Browse the repository at this point in the history
  • Loading branch information
brunocodutra committed Nov 4, 2024
1 parent 37e644d commit ac27530
Show file tree
Hide file tree
Showing 25 changed files with 373 additions and 366 deletions.
7 changes: 2 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,11 @@ criterion-macro = { version = "0.4.0", default-features = false }
proptest = { version = "1.5.0", default-features = false, features = ["std"] }
test-strategy = { version = "0.4.0", default-features = false }

[profile.release.package.ruzstd]
opt-level = 's'

[profile.release]
codegen-units = 1
lto = true
panic = "abort"
strip = "symbols"
lto = true
strip = true

[profile.dev]
opt-level = 3
Expand Down
37 changes: 11 additions & 26 deletions bin/main.rs
Original file line number Diff line number Diff line change
@@ -1,36 +1,21 @@
use futures::executor::{block_on, block_on_stream};
use futures::{channel::mpsc, prelude::*};
use futures::executor::block_on;
use futures::{channel::mpsc::unbounded, sink::unfold};
use lib::uci::Uci;
use std::io::{prelude::*, stdin, stdout, LineWriter};
use std::thread;
use std::io::{prelude::*, stdin, stdout};
use std::{future::ready, thread};

fn main() {
let (mut tx, input) = mpsc::channel(32);
let (output, rx) = mpsc::channel(32);
let (tx, rx) = unbounded();

thread::spawn(move || {
for item in stdin().lock().lines() {
match item {
Err(error) => return eprint!("{error}"),
Ok(line) => {
if let Err(error) = block_on(tx.send(line)) {
if error.is_disconnected() {
break;
}
}
}
for line in stdin().lock().lines() {
if tx.unbounded_send(line.unwrap()).is_err() {
break;
}
}
});

thread::spawn(move || {
let mut stdout = LineWriter::new(stdout().lock());
for line in block_on_stream(rx) {
if let Err(error) = writeln!(stdout, "{line}") {
return eprint!("{error}");
}
}
});

block_on(Uci::new(input, output).run()).ok();
let mut stdout = stdout().lock();
let output = unfold((), |_, line: String| ready(writeln!(stdout, "{line}")));
block_on(Uci::new(rx, output).run()).unwrap();
}
6 changes: 3 additions & 3 deletions lib/chess/bitboard.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::chess::{File, Perspective, Rank, Square};
use crate::util::{Assume, Integer};
use derive_more::{Debug, *};
use std::fmt::{self, Write};
use std::fmt::{self, Formatter, Write};
use std::{cell::SyncUnsafeCell, mem::MaybeUninit};

/// A set of squares on a chess board.
Expand All @@ -26,9 +26,9 @@ use std::{cell::SyncUnsafeCell, mem::MaybeUninit};
#[repr(transparent)]
pub struct Bitboard(u64);

impl fmt::Debug for Bitboard {
impl Debug for Bitboard {
#[coverage(off)]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.write_char('\n')?;
for rank in Rank::iter().rev() {
for file in File::iter() {
Expand Down
37 changes: 22 additions & 15 deletions lib/chess/board.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use crate::{chess::*, util::Integer};
use arrayvec::ArrayString;
use crate::chess::*;
use crate::util::{Assume, Integer};
use derive_more::{Debug, Display, Error};
use std::fmt::{self, Write};
use std::{ops::Index, str::FromStr};
use std::fmt::{self, Formatter, Write};
use std::str::{self, FromStr};
use std::{io::Write as _, ops::Index};

/// The chess board.
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
Expand Down Expand Up @@ -163,26 +164,31 @@ impl Index<Square> for Board {
}

impl Display for Board {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
let mut skip = 0;
for sq in Square::iter().map(|sq| sq.flip()) {
let mut buffer = ArrayString::<2>::new();
let mut buffer = [b'\0'; 2];

match self[sq] {
None => skip += 1,
Some(p) => write!(buffer, "{}", p)?,
if sq.file() == File::H {
buffer[0] = if sq.rank() == Rank::First { b' ' } else { b'/' };
}

if sq.file() == File::H {
buffer.push(if sq.rank() == Rank::First { ' ' } else { '/' });
match self[sq] {
None => skip += 1,
Some(p) => {
buffer[1] = buffer[0];
write!(&mut buffer[..1], "{p}").assume()
}
}

if !buffer.is_empty() && skip > 0 {
write!(f, "{}", skip)?;
if skip > 0 && buffer != [b'\0'; 2] {
write!(f, "{skip}")?;
skip = 0;
}

f.write_str(&buffer)?;
for b in buffer.into_iter().take_while(|&b| b != b'\0') {
f.write_char(b.into())?;
}
}

match self.turn {
Expand All @@ -197,7 +203,7 @@ impl Display for Board {
}

if let Some(ep) = self.en_passant {
write!(f, "{} ", ep)?;
write!(f, "{ep} ")?;
} else {
f.write_str("- ")?;
}
Expand Down Expand Up @@ -230,6 +236,7 @@ pub enum ParseFenError {
impl FromStr for Board {
type Err = ParseFenError;

#[inline(always)]
fn from_str(s: &str) -> Result<Self, Self::Err> {
let fields: Vec<_> = s.split(' ').collect();
let [board, turn, castles, en_passant, halfmoves, fullmoves] = &fields[..] else {
Expand Down
12 changes: 7 additions & 5 deletions lib/chess/castles.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use crate::chess::{Color, Perspective, Piece, Role, Square};
use crate::util::{Bits, Integer};
use derive_more::{Debug, *};
use std::{cell::SyncUnsafeCell, fmt, mem::MaybeUninit, str::FromStr};
use std::fmt::{self, Formatter};
use std::{cell::SyncUnsafeCell, mem::MaybeUninit, str::FromStr};

/// The castling rights in a chess [`Position`][`crate::chess::Position`].
#[derive(
Expand Down Expand Up @@ -107,15 +108,15 @@ impl From<Square> for Castles {
}
}

impl fmt::Display for Castles {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
impl Display for Castles {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
for side in Color::iter() {
if self.has_short(side) {
fmt::Display::fmt(&Piece::new(Role::King, side), f)?;
Display::fmt(&Piece::new(Role::King, side), f)?;
}

if self.has_long(side) {
fmt::Display::fmt(&Piece::new(Role::Queen, side), f)?;
Display::fmt(&Piece::new(Role::Queen, side), f)?;
}
}

Expand All @@ -131,6 +132,7 @@ pub struct ParseCastlesError;
impl FromStr for Castles {
type Err = ParseCastlesError;

#[inline(always)]
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut castles = Castles::none();

Expand Down
42 changes: 17 additions & 25 deletions lib/chess/file.rs
Original file line number Diff line number Diff line change
@@ -1,28 +1,21 @@
use crate::chess::{Bitboard, Mirror};
use crate::util::Integer;
use derive_more::{Display, Error};
use std::fmt::{self, Formatter, Write};
use std::{ops::Sub, str::FromStr};

/// A column on the chess board.
#[derive(Debug, Display, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[cfg_attr(test, derive(test_strategy::Arbitrary))]
#[repr(i8)]
pub enum File {
#[display("a")]
A,
#[display("b")]
B,
#[display("c")]
C,
#[display("d")]
D,
#[display("e")]
E,
#[display("f")]
F,
#[display("g")]
G,
#[display("h")]
H,
}

Expand Down Expand Up @@ -57,30 +50,29 @@ impl Sub for File {
}
}

impl Display for File {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.write_char((b'a' + self.cast::<u8>()).into())
}
}

/// The reason why parsing [`File`] failed.
#[derive(Debug, Display, Clone, Eq, PartialEq, Error)]
#[display(
"failed to parse file, expected letter in the range `({}..={})`",
File::A,
File::H
)]
#[display("failed to parse file")]
pub struct ParseFileError;

impl FromStr for File {
type Err = ParseFileError;

#[inline(always)]
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"a" => Ok(File::A),
"b" => Ok(File::B),
"c" => Ok(File::C),
"d" => Ok(File::D),
"e" => Ok(File::E),
"f" => Ok(File::F),
"g" => Ok(File::G),
"h" => Ok(File::H),
_ => Err(ParseFileError),
}
let [c] = s.as_bytes() else {
return Err(ParseFileError);
};

c.checked_sub(b'a')
.and_then(Integer::convert)
.ok_or(ParseFileError)
}
}

Expand Down
3 changes: 3 additions & 0 deletions lib/chess/magic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,17 @@ use crate::chess::{Bitboard, Square};
pub struct Magic(Bitboard, u64, usize);

impl Magic {
#[inline(always)]
pub fn mask(&self) -> Bitboard {
self.0
}

#[inline(always)]
pub fn factor(&self) -> u64 {
self.1
}

#[inline(always)]
pub fn offset(&self) -> usize {
self.2
}
Expand Down
18 changes: 9 additions & 9 deletions lib/chess/move.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::chess::{Bitboard, Perspective, Piece, Rank, Role, Square, Squares};
use crate::util::{Assume, Binary, Bits, Integer};
use std::fmt::{self, Write};
use std::fmt::{self, Debug, Display, Formatter, Write};
use std::{num::NonZeroU16, ops::RangeBounds};

/// A chess move.
Expand Down Expand Up @@ -135,10 +135,10 @@ impl Move {
}
}

impl fmt::Debug for Move {
impl Debug for Move {
#[coverage(off)]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self, f)?;
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
Display::fmt(&self, f)?;

if self.is_en_passant() {
f.write_char('^')?;
Expand All @@ -152,13 +152,13 @@ impl fmt::Debug for Move {
}
}

impl fmt::Display for Move {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self.whence(), f)?;
fmt::Display::fmt(&self.whither(), f)?;
impl Display for Move {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
Display::fmt(&self.whence(), f)?;
Display::fmt(&self.whither(), f)?;

if let Some(r) = self.promotion() {
fmt::Display::fmt(&r, f)?;
Display::fmt(&r, f)?;
}

Ok(())
Expand Down
3 changes: 3 additions & 0 deletions lib/chess/outcome.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,19 @@ impl Outcome {
/// Whether the outcome is a [draw] and neither side has won.
///
/// [draw]: https://www.chessprogramming.org/Draw
#[inline(always)]
pub fn is_draw(&self) -> bool {
!self.is_decisive()
}

/// Whether the outcome is a decisive and one of the sides has won.
#[inline(always)]
pub fn is_decisive(&self) -> bool {
matches!(self, Outcome::Checkmate(_))
}

/// The winning side, if the outcome is [decisive](`Self::is_decisive`).
#[inline(always)]
pub fn winner(&self) -> Option<Color> {
match *self {
Outcome::Checkmate(c) => Some(c),
Expand Down
Loading

0 comments on commit ac27530

Please sign in to comment.